shell: handle $((NUM++...) like bash does. Closes 10706
[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 PIPE_BUF
259 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
260 #endif
261
262 #if !BB_MMU
263 # error "Do not even bother, ash will not run on NOMMU machine"
264 #endif
265
266
267 /* ============ Hash table sizes. Configurable. */
268
269 #define VTABSIZE 39
270 #define ATABSIZE 39
271 #define CMDTABLESIZE 31         /* should be prime */
272
273
274 /* ============ Shell options */
275
276 static const char *const optletters_optnames[] = {
277         "e"   "errexit",
278         "f"   "noglob",
279         "I"   "ignoreeof",
280         "i"   "interactive",
281         "m"   "monitor",
282         "n"   "noexec",
283         "s"   "stdin",
284         "x"   "xtrace",
285         "v"   "verbose",
286         "C"   "noclobber",
287         "a"   "allexport",
288         "b"   "notify",
289         "u"   "nounset",
290         "\0"  "vi"
291 #if BASH_PIPEFAIL
292         ,"\0"  "pipefail"
293 #endif
294 #if DEBUG
295         ,"\0"  "nolog"
296         ,"\0"  "debug"
297 #endif
298 };
299
300 #define optletters(n)  optletters_optnames[n][0]
301 #define optnames(n)   (optletters_optnames[n] + 1)
302
303 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
304
305
306 /* ============ Misc data */
307
308 #define msg_illnum "Illegal number: %s"
309
310 /*
311  * We enclose jmp_buf in a structure so that we can declare pointers to
312  * jump locations.  The global variable handler contains the location to
313  * jump to when an exception occurs, and the global variable exception_type
314  * contains a code identifying the exception.  To implement nested
315  * exception handlers, the user should save the value of handler on entry
316  * to an inner scope, set handler to point to a jmploc structure for the
317  * inner scope, and restore handler on exit from the scope.
318  */
319 struct jmploc {
320         jmp_buf loc;
321 };
322
323 struct globals_misc {
324         uint8_t exitstatus;     /* exit status of last command */
325         uint8_t back_exitstatus;/* exit status of backquoted command */
326         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
327         int rootpid;            /* pid of main shell */
328         /* shell level: 0 for the main shell, 1 for its children, and so on */
329         int shlvl;
330 #define rootshell (!shlvl)
331         int errlinno;
332
333         char *minusc;  /* argument to -c option */
334
335         char *curdir; // = nullstr;     /* current working directory */
336         char *physdir; // = nullstr;    /* physical working directory */
337
338         char *arg0; /* value of $0 */
339
340         struct jmploc *exception_handler;
341
342         volatile int suppress_int; /* counter */
343         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
344         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
345         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
346         smallint exception_type; /* kind of exception (0..5) */
347         /* exceptions */
348 #define EXINT 0         /* SIGINT received */
349 #define EXERROR 1       /* a generic error */
350 #define EXEXIT 4        /* exit the shell */
351
352         char nullstr[1];        /* zero length string */
353
354         char optlist[NOPTS];
355 #define eflag optlist[0]
356 #define fflag optlist[1]
357 #define Iflag optlist[2]
358 #define iflag optlist[3]
359 #define mflag optlist[4]
360 #define nflag optlist[5]
361 #define sflag optlist[6]
362 #define xflag optlist[7]
363 #define vflag optlist[8]
364 #define Cflag optlist[9]
365 #define aflag optlist[10]
366 #define bflag optlist[11]
367 #define uflag optlist[12]
368 #define viflag optlist[13]
369 #if BASH_PIPEFAIL
370 # define pipefail optlist[14]
371 #else
372 # define pipefail 0
373 #endif
374 #if DEBUG
375 # define nolog optlist[14 + BASH_PIPEFAIL]
376 # define debug optlist[15 + BASH_PIPEFAIL]
377 #endif
378
379         /* trap handler commands */
380         /*
381          * Sigmode records the current value of the signal handlers for the various
382          * modes.  A value of zero means that the current handler is not known.
383          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
384          */
385         char sigmode[NSIG - 1];
386 #define S_DFL      1            /* default signal handling (SIG_DFL) */
387 #define S_CATCH    2            /* signal is caught */
388 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
389 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
390
391         /* indicates specified signal received */
392         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
393         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
394         char *trap[NSIG];
395         char **trap_ptr;        /* used only by "trap hack" */
396
397         /* Rarely referenced stuff */
398 #if ENABLE_ASH_RANDOM_SUPPORT
399         random_t random_gen;
400 #endif
401         pid_t backgndpid;        /* pid of last background process */
402 };
403 extern struct globals_misc *const ash_ptr_to_globals_misc;
404 #define G_misc (*ash_ptr_to_globals_misc)
405 #define exitstatus        (G_misc.exitstatus )
406 #define back_exitstatus   (G_misc.back_exitstatus )
407 #define job_warning       (G_misc.job_warning)
408 #define rootpid     (G_misc.rootpid    )
409 #define shlvl       (G_misc.shlvl      )
410 #define errlinno    (G_misc.errlinno   )
411 #define minusc      (G_misc.minusc     )
412 #define curdir      (G_misc.curdir     )
413 #define physdir     (G_misc.physdir    )
414 #define arg0        (G_misc.arg0       )
415 #define exception_handler (G_misc.exception_handler)
416 #define exception_type    (G_misc.exception_type   )
417 #define suppress_int      (G_misc.suppress_int     )
418 #define pending_int       (G_misc.pending_int      )
419 #define got_sigchld       (G_misc.got_sigchld      )
420 #define pending_sig       (G_misc.pending_sig      )
421 #define nullstr     (G_misc.nullstr    )
422 #define optlist     (G_misc.optlist    )
423 #define sigmode     (G_misc.sigmode    )
424 #define gotsig      (G_misc.gotsig     )
425 #define may_have_traps    (G_misc.may_have_traps   )
426 #define trap        (G_misc.trap       )
427 #define trap_ptr    (G_misc.trap_ptr   )
428 #define random_gen  (G_misc.random_gen )
429 #define backgndpid  (G_misc.backgndpid )
430 #define INIT_G_misc() do { \
431         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
432         barrier(); \
433         curdir = nullstr; \
434         physdir = nullstr; \
435         trap_ptr = trap; \
436 } while (0)
437
438
439 /* ============ DEBUG */
440 #if DEBUG
441 static void trace_printf(const char *fmt, ...);
442 static void trace_vprintf(const char *fmt, va_list va);
443 # define TRACE(param)    trace_printf param
444 # define TRACEV(param)   trace_vprintf param
445 # define close(fd) do { \
446         int dfd = (fd); \
447         if (close(dfd) < 0) \
448                 bb_error_msg("bug on %d: closing %d(0x%x)", \
449                         __LINE__, dfd, dfd); \
450 } while (0)
451 #else
452 # define TRACE(param)
453 # define TRACEV(param)
454 #endif
455
456
457 /* ============ Utility functions */
458 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
459 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
460
461 static int
462 isdigit_str9(const char *str)
463 {
464         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
465         while (--maxlen && isdigit(*str))
466                 str++;
467         return (*str == '\0');
468 }
469
470 static const char *
471 var_end(const char *var)
472 {
473         while (*var)
474                 if (*var++ == '=')
475                         break;
476         return var;
477 }
478
479
480 /* ============ Interrupts / exceptions */
481
482 static void exitshell(void) NORETURN;
483
484 /*
485  * These macros allow the user to suspend the handling of interrupt signals
486  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
487  * much more efficient and portable.  (But hacking the kernel is so much
488  * more fun than worrying about efficiency and portability. :-))
489  */
490 #if DEBUG_INTONOFF
491 # define INT_OFF do { \
492         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
493         suppress_int++; \
494         barrier(); \
495 } while (0)
496 #else
497 # define INT_OFF do { \
498         suppress_int++; \
499         barrier(); \
500 } while (0)
501 #endif
502
503 /*
504  * Called to raise an exception.  Since C doesn't include exceptions, we
505  * just do a longjmp to the exception handler.  The type of exception is
506  * stored in the global variable "exception_type".
507  */
508 static void raise_exception(int) NORETURN;
509 static void
510 raise_exception(int e)
511 {
512 #if DEBUG
513         if (exception_handler == NULL)
514                 abort();
515 #endif
516         INT_OFF;
517         exception_type = e;
518         longjmp(exception_handler->loc, 1);
519 }
520 #if DEBUG
521 #define raise_exception(e) do { \
522         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
523         raise_exception(e); \
524 } while (0)
525 #endif
526
527 /*
528  * Called when a SIGINT is received.  (If the user specifies
529  * that SIGINT is to be trapped or ignored using the trap builtin, then
530  * this routine is not called.)  Suppressint is nonzero when interrupts
531  * are held using the INT_OFF macro.  (The test for iflag is just
532  * defensive programming.)
533  */
534 static void raise_interrupt(void) NORETURN;
535 static void
536 raise_interrupt(void)
537 {
538         pending_int = 0;
539         /* Signal is not automatically unmasked after it is raised,
540          * do it ourself - unmask all signals */
541         sigprocmask_allsigs(SIG_UNBLOCK);
542         /* pending_sig = 0; - now done in signal_handler() */
543
544         if (!(rootshell && iflag)) {
545                 /* Kill ourself with SIGINT */
546                 signal(SIGINT, SIG_DFL);
547                 raise(SIGINT);
548         }
549         /* bash: ^C even on empty command line sets $? */
550         exitstatus = SIGINT + 128;
551         raise_exception(EXINT);
552         /* NOTREACHED */
553 }
554 #if DEBUG
555 #define raise_interrupt() do { \
556         TRACE(("raising interrupt on line %d\n", __LINE__)); \
557         raise_interrupt(); \
558 } while (0)
559 #endif
560
561 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
562 int_on(void)
563 {
564         barrier();
565         if (--suppress_int == 0 && pending_int) {
566                 raise_interrupt();
567         }
568 }
569 #if DEBUG_INTONOFF
570 # define INT_ON do { \
571         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
572         int_on(); \
573 } while (0)
574 #else
575 # define INT_ON int_on()
576 #endif
577 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
578 force_int_on(void)
579 {
580         barrier();
581         suppress_int = 0;
582         if (pending_int)
583                 raise_interrupt();
584 }
585 #define FORCE_INT_ON force_int_on()
586
587 #define SAVE_INT(v) ((v) = suppress_int)
588
589 #define RESTORE_INT(v) do { \
590         barrier(); \
591         suppress_int = (v); \
592         if (suppress_int == 0 && pending_int) \
593                 raise_interrupt(); \
594 } while (0)
595
596
597 /* ============ Stdout/stderr output */
598
599 static void
600 outstr(const char *p, FILE *file)
601 {
602         INT_OFF;
603         fputs(p, file);
604         INT_ON;
605 }
606
607 static void
608 flush_stdout_stderr(void)
609 {
610         INT_OFF;
611         fflush_all();
612         INT_ON;
613 }
614
615 /* Was called outcslow(c,FILE*), but c was always '\n' */
616 static void
617 newline_and_flush(FILE *dest)
618 {
619         INT_OFF;
620         putc('\n', dest);
621         fflush(dest);
622         INT_ON;
623 }
624
625 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
626 static int
627 out1fmt(const char *fmt, ...)
628 {
629         va_list ap;
630         int r;
631
632         INT_OFF;
633         va_start(ap, fmt);
634         r = vprintf(fmt, ap);
635         va_end(ap);
636         INT_ON;
637         return r;
638 }
639
640 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
641 static int
642 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
643 {
644         va_list ap;
645         int ret;
646
647         INT_OFF;
648         va_start(ap, fmt);
649         ret = vsnprintf(outbuf, length, fmt, ap);
650         va_end(ap);
651         INT_ON;
652         return ret;
653 }
654
655 static void
656 out1str(const char *p)
657 {
658         outstr(p, stdout);
659 }
660
661 static void
662 out2str(const char *p)
663 {
664         outstr(p, stderr);
665         flush_stdout_stderr();
666 }
667
668
669 /* ============ Parser structures */
670
671 /* control characters in argument strings */
672 #define CTL_FIRST CTLESC
673 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
674 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
675 #define CTLENDVAR    ((unsigned char)'\203')
676 #define CTLBACKQ     ((unsigned char)'\204')
677 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
678 #define CTLENDARI    ((unsigned char)'\207')
679 #define CTLQUOTEMARK ((unsigned char)'\210')
680 #define CTL_LAST CTLQUOTEMARK
681
682 /* variable substitution byte (follows CTLVAR) */
683 #define VSTYPE  0x0f            /* type of variable substitution */
684 #define VSNUL   0x10            /* colon--treat the empty string as unset */
685
686 /* values of VSTYPE field */
687 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
688 #define VSMINUS         0x2     /* ${var-text} */
689 #define VSPLUS          0x3     /* ${var+text} */
690 #define VSQUESTION      0x4     /* ${var?message} */
691 #define VSASSIGN        0x5     /* ${var=text} */
692 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
693 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
694 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
695 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
696 #define VSLENGTH        0xa     /* ${#var} */
697 #if BASH_SUBSTR
698 #define VSSUBSTR        0xc     /* ${var:position:length} */
699 #endif
700 #if BASH_PATTERN_SUBST
701 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
702 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
703 #endif
704
705 static const char dolatstr[] ALIGN1 = {
706         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
707 };
708 #define DOLATSTRLEN 6
709
710 #define NCMD      0
711 #define NPIPE     1
712 #define NREDIR    2
713 #define NBACKGND  3
714 #define NSUBSHELL 4
715 #define NAND      5
716 #define NOR       6
717 #define NSEMI     7
718 #define NIF       8
719 #define NWHILE    9
720 #define NUNTIL   10
721 #define NFOR     11
722 #define NCASE    12
723 #define NCLIST   13
724 #define NDEFUN   14
725 #define NARG     15
726 #define NTO      16
727 #if BASH_REDIR_OUTPUT
728 #define NTO2     17
729 #endif
730 #define NCLOBBER 18
731 #define NFROM    19
732 #define NFROMTO  20
733 #define NAPPEND  21
734 #define NTOFD    22
735 #define NFROMFD  23
736 #define NHERE    24
737 #define NXHERE   25
738 #define NNOT     26
739 #define N_NUMBER 27
740
741 union node;
742
743 struct ncmd {
744         smallint type; /* Nxxxx */
745         int linno;
746         union node *assign;
747         union node *args;
748         union node *redirect;
749 };
750
751 struct npipe {
752         smallint type;
753         smallint pipe_backgnd;
754         struct nodelist *cmdlist;
755 };
756
757 struct nredir {
758         smallint type;
759         int linno;
760         union node *n;
761         union node *redirect;
762 };
763
764 struct nbinary {
765         smallint type;
766         union node *ch1;
767         union node *ch2;
768 };
769
770 struct nif {
771         smallint type;
772         union node *test;
773         union node *ifpart;
774         union node *elsepart;
775 };
776
777 struct nfor {
778         smallint type;
779         int linno;
780         union node *args;
781         union node *body;
782         char *var;
783 };
784
785 struct ncase {
786         smallint type;
787         int linno;
788         union node *expr;
789         union node *cases;
790 };
791
792 struct nclist {
793         smallint type;
794         union node *next;
795         union node *pattern;
796         union node *body;
797 };
798
799 struct ndefun {
800         smallint type;
801         int linno;
802         char *text;
803         union node *body;
804 };
805
806 struct narg {
807         smallint type;
808         union node *next;
809         char *text;
810         struct nodelist *backquote;
811 };
812
813 /* nfile and ndup layout must match!
814  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
815  * that it is actually NTO2 (>&file), and change its type.
816  */
817 struct nfile {
818         smallint type;
819         union node *next;
820         int fd;
821         int _unused_dupfd;
822         union node *fname;
823         char *expfname;
824 };
825
826 struct ndup {
827         smallint type;
828         union node *next;
829         int fd;
830         int dupfd;
831         union node *vname;
832         char *_unused_expfname;
833 };
834
835 struct nhere {
836         smallint type;
837         union node *next;
838         int fd;
839         union node *doc;
840 };
841
842 struct nnot {
843         smallint type;
844         union node *com;
845 };
846
847 union node {
848         smallint type;
849         struct ncmd ncmd;
850         struct npipe npipe;
851         struct nredir nredir;
852         struct nbinary nbinary;
853         struct nif nif;
854         struct nfor nfor;
855         struct ncase ncase;
856         struct nclist nclist;
857         struct ndefun ndefun;
858         struct narg narg;
859         struct nfile nfile;
860         struct ndup ndup;
861         struct nhere nhere;
862         struct nnot nnot;
863 };
864
865 /*
866  * NODE_EOF is returned by parsecmd when it encounters an end of file.
867  * It must be distinct from NULL.
868  */
869 #define NODE_EOF ((union node *) -1L)
870
871 struct nodelist {
872         struct nodelist *next;
873         union node *n;
874 };
875
876 struct funcnode {
877         int count;
878         union node n;
879 };
880
881 /*
882  * Free a parse tree.
883  */
884 static void
885 freefunc(struct funcnode *f)
886 {
887         if (f && --f->count < 0)
888                 free(f);
889 }
890
891
892 /* ============ Debugging output */
893
894 #if DEBUG
895
896 static FILE *tracefile;
897
898 static void
899 trace_printf(const char *fmt, ...)
900 {
901         va_list va;
902
903         if (debug != 1)
904                 return;
905         if (DEBUG_TIME)
906                 fprintf(tracefile, "%u ", (int) time(NULL));
907         if (DEBUG_PID)
908                 fprintf(tracefile, "[%u] ", (int) getpid());
909         if (DEBUG_SIG)
910                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
911         va_start(va, fmt);
912         vfprintf(tracefile, fmt, va);
913         va_end(va);
914 }
915
916 static void
917 trace_vprintf(const char *fmt, va_list va)
918 {
919         if (debug != 1)
920                 return;
921         vfprintf(tracefile, fmt, va);
922         fprintf(tracefile, "\n");
923 }
924
925 static void
926 trace_puts(const char *s)
927 {
928         if (debug != 1)
929                 return;
930         fputs(s, tracefile);
931 }
932
933 static void
934 trace_puts_quoted(char *s)
935 {
936         char *p;
937         char c;
938
939         if (debug != 1)
940                 return;
941         putc('"', tracefile);
942         for (p = s; *p; p++) {
943                 switch ((unsigned char)*p) {
944                 case '\n': c = 'n'; goto backslash;
945                 case '\t': c = 't'; goto backslash;
946                 case '\r': c = 'r'; goto backslash;
947                 case '\"': c = '\"'; goto backslash;
948                 case '\\': c = '\\'; goto backslash;
949                 case CTLESC: c = 'e'; goto backslash;
950                 case CTLVAR: c = 'v'; goto backslash;
951                 case CTLBACKQ: c = 'q'; goto backslash;
952  backslash:
953                         putc('\\', tracefile);
954                         putc(c, tracefile);
955                         break;
956                 default:
957                         if (*p >= ' ' && *p <= '~')
958                                 putc(*p, tracefile);
959                         else {
960                                 putc('\\', tracefile);
961                                 putc((*p >> 6) & 03, tracefile);
962                                 putc((*p >> 3) & 07, tracefile);
963                                 putc(*p & 07, tracefile);
964                         }
965                         break;
966                 }
967         }
968         putc('"', tracefile);
969 }
970
971 static void
972 trace_puts_args(char **ap)
973 {
974         if (debug != 1)
975                 return;
976         if (!*ap)
977                 return;
978         while (1) {
979                 trace_puts_quoted(*ap);
980                 if (!*++ap) {
981                         putc('\n', tracefile);
982                         break;
983                 }
984                 putc(' ', tracefile);
985         }
986 }
987
988 static void
989 opentrace(void)
990 {
991         char s[100];
992 #ifdef O_APPEND
993         int flags;
994 #endif
995
996         if (debug != 1) {
997                 if (tracefile)
998                         fflush(tracefile);
999                 /* leave open because libedit might be using it */
1000                 return;
1001         }
1002         strcpy(s, "./trace");
1003         if (tracefile) {
1004                 if (!freopen(s, "a", tracefile)) {
1005                         fprintf(stderr, "Can't re-open %s\n", s);
1006                         debug = 0;
1007                         return;
1008                 }
1009         } else {
1010                 tracefile = fopen(s, "a");
1011                 if (tracefile == NULL) {
1012                         fprintf(stderr, "Can't open %s\n", s);
1013                         debug = 0;
1014                         return;
1015                 }
1016         }
1017 #ifdef O_APPEND
1018         flags = fcntl(fileno(tracefile), F_GETFL);
1019         if (flags >= 0)
1020                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1021 #endif
1022         setlinebuf(tracefile);
1023         fputs("\nTracing started.\n", tracefile);
1024 }
1025
1026 static void
1027 indent(int amount, char *pfx, FILE *fp)
1028 {
1029         int i;
1030
1031         for (i = 0; i < amount; i++) {
1032                 if (pfx && i == amount - 1)
1033                         fputs(pfx, fp);
1034                 putc('\t', fp);
1035         }
1036 }
1037
1038 /* little circular references here... */
1039 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1040
1041 static void
1042 sharg(union node *arg, FILE *fp)
1043 {
1044         char *p;
1045         struct nodelist *bqlist;
1046         unsigned char subtype;
1047
1048         if (arg->type != NARG) {
1049                 out1fmt("<node type %d>\n", arg->type);
1050                 abort();
1051         }
1052         bqlist = arg->narg.backquote;
1053         for (p = arg->narg.text; *p; p++) {
1054                 switch ((unsigned char)*p) {
1055                 case CTLESC:
1056                         p++;
1057                         putc(*p, fp);
1058                         break;
1059                 case CTLVAR:
1060                         putc('$', fp);
1061                         putc('{', fp);
1062                         subtype = *++p;
1063                         if (subtype == VSLENGTH)
1064                                 putc('#', fp);
1065
1066                         while (*p != '=') {
1067                                 putc(*p, fp);
1068                                 p++;
1069                         }
1070
1071                         if (subtype & VSNUL)
1072                                 putc(':', fp);
1073
1074                         switch (subtype & VSTYPE) {
1075                         case VSNORMAL:
1076                                 putc('}', fp);
1077                                 break;
1078                         case VSMINUS:
1079                                 putc('-', fp);
1080                                 break;
1081                         case VSPLUS:
1082                                 putc('+', fp);
1083                                 break;
1084                         case VSQUESTION:
1085                                 putc('?', fp);
1086                                 break;
1087                         case VSASSIGN:
1088                                 putc('=', fp);
1089                                 break;
1090                         case VSTRIMLEFT:
1091                                 putc('#', fp);
1092                                 break;
1093                         case VSTRIMLEFTMAX:
1094                                 putc('#', fp);
1095                                 putc('#', fp);
1096                                 break;
1097                         case VSTRIMRIGHT:
1098                                 putc('%', fp);
1099                                 break;
1100                         case VSTRIMRIGHTMAX:
1101                                 putc('%', fp);
1102                                 putc('%', fp);
1103                                 break;
1104                         case VSLENGTH:
1105                                 break;
1106                         default:
1107                                 out1fmt("<subtype %d>", subtype);
1108                         }
1109                         break;
1110                 case CTLENDVAR:
1111                         putc('}', fp);
1112                         break;
1113                 case CTLBACKQ:
1114                         putc('$', fp);
1115                         putc('(', fp);
1116                         shtree(bqlist->n, -1, NULL, fp);
1117                         putc(')', fp);
1118                         break;
1119                 default:
1120                         putc(*p, fp);
1121                         break;
1122                 }
1123         }
1124 }
1125
1126 static void
1127 shcmd(union node *cmd, FILE *fp)
1128 {
1129         union node *np;
1130         int first;
1131         const char *s;
1132         int dftfd;
1133
1134         first = 1;
1135         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1136                 if (!first)
1137                         putc(' ', fp);
1138                 sharg(np, fp);
1139                 first = 0;
1140         }
1141         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1142                 if (!first)
1143                         putc(' ', fp);
1144                 dftfd = 0;
1145                 switch (np->nfile.type) {
1146                 case NTO:      s = ">>"+1; dftfd = 1; break;
1147                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1148                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1149 #if BASH_REDIR_OUTPUT
1150                 case NTO2:
1151 #endif
1152                 case NTOFD:    s = ">&"; dftfd = 1; break;
1153                 case NFROM:    s = "<"; break;
1154                 case NFROMFD:  s = "<&"; break;
1155                 case NFROMTO:  s = "<>"; break;
1156                 default:       s = "*error*"; break;
1157                 }
1158                 if (np->nfile.fd != dftfd)
1159                         fprintf(fp, "%d", np->nfile.fd);
1160                 fputs(s, fp);
1161                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1162                         fprintf(fp, "%d", np->ndup.dupfd);
1163                 } else {
1164                         sharg(np->nfile.fname, fp);
1165                 }
1166                 first = 0;
1167         }
1168 }
1169
1170 static void
1171 shtree(union node *n, int ind, char *pfx, FILE *fp)
1172 {
1173         struct nodelist *lp;
1174         const char *s;
1175
1176         if (n == NULL)
1177                 return;
1178
1179         indent(ind, pfx, fp);
1180
1181         if (n == NODE_EOF) {
1182                 fputs("<EOF>", fp);
1183                 return;
1184         }
1185
1186         switch (n->type) {
1187         case NSEMI:
1188                 s = "; ";
1189                 goto binop;
1190         case NAND:
1191                 s = " && ";
1192                 goto binop;
1193         case NOR:
1194                 s = " || ";
1195  binop:
1196                 shtree(n->nbinary.ch1, ind, NULL, fp);
1197                 /* if (ind < 0) */
1198                         fputs(s, fp);
1199                 shtree(n->nbinary.ch2, ind, NULL, fp);
1200                 break;
1201         case NCMD:
1202                 shcmd(n, fp);
1203                 if (ind >= 0)
1204                         putc('\n', fp);
1205                 break;
1206         case NPIPE:
1207                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1208                         shtree(lp->n, 0, NULL, fp);
1209                         if (lp->next)
1210                                 fputs(" | ", fp);
1211                 }
1212                 if (n->npipe.pipe_backgnd)
1213                         fputs(" &", fp);
1214                 if (ind >= 0)
1215                         putc('\n', fp);
1216                 break;
1217         default:
1218                 fprintf(fp, "<node type %d>", n->type);
1219                 if (ind >= 0)
1220                         putc('\n', fp);
1221                 break;
1222         }
1223 }
1224
1225 static void
1226 showtree(union node *n)
1227 {
1228         trace_puts("showtree called\n");
1229         shtree(n, 1, NULL, stderr);
1230 }
1231
1232 #endif /* DEBUG */
1233
1234
1235 /* ============ Parser data */
1236
1237 /*
1238  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1239  */
1240 struct strlist {
1241         struct strlist *next;
1242         char *text;
1243 };
1244
1245 struct alias;
1246
1247 struct strpush {
1248         struct strpush *prev;   /* preceding string on stack */
1249         char *prev_string;
1250         int prev_left_in_line;
1251 #if ENABLE_ASH_ALIAS
1252         struct alias *ap;       /* if push was associated with an alias */
1253 #endif
1254         char *string;           /* remember the string since it may change */
1255
1256         /* Remember last two characters for pungetc. */
1257         int lastc[2];
1258
1259         /* Number of outstanding calls to pungetc. */
1260         int unget;
1261 };
1262
1263 /*
1264  * The parsefile structure pointed to by the global variable parsefile
1265  * contains information about the current file being read.
1266  */
1267 struct parsefile {
1268         struct parsefile *prev; /* preceding file on stack */
1269         int linno;              /* current line */
1270         int pf_fd;              /* file descriptor (or -1 if string) */
1271         int left_in_line;       /* number of chars left in this line */
1272         int left_in_buffer;     /* number of chars left in this buffer past the line */
1273         char *next_to_pgetc;    /* next char in buffer */
1274         char *buf;              /* input buffer */
1275         struct strpush *strpush; /* for pushing strings at this level */
1276         struct strpush basestrpush; /* so pushing one is fast */
1277
1278         /* Remember last two characters for pungetc. */
1279         int lastc[2];
1280
1281         /* Number of outstanding calls to pungetc. */
1282         int unget;
1283 };
1284
1285 static struct parsefile basepf;        /* top level input file */
1286 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1287 static char *commandname;              /* currently executing command */
1288
1289
1290 /* ============ Message printing */
1291
1292 static void
1293 ash_vmsg(const char *msg, va_list ap)
1294 {
1295         fprintf(stderr, "%s: ", arg0);
1296         if (commandname) {
1297                 if (strcmp(arg0, commandname))
1298                         fprintf(stderr, "%s: ", commandname);
1299                 if (!iflag || g_parsefile->pf_fd > 0)
1300                         fprintf(stderr, "line %d: ", errlinno);
1301         }
1302         vfprintf(stderr, msg, ap);
1303         newline_and_flush(stderr);
1304 }
1305
1306 /*
1307  * Exverror is called to raise the error exception.  If the second argument
1308  * is not NULL then error prints an error message using printf style
1309  * formatting.  It then raises the error exception.
1310  */
1311 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1312 static void
1313 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1314 {
1315 #if DEBUG
1316         if (msg) {
1317                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1318                 TRACEV((msg, ap));
1319         } else
1320                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1321         if (msg)
1322 #endif
1323                 ash_vmsg(msg, ap);
1324
1325         flush_stdout_stderr();
1326         raise_exception(cond);
1327         /* NOTREACHED */
1328 }
1329
1330 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1331 static void
1332 ash_msg_and_raise_error(const char *msg, ...)
1333 {
1334         va_list ap;
1335
1336         exitstatus = 2;
1337
1338         va_start(ap, msg);
1339         ash_vmsg_and_raise(EXERROR, msg, ap);
1340         /* NOTREACHED */
1341         va_end(ap);
1342 }
1343
1344 /*
1345  * 'fmt' must be a string literal.
1346  */
1347 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1348
1349 static void raise_error_syntax(const char *) NORETURN;
1350 static void
1351 raise_error_syntax(const char *msg)
1352 {
1353         errlinno = g_parsefile->linno;
1354         ash_msg_and_raise_error("syntax error: %s", msg);
1355         /* NOTREACHED */
1356 }
1357
1358 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1359 static void
1360 ash_msg_and_raise(int cond, const char *msg, ...)
1361 {
1362         va_list ap;
1363
1364         va_start(ap, msg);
1365         ash_vmsg_and_raise(cond, msg, ap);
1366         /* NOTREACHED */
1367         va_end(ap);
1368 }
1369
1370 /*
1371  * error/warning routines for external builtins
1372  */
1373 static void
1374 ash_msg(const char *fmt, ...)
1375 {
1376         va_list ap;
1377
1378         va_start(ap, fmt);
1379         ash_vmsg(fmt, ap);
1380         va_end(ap);
1381 }
1382
1383 /*
1384  * Return a string describing an error.  The returned string may be a
1385  * pointer to a static buffer that will be overwritten on the next call.
1386  * Action describes the operation that got the error.
1387  */
1388 static const char *
1389 errmsg(int e, const char *em)
1390 {
1391         if (e == ENOENT || e == ENOTDIR) {
1392                 return em;
1393         }
1394         return strerror(e);
1395 }
1396
1397
1398 /* ============ Memory allocation */
1399
1400 #if 0
1401 /* I consider these wrappers nearly useless:
1402  * ok, they return you to nearest exception handler, but
1403  * how much memory do you leak in the process, making
1404  * memory starvation worse?
1405  */
1406 static void *
1407 ckrealloc(void * p, size_t nbytes)
1408 {
1409         p = realloc(p, nbytes);
1410         if (!p)
1411                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1412         return p;
1413 }
1414
1415 static void *
1416 ckmalloc(size_t nbytes)
1417 {
1418         return ckrealloc(NULL, nbytes);
1419 }
1420
1421 static void *
1422 ckzalloc(size_t nbytes)
1423 {
1424         return memset(ckmalloc(nbytes), 0, nbytes);
1425 }
1426
1427 static char *
1428 ckstrdup(const char *s)
1429 {
1430         char *p = strdup(s);
1431         if (!p)
1432                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1433         return p;
1434 }
1435 #else
1436 /* Using bbox equivalents. They exit if out of memory */
1437 # define ckrealloc xrealloc
1438 # define ckmalloc  xmalloc
1439 # define ckzalloc  xzalloc
1440 # define ckstrdup  xstrdup
1441 #endif
1442
1443 /*
1444  * It appears that grabstackstr() will barf with such alignments
1445  * because stalloc() will return a string allocated in a new stackblock.
1446  */
1447 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1448 enum {
1449         /* Most machines require the value returned from malloc to be aligned
1450          * in some way.  The following macro will get this right
1451          * on many machines.  */
1452         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1453         /* Minimum size of a block */
1454         MINSIZE = SHELL_ALIGN(504),
1455 };
1456
1457 struct stack_block {
1458         struct stack_block *prev;
1459         char space[MINSIZE];
1460 };
1461
1462 struct stackmark {
1463         struct stack_block *stackp;
1464         char *stacknxt;
1465         size_t stacknleft;
1466 };
1467
1468
1469 struct globals_memstack {
1470         struct stack_block *g_stackp; // = &stackbase;
1471         char *g_stacknxt; // = stackbase.space;
1472         char *sstrend; // = stackbase.space + MINSIZE;
1473         size_t g_stacknleft; // = MINSIZE;
1474         struct stack_block stackbase;
1475 };
1476 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1477 #define G_memstack (*ash_ptr_to_globals_memstack)
1478 #define g_stackp     (G_memstack.g_stackp    )
1479 #define g_stacknxt   (G_memstack.g_stacknxt  )
1480 #define sstrend      (G_memstack.sstrend     )
1481 #define g_stacknleft (G_memstack.g_stacknleft)
1482 #define stackbase    (G_memstack.stackbase   )
1483 #define INIT_G_memstack() do { \
1484         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1485         barrier(); \
1486         g_stackp = &stackbase; \
1487         g_stacknxt = stackbase.space; \
1488         g_stacknleft = MINSIZE; \
1489         sstrend = stackbase.space + MINSIZE; \
1490 } while (0)
1491
1492
1493 #define stackblock()     ((void *)g_stacknxt)
1494 #define stackblocksize() g_stacknleft
1495
1496 /*
1497  * Parse trees for commands are allocated in lifo order, so we use a stack
1498  * to make this more efficient, and also to avoid all sorts of exception
1499  * handling code to handle interrupts in the middle of a parse.
1500  *
1501  * The size 504 was chosen because the Ultrix malloc handles that size
1502  * well.
1503  */
1504 static void *
1505 stalloc(size_t nbytes)
1506 {
1507         char *p;
1508         size_t aligned;
1509
1510         aligned = SHELL_ALIGN(nbytes);
1511         if (aligned > g_stacknleft) {
1512                 size_t len;
1513                 size_t blocksize;
1514                 struct stack_block *sp;
1515
1516                 blocksize = aligned;
1517                 if (blocksize < MINSIZE)
1518                         blocksize = MINSIZE;
1519                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1520                 if (len < blocksize)
1521                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1522                 INT_OFF;
1523                 sp = ckmalloc(len);
1524                 sp->prev = g_stackp;
1525                 g_stacknxt = sp->space;
1526                 g_stacknleft = blocksize;
1527                 sstrend = g_stacknxt + blocksize;
1528                 g_stackp = sp;
1529                 INT_ON;
1530         }
1531         p = g_stacknxt;
1532         g_stacknxt += aligned;
1533         g_stacknleft -= aligned;
1534         return p;
1535 }
1536
1537 static void *
1538 stzalloc(size_t nbytes)
1539 {
1540         return memset(stalloc(nbytes), 0, nbytes);
1541 }
1542
1543 static void
1544 stunalloc(void *p)
1545 {
1546 #if DEBUG
1547         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1548                 write(STDERR_FILENO, "stunalloc\n", 10);
1549                 abort();
1550         }
1551 #endif
1552         g_stacknleft += g_stacknxt - (char *)p;
1553         g_stacknxt = p;
1554 }
1555
1556 /*
1557  * Like strdup but works with the ash stack.
1558  */
1559 static char *
1560 sstrdup(const char *p)
1561 {
1562         size_t len = strlen(p) + 1;
1563         return memcpy(stalloc(len), p, len);
1564 }
1565
1566 static ALWAYS_INLINE void
1567 grabstackblock(size_t len)
1568 {
1569         stalloc(len);
1570 }
1571
1572 static void
1573 pushstackmark(struct stackmark *mark, size_t len)
1574 {
1575         mark->stackp = g_stackp;
1576         mark->stacknxt = g_stacknxt;
1577         mark->stacknleft = g_stacknleft;
1578         grabstackblock(len);
1579 }
1580
1581 static void
1582 setstackmark(struct stackmark *mark)
1583 {
1584         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1585 }
1586
1587 static void
1588 popstackmark(struct stackmark *mark)
1589 {
1590         struct stack_block *sp;
1591
1592         if (!mark->stackp)
1593                 return;
1594
1595         INT_OFF;
1596         while (g_stackp != mark->stackp) {
1597                 sp = g_stackp;
1598                 g_stackp = sp->prev;
1599                 free(sp);
1600         }
1601         g_stacknxt = mark->stacknxt;
1602         g_stacknleft = mark->stacknleft;
1603         sstrend = mark->stacknxt + mark->stacknleft;
1604         INT_ON;
1605 }
1606
1607 /*
1608  * When the parser reads in a string, it wants to stick the string on the
1609  * stack and only adjust the stack pointer when it knows how big the
1610  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1611  * of space on top of the stack and stackblocklen returns the length of
1612  * this block.  Growstackblock will grow this space by at least one byte,
1613  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1614  * part of the block that has been used.
1615  */
1616 static void
1617 growstackblock(void)
1618 {
1619         size_t newlen;
1620
1621         newlen = g_stacknleft * 2;
1622         if (newlen < g_stacknleft)
1623                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1624         if (newlen < 128)
1625                 newlen += 128;
1626
1627         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1628                 struct stack_block *sp;
1629                 struct stack_block *prevstackp;
1630                 size_t grosslen;
1631
1632                 INT_OFF;
1633                 sp = g_stackp;
1634                 prevstackp = sp->prev;
1635                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1636                 sp = ckrealloc(sp, grosslen);
1637                 sp->prev = prevstackp;
1638                 g_stackp = sp;
1639                 g_stacknxt = sp->space;
1640                 g_stacknleft = newlen;
1641                 sstrend = sp->space + newlen;
1642                 INT_ON;
1643         } else {
1644                 char *oldspace = g_stacknxt;
1645                 size_t oldlen = g_stacknleft;
1646                 char *p = stalloc(newlen);
1647
1648                 /* free the space we just allocated */
1649                 g_stacknxt = memcpy(p, oldspace, oldlen);
1650                 g_stacknleft += newlen;
1651         }
1652 }
1653
1654 /*
1655  * The following routines are somewhat easier to use than the above.
1656  * The user declares a variable of type STACKSTR, which may be declared
1657  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1658  * the user uses the macro STPUTC to add characters to the string.  In
1659  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1660  * grown as necessary.  When the user is done, she can just leave the
1661  * string there and refer to it using stackblock().  Or she can allocate
1662  * the space for it using grabstackstr().  If it is necessary to allow
1663  * someone else to use the stack temporarily and then continue to grow
1664  * the string, the user should use grabstack to allocate the space, and
1665  * then call ungrabstr(p) to return to the previous mode of operation.
1666  *
1667  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1668  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1669  * is space for at least one character.
1670  */
1671 static void *
1672 growstackstr(void)
1673 {
1674         size_t len = stackblocksize();
1675         growstackblock();
1676         return (char *)stackblock() + len;
1677 }
1678
1679 /*
1680  * Called from CHECKSTRSPACE.
1681  */
1682 static char *
1683 makestrspace(size_t newlen, char *p)
1684 {
1685         size_t len = p - g_stacknxt;
1686         size_t size;
1687
1688         for (;;) {
1689                 size_t nleft;
1690
1691                 size = stackblocksize();
1692                 nleft = size - len;
1693                 if (nleft >= newlen)
1694                         break;
1695                 growstackblock();
1696         }
1697         return (char *)stackblock() + len;
1698 }
1699
1700 static char *
1701 stack_nputstr(const char *s, size_t n, char *p)
1702 {
1703         p = makestrspace(n, p);
1704         p = (char *)mempcpy(p, s, n);
1705         return p;
1706 }
1707
1708 static char *
1709 stack_putstr(const char *s, char *p)
1710 {
1711         return stack_nputstr(s, strlen(s), p);
1712 }
1713
1714 static char *
1715 _STPUTC(int c, char *p)
1716 {
1717         if (p == sstrend)
1718                 p = growstackstr();
1719         *p++ = c;
1720         return p;
1721 }
1722
1723 #define STARTSTACKSTR(p)        ((p) = stackblock())
1724 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1725 #define CHECKSTRSPACE(n, p) do { \
1726         char *q = (p); \
1727         size_t l = (n); \
1728         size_t m = sstrend - q; \
1729         if (l > m) \
1730                 (p) = makestrspace(l, q); \
1731 } while (0)
1732 #define USTPUTC(c, p)           (*(p)++ = (c))
1733 #define STACKSTRNUL(p) do { \
1734         if ((p) == sstrend) \
1735                 (p) = growstackstr(); \
1736         *(p) = '\0'; \
1737 } while (0)
1738 #define STUNPUTC(p)             (--(p))
1739 #define STTOPC(p)               ((p)[-1])
1740 #define STADJUST(amount, p)     ((p) += (amount))
1741
1742 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1743 #define ungrabstackstr(s, p)    stunalloc(s)
1744 #define stackstrend()           ((void *)sstrend)
1745
1746
1747 /* ============ String helpers */
1748
1749 /*
1750  * prefix -- see if pfx is a prefix of string.
1751  */
1752 static char *
1753 prefix(const char *string, const char *pfx)
1754 {
1755         while (*pfx) {
1756                 if (*pfx++ != *string++)
1757                         return NULL;
1758         }
1759         return (char *) string;
1760 }
1761
1762 /*
1763  * Check for a valid number.  This should be elsewhere.
1764  */
1765 static int
1766 is_number(const char *p)
1767 {
1768         do {
1769                 if (!isdigit(*p))
1770                         return 0;
1771         } while (*++p != '\0');
1772         return 1;
1773 }
1774
1775 /*
1776  * Convert a string of digits to an integer, printing an error message on
1777  * failure.
1778  */
1779 static int
1780 number(const char *s)
1781 {
1782         if (!is_number(s))
1783                 ash_msg_and_raise_error(msg_illnum, s);
1784         return atoi(s);
1785 }
1786
1787 /*
1788  * Produce a single quoted string suitable as input to the shell.
1789  * The return string is allocated on the stack.
1790  */
1791 static char *
1792 single_quote(const char *s)
1793 {
1794         char *p;
1795
1796         STARTSTACKSTR(p);
1797
1798         do {
1799                 char *q;
1800                 size_t len;
1801
1802                 len = strchrnul(s, '\'') - s;
1803
1804                 q = p = makestrspace(len + 3, p);
1805
1806                 *q++ = '\'';
1807                 q = (char *)mempcpy(q, s, len);
1808                 *q++ = '\'';
1809                 s += len;
1810
1811                 STADJUST(q - p, p);
1812
1813                 if (*s != '\'')
1814                         break;
1815                 len = 0;
1816                 do len++; while (*++s == '\'');
1817
1818                 q = p = makestrspace(len + 3, p);
1819
1820                 *q++ = '"';
1821                 q = (char *)mempcpy(q, s - len, len);
1822                 *q++ = '"';
1823
1824                 STADJUST(q - p, p);
1825         } while (*s);
1826
1827         USTPUTC('\0', p);
1828
1829         return stackblock();
1830 }
1831
1832 /*
1833  * Produce a possibly single quoted string suitable as input to the shell.
1834  * If quoting was done, the return string is allocated on the stack,
1835  * otherwise a pointer to the original string is returned.
1836  */
1837 static const char *
1838 maybe_single_quote(const char *s)
1839 {
1840         const char *p = s;
1841
1842         while (*p) {
1843                 /* Assuming ACSII */
1844                 /* quote ctrl_chars space !"#$%&'()* */
1845                 if (*p < '+')
1846                         goto need_quoting;
1847                 /* quote ;<=>? */
1848                 if (*p >= ';' && *p <= '?')
1849                         goto need_quoting;
1850                 /* quote `[\ */
1851                 if (*p == '`')
1852                         goto need_quoting;
1853                 if (*p == '[')
1854                         goto need_quoting;
1855                 if (*p == '\\')
1856                         goto need_quoting;
1857                 /* quote {|}~ DEL and high bytes */
1858                 if (*p > 'z')
1859                         goto need_quoting;
1860                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1861                 /* TODO: maybe avoid quoting % */
1862                 p++;
1863         }
1864         return s;
1865
1866  need_quoting:
1867         return single_quote(s);
1868 }
1869
1870
1871 /* ============ nextopt */
1872
1873 static char **argptr;                  /* argument list for builtin commands */
1874 static char *optionarg;                /* set by nextopt (like getopt) */
1875 static char *optptr;                   /* used by nextopt */
1876
1877 /*
1878  * XXX - should get rid of. Have all builtins use getopt(3).
1879  * The library getopt must have the BSD extension static variable
1880  * "optreset", otherwise it can't be used within the shell safely.
1881  *
1882  * Standard option processing (a la getopt) for builtin routines.
1883  * The only argument that is passed to nextopt is the option string;
1884  * the other arguments are unnecessary. It returns the character,
1885  * or '\0' on end of input.
1886  */
1887 static int
1888 nextopt(const char *optstring)
1889 {
1890         char *p;
1891         const char *q;
1892         char c;
1893
1894         p = optptr;
1895         if (p == NULL || *p == '\0') {
1896                 /* We ate entire "-param", take next one */
1897                 p = *argptr;
1898                 if (p == NULL)
1899                         return '\0';
1900                 if (*p != '-')
1901                         return '\0';
1902                 if (*++p == '\0') /* just "-" ? */
1903                         return '\0';
1904                 argptr++;
1905                 if (LONE_DASH(p)) /* "--" ? */
1906                         return '\0';
1907                 /* p => next "-param" */
1908         }
1909         /* p => some option char in the middle of a "-param" */
1910         c = *p++;
1911         for (q = optstring; *q != c;) {
1912                 if (*q == '\0')
1913                         ash_msg_and_raise_error("illegal option -%c", c);
1914                 if (*++q == ':')
1915                         q++;
1916         }
1917         if (*++q == ':') {
1918                 if (*p == '\0') {
1919                         p = *argptr++;
1920                         if (p == NULL)
1921                                 ash_msg_and_raise_error("no arg for -%c option", c);
1922                 }
1923                 optionarg = p;
1924                 p = NULL;
1925         }
1926         optptr = p;
1927         return c;
1928 }
1929
1930
1931 /* ============ Shell variables */
1932
1933 struct shparam {
1934         int nparam;             /* # of positional parameters (without $0) */
1935 #if ENABLE_ASH_GETOPTS
1936         int optind;             /* next parameter to be processed by getopts */
1937         int optoff;             /* used by getopts */
1938 #endif
1939         unsigned char malloced; /* if parameter list dynamically allocated */
1940         char **p;               /* parameter list */
1941 };
1942
1943 /*
1944  * Free the list of positional parameters.
1945  */
1946 static void
1947 freeparam(volatile struct shparam *param)
1948 {
1949         if (param->malloced) {
1950                 char **ap, **ap1;
1951                 ap = ap1 = param->p;
1952                 while (*ap)
1953                         free(*ap++);
1954                 free(ap1);
1955         }
1956 }
1957
1958 #if ENABLE_ASH_GETOPTS
1959 static void FAST_FUNC getoptsreset(const char *value);
1960 #endif
1961
1962 struct var {
1963         struct var *next;               /* next entry in hash list */
1964         int flags;                      /* flags are defined above */
1965         const char *var_text;           /* name=value */
1966         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1967                                         /* the variable gets set/unset */
1968 };
1969
1970 struct localvar {
1971         struct localvar *next;          /* next local variable in list */
1972         struct var *vp;                 /* the variable that was made local */
1973         int flags;                      /* saved flags */
1974         const char *text;               /* saved text */
1975 };
1976
1977 /* flags */
1978 #define VEXPORT         0x01    /* variable is exported */
1979 #define VREADONLY       0x02    /* variable cannot be modified */
1980 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1981 #define VTEXTFIXED      0x08    /* text is statically allocated */
1982 #define VSTACK          0x10    /* text is allocated on the stack */
1983 #define VUNSET          0x20    /* the variable is not set */
1984 #define VNOFUNC         0x40    /* don't call the callback function */
1985 #define VNOSET          0x80    /* do not set variable - just readonly test */
1986 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1987 #if ENABLE_ASH_RANDOM_SUPPORT
1988 # define VDYNAMIC       0x200   /* dynamic variable */
1989 #else
1990 # define VDYNAMIC       0
1991 #endif
1992
1993
1994 /* Need to be before varinit_data[] */
1995 #if ENABLE_LOCALE_SUPPORT
1996 static void FAST_FUNC
1997 change_lc_all(const char *value)
1998 {
1999         if (value && *value != '\0')
2000                 setlocale(LC_ALL, value);
2001 }
2002 static void FAST_FUNC
2003 change_lc_ctype(const char *value)
2004 {
2005         if (value && *value != '\0')
2006                 setlocale(LC_CTYPE, value);
2007 }
2008 #endif
2009 #if ENABLE_ASH_MAIL
2010 static void chkmail(void);
2011 static void changemail(const char *var_value) FAST_FUNC;
2012 #else
2013 # define chkmail()  ((void)0)
2014 #endif
2015 static void changepath(const char *) FAST_FUNC;
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017 static void change_random(const char *) FAST_FUNC;
2018 #endif
2019
2020 static const struct {
2021         int flags;
2022         const char *var_text;
2023         void (*var_func)(const char *) FAST_FUNC;
2024 } varinit_data[] = {
2025         /*
2026          * Note: VEXPORT would not work correctly here for NOFORK applets:
2027          * some environment strings may be constant.
2028          */
2029         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2030 #if ENABLE_ASH_MAIL
2031         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2032         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2033 #endif
2034         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2035         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2036         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2037         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2038 #if ENABLE_ASH_GETOPTS
2039         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2040 #endif
2041         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2042 #if ENABLE_ASH_RANDOM_SUPPORT
2043         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2044 #endif
2045 #if ENABLE_LOCALE_SUPPORT
2046         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2047         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2048 #endif
2049 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2050         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2051 #endif
2052 };
2053
2054 struct redirtab;
2055
2056 struct globals_var {
2057         struct shparam shellparam;      /* $@ current positional parameters */
2058         struct redirtab *redirlist;
2059         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2060         struct var *vartab[VTABSIZE];
2061         struct var varinit[ARRAY_SIZE(varinit_data)];
2062         int lineno;
2063         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2064 };
2065 extern struct globals_var *const ash_ptr_to_globals_var;
2066 #define G_var (*ash_ptr_to_globals_var)
2067 #define shellparam    (G_var.shellparam   )
2068 //#define redirlist     (G_var.redirlist    )
2069 #define preverrout_fd (G_var.preverrout_fd)
2070 #define vartab        (G_var.vartab       )
2071 #define varinit       (G_var.varinit      )
2072 #define lineno        (G_var.lineno       )
2073 #define linenovar     (G_var.linenovar    )
2074 #define vifs      varinit[0]
2075 #if ENABLE_ASH_MAIL
2076 # define vmail    (&vifs)[1]
2077 # define vmpath   (&vmail)[1]
2078 # define vpath    (&vmpath)[1]
2079 #else
2080 # define vpath    (&vifs)[1]
2081 #endif
2082 #define vps1      (&vpath)[1]
2083 #define vps2      (&vps1)[1]
2084 #define vps4      (&vps2)[1]
2085 #if ENABLE_ASH_GETOPTS
2086 # define voptind  (&vps4)[1]
2087 # define vlineno  (&voptind)[1]
2088 # if ENABLE_ASH_RANDOM_SUPPORT
2089 #  define vrandom (&vlineno)[1]
2090 # endif
2091 #else
2092 # define vlineno  (&vps4)[1]
2093 # if ENABLE_ASH_RANDOM_SUPPORT
2094 #  define vrandom (&vlineno)[1]
2095 # endif
2096 #endif
2097 #define INIT_G_var() do { \
2098         unsigned i; \
2099         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2100         barrier(); \
2101         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2102                 varinit[i].flags    = varinit_data[i].flags; \
2103                 varinit[i].var_text = varinit_data[i].var_text; \
2104                 varinit[i].var_func = varinit_data[i].var_func; \
2105         } \
2106         strcpy(linenovar, "LINENO="); \
2107         vlineno.var_text = linenovar; \
2108 } while (0)
2109
2110 /*
2111  * The following macros access the values of the above variables.
2112  * They have to skip over the name.  They return the null string
2113  * for unset variables.
2114  */
2115 #define ifsval()        (vifs.var_text + 4)
2116 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2117 #if ENABLE_ASH_MAIL
2118 # define mailval()      (vmail.var_text + 5)
2119 # define mpathval()     (vmpath.var_text + 9)
2120 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2121 #endif
2122 #define pathval()       (vpath.var_text + 5)
2123 #define ps1val()        (vps1.var_text + 4)
2124 #define ps2val()        (vps2.var_text + 4)
2125 #define ps4val()        (vps4.var_text + 4)
2126 #if ENABLE_ASH_GETOPTS
2127 # define optindval()    (voptind.var_text + 7)
2128 #endif
2129
2130 #if ENABLE_ASH_GETOPTS
2131 static void FAST_FUNC
2132 getoptsreset(const char *value)
2133 {
2134         shellparam.optind = 1;
2135         if (is_number(value))
2136                 shellparam.optind = number(value) ?: 1;
2137         shellparam.optoff = -1;
2138 }
2139 #endif
2140
2141 /*
2142  * Compares two strings up to the first = or '\0'.  The first
2143  * string must be terminated by '='; the second may be terminated by
2144  * either '=' or '\0'.
2145  */
2146 static int
2147 varcmp(const char *p, const char *q)
2148 {
2149         int c, d;
2150
2151         while ((c = *p) == (d = *q)) {
2152                 if (c == '\0' || c == '=')
2153                         goto out;
2154                 p++;
2155                 q++;
2156         }
2157         if (c == '=')
2158                 c = '\0';
2159         if (d == '=')
2160                 d = '\0';
2161  out:
2162         return c - d;
2163 }
2164
2165 /*
2166  * Find the appropriate entry in the hash table from the name.
2167  */
2168 static struct var **
2169 hashvar(const char *p)
2170 {
2171         unsigned hashval;
2172
2173         hashval = ((unsigned char) *p) << 4;
2174         while (*p && *p != '=')
2175                 hashval += (unsigned char) *p++;
2176         return &vartab[hashval % VTABSIZE];
2177 }
2178
2179 static int
2180 vpcmp(const void *a, const void *b)
2181 {
2182         return varcmp(*(const char **)a, *(const char **)b);
2183 }
2184
2185 /*
2186  * This routine initializes the builtin variables.
2187  */
2188 static void
2189 initvar(void)
2190 {
2191         struct var *vp;
2192         struct var *end;
2193         struct var **vpp;
2194
2195         /*
2196          * PS1 depends on uid
2197          */
2198 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2199         vps1.var_text = "PS1=\\w \\$ ";
2200 #else
2201         if (!geteuid())
2202                 vps1.var_text = "PS1=# ";
2203 #endif
2204         vp = varinit;
2205         end = vp + ARRAY_SIZE(varinit);
2206         do {
2207                 vpp = hashvar(vp->var_text);
2208                 vp->next = *vpp;
2209                 *vpp = vp;
2210         } while (++vp < end);
2211 }
2212
2213 static struct var **
2214 findvar(struct var **vpp, const char *name)
2215 {
2216         for (; *vpp; vpp = &(*vpp)->next) {
2217                 if (varcmp((*vpp)->var_text, name) == 0) {
2218                         break;
2219                 }
2220         }
2221         return vpp;
2222 }
2223
2224 /*
2225  * Find the value of a variable.  Returns NULL if not set.
2226  */
2227 static const char* FAST_FUNC
2228 lookupvar(const char *name)
2229 {
2230         struct var *v;
2231
2232         v = *findvar(hashvar(name), name);
2233         if (v) {
2234 #if ENABLE_ASH_RANDOM_SUPPORT
2235         /*
2236          * Dynamic variables are implemented roughly the same way they are
2237          * in bash. Namely, they're "special" so long as they aren't unset.
2238          * As soon as they're unset, they're no longer dynamic, and dynamic
2239          * lookup will no longer happen at that point. -- PFM.
2240          */
2241                 if (v->flags & VDYNAMIC)
2242                         v->var_func(NULL);
2243 #endif
2244                 if (!(v->flags & VUNSET)) {
2245                         if (v == &vlineno && v->var_text == linenovar) {
2246                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2247                         }
2248                         return var_end(v->var_text);
2249                 }
2250         }
2251         return NULL;
2252 }
2253
2254 #if ENABLE_UNICODE_SUPPORT
2255 static void
2256 reinit_unicode_for_ash(void)
2257 {
2258         /* Unicode support should be activated even if LANG is set
2259          * _during_ shell execution, not only if it was set when
2260          * shell was started. Therefore, re-check LANG every time:
2261          */
2262         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2263          || ENABLE_UNICODE_USING_LOCALE
2264         ) {
2265                 const char *s = lookupvar("LC_ALL");
2266                 if (!s) s = lookupvar("LC_CTYPE");
2267                 if (!s) s = lookupvar("LANG");
2268                 reinit_unicode(s);
2269         }
2270 }
2271 #else
2272 # define reinit_unicode_for_ash() ((void)0)
2273 #endif
2274
2275 /*
2276  * Search the environment of a builtin command.
2277  */
2278 static ALWAYS_INLINE const char *
2279 bltinlookup(const char *name)
2280 {
2281         return lookupvar(name);
2282 }
2283
2284 /*
2285  * Same as setvar except that the variable and value are passed in
2286  * the first argument as name=value.  Since the first argument will
2287  * be actually stored in the table, it should not be a string that
2288  * will go away.
2289  * Called with interrupts off.
2290  */
2291 static struct var *
2292 setvareq(char *s, int flags)
2293 {
2294         struct var *vp, **vpp;
2295
2296         vpp = hashvar(s);
2297         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2298         vpp = findvar(vpp, s);
2299         vp = *vpp;
2300         if (vp) {
2301                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2302                         const char *n;
2303
2304                         if (flags & VNOSAVE)
2305                                 free(s);
2306                         n = vp->var_text;
2307                         exitstatus = 1;
2308                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2309                 }
2310
2311                 if (flags & VNOSET)
2312                         goto out;
2313
2314                 if (vp->var_func && !(flags & VNOFUNC))
2315                         vp->var_func(var_end(s));
2316
2317                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2318                         free((char*)vp->var_text);
2319
2320                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2321                         *vpp = vp->next;
2322                         free(vp);
2323  out_free:
2324                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2325                                 free(s);
2326                         goto out;
2327                 }
2328
2329                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2330         } else {
2331                 /* variable s is not found */
2332                 if (flags & VNOSET)
2333                         goto out;
2334                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2335                         goto out_free;
2336                 vp = ckzalloc(sizeof(*vp));
2337                 vp->next = *vpp;
2338                 /*vp->func = NULL; - ckzalloc did it */
2339                 *vpp = vp;
2340         }
2341         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2342                 s = ckstrdup(s);
2343         vp->var_text = s;
2344         vp->flags = flags;
2345
2346  out:
2347         return vp;
2348 }
2349
2350 /*
2351  * Set the value of a variable.  The flags argument is ored with the
2352  * flags of the variable.  If val is NULL, the variable is unset.
2353  */
2354 static struct var *
2355 setvar(const char *name, const char *val, int flags)
2356 {
2357         const char *q;
2358         char *p;
2359         char *nameeq;
2360         size_t namelen;
2361         size_t vallen;
2362         struct var *vp;
2363
2364         q = endofname(name);
2365         p = strchrnul(q, '=');
2366         namelen = p - name;
2367         if (!namelen || p != q)
2368                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2369         vallen = 0;
2370         if (val == NULL) {
2371                 flags |= VUNSET;
2372         } else {
2373                 vallen = strlen(val);
2374         }
2375
2376         INT_OFF;
2377         nameeq = ckmalloc(namelen + vallen + 2);
2378         p = mempcpy(nameeq, name, namelen);
2379         if (val) {
2380                 *p++ = '=';
2381                 p = mempcpy(p, val, vallen);
2382         }
2383         *p = '\0';
2384         vp = setvareq(nameeq, flags | VNOSAVE);
2385         INT_ON;
2386
2387         return vp;
2388 }
2389
2390 static void FAST_FUNC
2391 setvar0(const char *name, const char *val)
2392 {
2393         setvar(name, val, 0);
2394 }
2395
2396 /*
2397  * Unset the specified variable.
2398  */
2399 static void
2400 unsetvar(const char *s)
2401 {
2402         setvar(s, NULL, 0);
2403 }
2404
2405 /*
2406  * Process a linked list of variable assignments.
2407  */
2408 static void
2409 listsetvar(struct strlist *list_set_var, int flags)
2410 {
2411         struct strlist *lp = list_set_var;
2412
2413         if (!lp)
2414                 return;
2415         INT_OFF;
2416         do {
2417                 setvareq(lp->text, flags);
2418                 lp = lp->next;
2419         } while (lp);
2420         INT_ON;
2421 }
2422
2423 /*
2424  * Generate a list of variables satisfying the given conditions.
2425  */
2426 #if !ENABLE_FEATURE_SH_NOFORK
2427 # define listvars(on, off, lp, end) listvars(on, off, end)
2428 #endif
2429 static char **
2430 listvars(int on, int off, struct strlist *lp, char ***end)
2431 {
2432         struct var **vpp;
2433         struct var *vp;
2434         char **ep;
2435         int mask;
2436
2437         STARTSTACKSTR(ep);
2438         vpp = vartab;
2439         mask = on | off;
2440         do {
2441                 for (vp = *vpp; vp; vp = vp->next) {
2442                         if ((vp->flags & mask) == on) {
2443 #if ENABLE_FEATURE_SH_NOFORK
2444                                 /* If variable with the same name is both
2445                                  * exported and temporarily set for a command:
2446                                  *  export ZVAR=5
2447                                  *  ZVAR=6 printenv
2448                                  * then "ZVAR=6" will be both in vartab and
2449                                  * lp lists. Do not pass it twice to printenv.
2450                                  */
2451                                 struct strlist *lp1 = lp;
2452                                 while (lp1) {
2453                                         if (strcmp(lp1->text, vp->var_text) == 0)
2454                                                 goto skip;
2455                                         lp1 = lp1->next;
2456                                 }
2457 #endif
2458                                 if (ep == stackstrend())
2459                                         ep = growstackstr();
2460                                 *ep++ = (char*)vp->var_text;
2461 #if ENABLE_FEATURE_SH_NOFORK
2462  skip: ;
2463 #endif
2464                         }
2465                 }
2466         } while (++vpp < vartab + VTABSIZE);
2467
2468 #if ENABLE_FEATURE_SH_NOFORK
2469         while (lp) {
2470                 if (ep == stackstrend())
2471                         ep = growstackstr();
2472                 *ep++ = lp->text;
2473                 lp = lp->next;
2474         }
2475 #endif
2476
2477         if (ep == stackstrend())
2478                 ep = growstackstr();
2479         if (end)
2480                 *end = ep;
2481         *ep++ = NULL;
2482         return grabstackstr(ep);
2483 }
2484
2485
2486 /* ============ Path search helper
2487  *
2488  * The variable path (passed by reference) should be set to the start
2489  * of the path before the first call; path_advance will update
2490  * this value as it proceeds.  Successive calls to path_advance will return
2491  * the possible path expansions in sequence.  If an option (indicated by
2492  * a percent sign) appears in the path entry then the global variable
2493  * pathopt will be set to point to it; otherwise pathopt will be set to
2494  * NULL.
2495  */
2496 static const char *pathopt;     /* set by path_advance */
2497
2498 static char *
2499 path_advance(const char **path, const char *name)
2500 {
2501         const char *p;
2502         char *q;
2503         const char *start;
2504         size_t len;
2505
2506         if (*path == NULL)
2507                 return NULL;
2508         start = *path;
2509         for (p = start; *p && *p != ':' && *p != '%'; p++)
2510                 continue;
2511         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2512         while (stackblocksize() < len)
2513                 growstackblock();
2514         q = stackblock();
2515         if (p != start) {
2516                 q = mempcpy(q, start, p - start);
2517                 *q++ = '/';
2518         }
2519         strcpy(q, name);
2520         pathopt = NULL;
2521         if (*p == '%') {
2522                 pathopt = ++p;
2523                 while (*p && *p != ':')
2524                         p++;
2525         }
2526         if (*p == ':')
2527                 *path = p + 1;
2528         else
2529                 *path = NULL;
2530         return stalloc(len);
2531 }
2532
2533
2534 /* ============ Prompt */
2535
2536 static smallint doprompt;                   /* if set, prompt the user */
2537 static smallint needprompt;                 /* true if interactive and at start of line */
2538
2539 #if ENABLE_FEATURE_EDITING
2540 static line_input_t *line_input_state;
2541 static const char *cmdedit_prompt;
2542 static void
2543 putprompt(const char *s)
2544 {
2545         if (ENABLE_ASH_EXPAND_PRMT) {
2546                 free((char*)cmdedit_prompt);
2547                 cmdedit_prompt = ckstrdup(s);
2548                 return;
2549         }
2550         cmdedit_prompt = s;
2551 }
2552 #else
2553 static void
2554 putprompt(const char *s)
2555 {
2556         out2str(s);
2557 }
2558 #endif
2559
2560 /* expandstr() needs parsing machinery, so it is far away ahead... */
2561 static const char *expandstr(const char *ps, int syntax_type);
2562 /* Values for syntax param */
2563 #define BASESYNTAX 0    /* not in quotes */
2564 #define DQSYNTAX   1    /* in double quotes */
2565 #define SQSYNTAX   2    /* in single quotes */
2566 #define ARISYNTAX  3    /* in arithmetic */
2567 #if ENABLE_ASH_EXPAND_PRMT
2568 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2569 #endif
2570 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2571
2572 /*
2573  * called by editline -- any expansions to the prompt should be added here.
2574  */
2575 static void
2576 setprompt_if(smallint do_set, int whichprompt)
2577 {
2578         const char *prompt;
2579         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2580
2581         if (!do_set)
2582                 return;
2583
2584         needprompt = 0;
2585
2586         switch (whichprompt) {
2587         case 1:
2588                 prompt = ps1val();
2589                 break;
2590         case 2:
2591                 prompt = ps2val();
2592                 break;
2593         default:                        /* 0 */
2594                 prompt = nullstr;
2595         }
2596 #if ENABLE_ASH_EXPAND_PRMT
2597         pushstackmark(&smark, stackblocksize());
2598         putprompt(expandstr(prompt, PSSYNTAX));
2599         popstackmark(&smark);
2600 #else
2601         putprompt(prompt);
2602 #endif
2603 }
2604
2605
2606 /* ============ The cd and pwd commands */
2607
2608 #define CD_PHYSICAL 1
2609 #define CD_PRINT 2
2610
2611 static int
2612 cdopt(void)
2613 {
2614         int flags = 0;
2615         int i, j;
2616
2617         j = 'L';
2618         while ((i = nextopt("LP")) != '\0') {
2619                 if (i != j) {
2620                         flags ^= CD_PHYSICAL;
2621                         j = i;
2622                 }
2623         }
2624
2625         return flags;
2626 }
2627
2628 /*
2629  * Update curdir (the name of the current directory) in response to a
2630  * cd command.
2631  */
2632 static const char *
2633 updatepwd(const char *dir)
2634 {
2635         char *new;
2636         char *p;
2637         char *cdcomppath;
2638         const char *lim;
2639
2640         cdcomppath = sstrdup(dir);
2641         STARTSTACKSTR(new);
2642         if (*dir != '/') {
2643                 if (curdir == nullstr)
2644                         return 0;
2645                 new = stack_putstr(curdir, new);
2646         }
2647         new = makestrspace(strlen(dir) + 2, new);
2648         lim = (char *)stackblock() + 1;
2649         if (*dir != '/') {
2650                 if (new[-1] != '/')
2651                         USTPUTC('/', new);
2652                 if (new > lim && *lim == '/')
2653                         lim++;
2654         } else {
2655                 USTPUTC('/', new);
2656                 cdcomppath++;
2657                 if (dir[1] == '/' && dir[2] != '/') {
2658                         USTPUTC('/', new);
2659                         cdcomppath++;
2660                         lim++;
2661                 }
2662         }
2663         p = strtok(cdcomppath, "/");
2664         while (p) {
2665                 switch (*p) {
2666                 case '.':
2667                         if (p[1] == '.' && p[2] == '\0') {
2668                                 while (new > lim) {
2669                                         STUNPUTC(new);
2670                                         if (new[-1] == '/')
2671                                                 break;
2672                                 }
2673                                 break;
2674                         }
2675                         if (p[1] == '\0')
2676                                 break;
2677                         /* fall through */
2678                 default:
2679                         new = stack_putstr(p, new);
2680                         USTPUTC('/', new);
2681                 }
2682                 p = strtok(NULL, "/");
2683         }
2684         if (new > lim)
2685                 STUNPUTC(new);
2686         *new = 0;
2687         return stackblock();
2688 }
2689
2690 /*
2691  * Find out what the current directory is. If we already know the current
2692  * directory, this routine returns immediately.
2693  */
2694 static char *
2695 getpwd(void)
2696 {
2697         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2698         return dir ? dir : nullstr;
2699 }
2700
2701 static void
2702 setpwd(const char *val, int setold)
2703 {
2704         char *oldcur, *dir;
2705
2706         oldcur = dir = curdir;
2707
2708         if (setold) {
2709                 setvar("OLDPWD", oldcur, VEXPORT);
2710         }
2711         INT_OFF;
2712         if (physdir != nullstr) {
2713                 if (physdir != oldcur)
2714                         free(physdir);
2715                 physdir = nullstr;
2716         }
2717         if (oldcur == val || !val) {
2718                 char *s = getpwd();
2719                 physdir = s;
2720                 if (!val)
2721                         dir = s;
2722         } else
2723                 dir = ckstrdup(val);
2724         if (oldcur != dir && oldcur != nullstr) {
2725                 free(oldcur);
2726         }
2727         curdir = dir;
2728         INT_ON;
2729         setvar("PWD", dir, VEXPORT);
2730 }
2731
2732 static void hashcd(void);
2733
2734 /*
2735  * Actually do the chdir.  We also call hashcd to let other routines
2736  * know that the current directory has changed.
2737  */
2738 static int
2739 docd(const char *dest, int flags)
2740 {
2741         const char *dir = NULL;
2742         int err;
2743
2744         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2745
2746         INT_OFF;
2747         if (!(flags & CD_PHYSICAL)) {
2748                 dir = updatepwd(dest);
2749                 if (dir)
2750                         dest = dir;
2751         }
2752         err = chdir(dest);
2753         if (err)
2754                 goto out;
2755         setpwd(dir, 1);
2756         hashcd();
2757  out:
2758         INT_ON;
2759         return err;
2760 }
2761
2762 static int FAST_FUNC
2763 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2764 {
2765         const char *dest;
2766         const char *path;
2767         const char *p;
2768         char c;
2769         struct stat statb;
2770         int flags;
2771
2772         flags = cdopt();
2773         dest = *argptr;
2774         if (!dest)
2775                 dest = bltinlookup("HOME");
2776         else if (LONE_DASH(dest)) {
2777                 dest = bltinlookup("OLDPWD");
2778                 flags |= CD_PRINT;
2779         }
2780         if (!dest)
2781                 dest = nullstr;
2782         if (*dest == '/')
2783                 goto step6;
2784         if (*dest == '.') {
2785                 c = dest[1];
2786  dotdot:
2787                 switch (c) {
2788                 case '\0':
2789                 case '/':
2790                         goto step6;
2791                 case '.':
2792                         c = dest[2];
2793                         if (c != '.')
2794                                 goto dotdot;
2795                 }
2796         }
2797         if (!*dest)
2798                 dest = ".";
2799         path = bltinlookup("CDPATH");
2800         while (path) {
2801                 c = *path;
2802                 p = path_advance(&path, dest);
2803                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2804                         if (c && c != ':')
2805                                 flags |= CD_PRINT;
2806  docd:
2807                         if (!docd(p, flags))
2808                                 goto out;
2809                         goto err;
2810                 }
2811         }
2812
2813  step6:
2814         p = dest;
2815         goto docd;
2816
2817  err:
2818         ash_msg_and_raise_perror("can't cd to %s", dest);
2819         /* NOTREACHED */
2820  out:
2821         if (flags & CD_PRINT)
2822                 out1fmt("%s\n", curdir);
2823         return 0;
2824 }
2825
2826 static int FAST_FUNC
2827 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2828 {
2829         int flags;
2830         const char *dir = curdir;
2831
2832         flags = cdopt();
2833         if (flags) {
2834                 if (physdir == nullstr)
2835                         setpwd(dir, 0);
2836                 dir = physdir;
2837         }
2838         out1fmt("%s\n", dir);
2839         return 0;
2840 }
2841
2842
2843 /* ============ ... */
2844
2845
2846 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2847
2848 /* Syntax classes */
2849 #define CWORD     0             /* character is nothing special */
2850 #define CNL       1             /* newline character */
2851 #define CBACK     2             /* a backslash character */
2852 #define CSQUOTE   3             /* single quote */
2853 #define CDQUOTE   4             /* double quote */
2854 #define CENDQUOTE 5             /* a terminating quote */
2855 #define CBQUOTE   6             /* backwards single quote */
2856 #define CVAR      7             /* a dollar sign */
2857 #define CENDVAR   8             /* a '}' character */
2858 #define CLP       9             /* a left paren in arithmetic */
2859 #define CRP      10             /* a right paren in arithmetic */
2860 #define CENDFILE 11             /* end of file */
2861 #define CCTL     12             /* like CWORD, except it must be escaped */
2862 #define CSPCL    13             /* these terminate a word */
2863 #define CIGN     14             /* character should be ignored */
2864
2865 #define PEOF     256
2866 #if ENABLE_ASH_ALIAS
2867 # define PEOA    257
2868 #endif
2869
2870 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2871
2872 #if ENABLE_FEATURE_SH_MATH
2873 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2874 #else
2875 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2876 #endif
2877 static const uint16_t S_I_T[] ALIGN2 = {
2878 #if ENABLE_ASH_ALIAS
2879         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2880 #endif
2881         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2882         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2883         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2884         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2885         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2886         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2887         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2888         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2889         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2890         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2891         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2892 #if !USE_SIT_FUNCTION
2893         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2894         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2895         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2896 #endif
2897 #undef SIT_ITEM
2898 };
2899 /* Constants below must match table above */
2900 enum {
2901 #if ENABLE_ASH_ALIAS
2902         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2903 #endif
2904         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2905         CNL_CNL_CNL_CNL                    , /*  2 */
2906         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2907         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2908         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2909         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2910         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2911         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2912         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2913         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2914         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2915         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2916         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2917         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2918 };
2919
2920 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2921  * caller must ensure proper cast on it if c is *char_ptr!
2922  */
2923 #if USE_SIT_FUNCTION
2924
2925 static int
2926 SIT(int c, int syntax)
2927 {
2928         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2929         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2930         /*
2931          * This causes '/' to be prepended with CTLESC in dquoted string,
2932          * making "./file"* treated incorrectly because we feed
2933          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2934          * The "homegrown" glob implementation is okay with that,
2935          * but glibc one isn't. With '/' always treated as CWORD,
2936          * both work fine.
2937          */
2938 # if ENABLE_ASH_ALIAS
2939         static const uint8_t syntax_index_table[] ALIGN1 = {
2940                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2941                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2942                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2943                 11, 3                           /* "}~" */
2944         };
2945 # else
2946         static const uint8_t syntax_index_table[] ALIGN1 = {
2947                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2948                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2949                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2950                 10, 2                           /* "}~" */
2951         };
2952 # endif
2953         const char *s;
2954         int indx;
2955
2956         if (c == PEOF)
2957                 return CENDFILE;
2958 # if ENABLE_ASH_ALIAS
2959         if (c == PEOA)
2960                 indx = 0;
2961         else
2962 # endif
2963         {
2964                 /* Cast is purely for paranoia here,
2965                  * just in case someone passed signed char to us */
2966                 if ((unsigned char)c >= CTL_FIRST
2967                  && (unsigned char)c <= CTL_LAST
2968                 ) {
2969                         return CCTL;
2970                 }
2971                 s = strchrnul(spec_symbls, c);
2972                 if (*s == '\0')
2973                         return CWORD;
2974                 indx = syntax_index_table[s - spec_symbls];
2975         }
2976         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2977 }
2978
2979 #else   /* !USE_SIT_FUNCTION */
2980
2981 static const uint8_t syntax_index_table[] ALIGN1 = {
2982         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2983         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2984         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2985         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2986         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2987         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2988         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2989         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2990         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2991         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2992         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2993         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2994         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2995         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2996         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2997         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2998         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2999         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3000         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3001         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3002         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3003         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3004         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3005         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3006         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3007         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3008         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3009         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3010         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3011         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3012         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3013         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3014         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3015         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3016         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3017         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3018         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3019         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3020         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3021         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3022         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3023         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3024         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3025         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3026         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3027         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3028         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3029         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3030 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3031         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3032         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3033         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3034         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3035         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3036         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3037         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3038         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3039         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3040         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3041         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3042         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3043         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3044         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3045         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3046         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3047         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3048         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3049         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3050         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3051         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3053         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3054         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3055         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3056         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3057         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3058         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3059         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3060         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3061         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3062         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3063         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3064         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3065         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3066         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3067         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3074         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3075         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3076         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3077         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3078         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3079         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3081         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3084         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3085         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3086         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3087         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3088         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3089         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3090         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3091         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3092         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3093         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3094         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3095         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3096         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3097         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3098         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3099         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3100         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3101         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3102         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3103         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3104         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3105         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3106         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3107         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3108         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3109         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3110         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3111         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3112         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3113         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3114         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3115         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3116         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3117         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3118         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3119         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3120         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3121         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3240         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3241 # if ENABLE_ASH_ALIAS
3242         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3243 # endif
3244 };
3245
3246 #if 1
3247 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3248 #else /* debug version, caught one signed char bug */
3249 # define SIT(c, syntax) \
3250         ({ \
3251                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3252                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3253                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3254                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3255                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3256         })
3257 #endif
3258
3259 #endif  /* !USE_SIT_FUNCTION */
3260
3261
3262 /* ============ Alias handling */
3263
3264 #if ENABLE_ASH_ALIAS
3265
3266 #define ALIASINUSE 1
3267 #define ALIASDEAD  2
3268
3269 struct alias {
3270         struct alias *next;
3271         char *name;
3272         char *val;
3273         int flag;
3274 };
3275
3276
3277 static struct alias **atab; // [ATABSIZE];
3278 #define INIT_G_alias() do { \
3279         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3280 } while (0)
3281
3282
3283 static struct alias **
3284 __lookupalias(const char *name)
3285 {
3286         unsigned int hashval;
3287         struct alias **app;
3288         const char *p;
3289         unsigned int ch;
3290
3291         p = name;
3292
3293         ch = (unsigned char)*p;
3294         hashval = ch << 4;
3295         while (ch) {
3296                 hashval += ch;
3297                 ch = (unsigned char)*++p;
3298         }
3299         app = &atab[hashval % ATABSIZE];
3300
3301         for (; *app; app = &(*app)->next) {
3302                 if (strcmp(name, (*app)->name) == 0) {
3303                         break;
3304                 }
3305         }
3306
3307         return app;
3308 }
3309
3310 static struct alias *
3311 lookupalias(const char *name, int check)
3312 {
3313         struct alias *ap = *__lookupalias(name);
3314
3315         if (check && ap && (ap->flag & ALIASINUSE))
3316                 return NULL;
3317         return ap;
3318 }
3319
3320 static struct alias *
3321 freealias(struct alias *ap)
3322 {
3323         struct alias *next;
3324
3325         if (ap->flag & ALIASINUSE) {
3326                 ap->flag |= ALIASDEAD;
3327                 return ap;
3328         }
3329
3330         next = ap->next;
3331         free(ap->name);
3332         free(ap->val);
3333         free(ap);
3334         return next;
3335 }
3336
3337 static void
3338 setalias(const char *name, const char *val)
3339 {
3340         struct alias *ap, **app;
3341
3342         app = __lookupalias(name);
3343         ap = *app;
3344         INT_OFF;
3345         if (ap) {
3346                 if (!(ap->flag & ALIASINUSE)) {
3347                         free(ap->val);
3348                 }
3349                 ap->val = ckstrdup(val);
3350                 ap->flag &= ~ALIASDEAD;
3351         } else {
3352                 /* not found */
3353                 ap = ckzalloc(sizeof(struct alias));
3354                 ap->name = ckstrdup(name);
3355                 ap->val = ckstrdup(val);
3356                 /*ap->flag = 0; - ckzalloc did it */
3357                 /*ap->next = NULL;*/
3358                 *app = ap;
3359         }
3360         INT_ON;
3361 }
3362
3363 static int
3364 unalias(const char *name)
3365 {
3366         struct alias **app;
3367
3368         app = __lookupalias(name);
3369
3370         if (*app) {
3371                 INT_OFF;
3372                 *app = freealias(*app);
3373                 INT_ON;
3374                 return 0;
3375         }
3376
3377         return 1;
3378 }
3379
3380 static void
3381 rmaliases(void)
3382 {
3383         struct alias *ap, **app;
3384         int i;
3385
3386         INT_OFF;
3387         for (i = 0; i < ATABSIZE; i++) {
3388                 app = &atab[i];
3389                 for (ap = *app; ap; ap = *app) {
3390                         *app = freealias(*app);
3391                         if (ap == *app) {
3392                                 app = &ap->next;
3393                         }
3394                 }
3395         }
3396         INT_ON;
3397 }
3398
3399 static void
3400 printalias(const struct alias *ap)
3401 {
3402         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3403 }
3404
3405 /*
3406  * TODO - sort output
3407  */
3408 static int FAST_FUNC
3409 aliascmd(int argc UNUSED_PARAM, char **argv)
3410 {
3411         char *n, *v;
3412         int ret = 0;
3413         struct alias *ap;
3414
3415         if (!argv[1]) {
3416                 int i;
3417
3418                 for (i = 0; i < ATABSIZE; i++) {
3419                         for (ap = atab[i]; ap; ap = ap->next) {
3420                                 printalias(ap);
3421                         }
3422                 }
3423                 return 0;
3424         }
3425         while ((n = *++argv) != NULL) {
3426                 v = strchr(n+1, '=');
3427                 if (v == NULL) { /* n+1: funny ksh stuff */
3428                         ap = *__lookupalias(n);
3429                         if (ap == NULL) {
3430                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3431                                 ret = 1;
3432                         } else
3433                                 printalias(ap);
3434                 } else {
3435                         *v++ = '\0';
3436                         setalias(n, v);
3437                 }
3438         }
3439
3440         return ret;
3441 }
3442
3443 static int FAST_FUNC
3444 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3445 {
3446         int i;
3447
3448         while (nextopt("a") != '\0') {
3449                 rmaliases();
3450                 return 0;
3451         }
3452         for (i = 0; *argptr; argptr++) {
3453                 if (unalias(*argptr)) {
3454                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3455                         i = 1;
3456                 }
3457         }
3458
3459         return i;
3460 }
3461
3462 #endif /* ASH_ALIAS */
3463
3464
3465 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3466 #define FORK_FG    0
3467 #define FORK_BG    1
3468 #define FORK_NOJOB 2
3469
3470 /* mode flags for showjob(s) */
3471 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3472 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3473 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3474 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3475
3476 /*
3477  * A job structure contains information about a job.  A job is either a
3478  * single process or a set of processes contained in a pipeline.  In the
3479  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3480  * array of pids.
3481  */
3482 struct procstat {
3483         pid_t   ps_pid;         /* process id */
3484         int     ps_status;      /* last process status from wait() */
3485         char    *ps_cmd;        /* text of command being run */
3486 };
3487
3488 struct job {
3489         struct procstat ps0;    /* status of process */
3490         struct procstat *ps;    /* status or processes when more than one */
3491 #if JOBS
3492         int stopstatus;         /* status of a stopped job */
3493 #endif
3494         unsigned nprocs;        /* number of processes */
3495
3496 #define JOBRUNNING      0       /* at least one proc running */
3497 #define JOBSTOPPED      1       /* all procs are stopped */
3498 #define JOBDONE         2       /* all procs are completed */
3499         unsigned
3500                 state: 8,
3501 #if JOBS
3502                 sigint: 1,      /* job was killed by SIGINT */
3503                 jobctl: 1,      /* job running under job control */
3504 #endif
3505                 waited: 1,      /* true if this entry has been waited for */
3506                 used: 1,        /* true if this entry is in used */
3507                 changed: 1;     /* true if status has changed */
3508         struct job *prev_job;   /* previous job */
3509 };
3510
3511 static struct job *makejob(/*union node *,*/ int);
3512 static int forkshell(struct job *, union node *, int);
3513 static int waitforjob(struct job *);
3514
3515 #if !JOBS
3516 enum { doing_jobctl = 0 };
3517 #define setjobctl(on) do {} while (0)
3518 #else
3519 static smallint doing_jobctl; //references:8
3520 static void setjobctl(int);
3521 #endif
3522
3523 /*
3524  * Ignore a signal.
3525  */
3526 static void
3527 ignoresig(int signo)
3528 {
3529         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3530         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3531                 /* No, need to do it */
3532                 signal(signo, SIG_IGN);
3533         }
3534         sigmode[signo - 1] = S_HARD_IGN;
3535 }
3536
3537 /*
3538  * Only one usage site - in setsignal()
3539  */
3540 static void
3541 signal_handler(int signo)
3542 {
3543         if (signo == SIGCHLD) {
3544                 got_sigchld = 1;
3545                 if (!trap[SIGCHLD])
3546                         return;
3547         }
3548
3549         gotsig[signo - 1] = 1;
3550         pending_sig = signo;
3551
3552         if (signo == SIGINT && !trap[SIGINT]) {
3553                 if (!suppress_int) {
3554                         pending_sig = 0;
3555                         raise_interrupt(); /* does not return */
3556                 }
3557                 pending_int = 1;
3558         }
3559 }
3560
3561 /*
3562  * Set the signal handler for the specified signal.  The routine figures
3563  * out what it should be set to.
3564  */
3565 static void
3566 setsignal(int signo)
3567 {
3568         char *t;
3569         char cur_act, new_act;
3570         struct sigaction act;
3571
3572         t = trap[signo];
3573         new_act = S_DFL;
3574         if (t != NULL) { /* trap for this sig is set */
3575                 new_act = S_CATCH;
3576                 if (t[0] == '\0') /* trap is "": ignore this sig */
3577                         new_act = S_IGN;
3578         }
3579
3580         if (rootshell && new_act == S_DFL) {
3581                 switch (signo) {
3582                 case SIGINT:
3583                         if (iflag || minusc || sflag == 0)
3584                                 new_act = S_CATCH;
3585                         break;
3586                 case SIGQUIT:
3587 #if DEBUG
3588                         if (debug)
3589                                 break;
3590 #endif
3591                         /* man bash:
3592                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3593                          * commands run by bash have signal handlers
3594                          * set to the values inherited by the shell
3595                          * from its parent". */
3596                         new_act = S_IGN;
3597                         break;
3598                 case SIGTERM:
3599                         if (iflag)
3600                                 new_act = S_IGN;
3601                         break;
3602 #if JOBS
3603                 case SIGTSTP:
3604                 case SIGTTOU:
3605                         if (mflag)
3606                                 new_act = S_IGN;
3607                         break;
3608 #endif
3609                 }
3610         }
3611         /* if !rootshell, we reset SIGQUIT to DFL,
3612          * whereas we have to restore it to what shell got on entry.
3613          * This is handled by the fact that if signal was IGNored on entry,
3614          * then cur_act is S_HARD_IGN and we never change its sigaction
3615          * (see code below).
3616          */
3617
3618         if (signo == SIGCHLD)
3619                 new_act = S_CATCH;
3620
3621         t = &sigmode[signo - 1];
3622         cur_act = *t;
3623         if (cur_act == 0) {
3624                 /* current setting is not yet known */
3625                 if (sigaction(signo, NULL, &act)) {
3626                         /* pretend it worked; maybe we should give a warning,
3627                          * but other shells don't. We don't alter sigmode,
3628                          * so we retry every time.
3629                          * btw, in Linux it never fails. --vda */
3630                         return;
3631                 }
3632                 if (act.sa_handler == SIG_IGN) {
3633                         cur_act = S_HARD_IGN;
3634                         if (mflag
3635                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3636                         ) {
3637                                 cur_act = S_IGN;   /* don't hard ignore these */
3638                         }
3639                 }
3640                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3641                         /* installing SIG_DFL over SIG_DFL is a no-op */
3642                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3643                         *t = S_DFL;
3644                         return;
3645                 }
3646         }
3647         if (cur_act == S_HARD_IGN || cur_act == new_act)
3648                 return;
3649
3650         *t = new_act;
3651
3652         act.sa_handler = SIG_DFL;
3653         switch (new_act) {
3654         case S_CATCH:
3655                 act.sa_handler = signal_handler;
3656                 break;
3657         case S_IGN:
3658                 act.sa_handler = SIG_IGN;
3659                 break;
3660         }
3661         /* flags and mask matter only if !DFL and !IGN, but we do it
3662          * for all cases for more deterministic behavior:
3663          */
3664         act.sa_flags = 0; //TODO: why not SA_RESTART?
3665         sigfillset(&act.sa_mask);
3666
3667         sigaction_set(signo, &act);
3668 }
3669
3670 /* mode flags for set_curjob */
3671 #define CUR_DELETE 2
3672 #define CUR_RUNNING 1
3673 #define CUR_STOPPED 0
3674
3675 #if JOBS
3676 /* pgrp of shell on invocation */
3677 static int initialpgrp; //references:2
3678 static int ttyfd = -1; //5
3679 #endif
3680 /* array of jobs */
3681 static struct job *jobtab; //5
3682 /* size of array */
3683 static unsigned njobs; //4
3684 /* current job */
3685 static struct job *curjob; //lots
3686 /* number of presumed living untracked jobs */
3687 static int jobless; //4
3688
3689 #if 0
3690 /* Bash has a feature: it restores termios after a successful wait for
3691  * a foreground job which had at least one stopped or sigkilled member.
3692  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3693  * properly restoring tty state. Should we do this too?
3694  * A reproducer: ^Z an interactive python:
3695  *
3696  * # python
3697  * Python 2.7.12 (...)
3698  * >>> ^Z
3699  *      { python leaves tty in -icanon -echo state. We do survive that... }
3700  *  [1]+  Stopped                    python
3701  *      { ...however, next program (python #2) does not survive it well: }
3702  * # python
3703  * Python 2.7.12 (...)
3704  * >>> Traceback (most recent call last):
3705  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3706  *   File "<stdin>", line 1, in <module>
3707  * NameError: name 'qwerty' is not defined
3708  *
3709  * The implementation below is modeled on bash code and seems to work.
3710  * However, I'm not sure we should do this. For one: what if I'd fg
3711  * the stopped python instead? It'll be confused by "restored" tty state.
3712  */
3713 static struct termios shell_tty_info;
3714 static void
3715 get_tty_state(void)
3716 {
3717         if (rootshell && ttyfd >= 0)
3718                 tcgetattr(ttyfd, &shell_tty_info);
3719 }
3720 static void
3721 set_tty_state(void)
3722 {
3723         /* if (rootshell) - caller ensures this */
3724         if (ttyfd >= 0)
3725                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3726 }
3727 static int
3728 job_signal_status(struct job *jp)
3729 {
3730         int status;
3731         unsigned i;
3732         struct procstat *ps = jp->ps;
3733         for (i = 0; i < jp->nprocs; i++) {
3734                 status = ps[i].ps_status;
3735                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3736                         return status;
3737         }
3738         return 0;
3739 }
3740 static void
3741 restore_tty_if_stopped_or_signaled(struct job *jp)
3742 {
3743 //TODO: check what happens if we come from waitforjob() in expbackq()
3744         if (rootshell) {
3745                 int s = job_signal_status(jp);
3746                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3747                         set_tty_state();
3748         }
3749 }
3750 #else
3751 # define get_tty_state() ((void)0)
3752 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3753 #endif
3754
3755 static void
3756 set_curjob(struct job *jp, unsigned mode)
3757 {
3758         struct job *jp1;
3759         struct job **jpp, **curp;
3760
3761         /* first remove from list */
3762         jpp = curp = &curjob;
3763         while (1) {
3764                 jp1 = *jpp;
3765                 if (jp1 == jp)
3766                         break;
3767                 jpp = &jp1->prev_job;
3768         }
3769         *jpp = jp1->prev_job;
3770
3771         /* Then re-insert in correct position */
3772         jpp = curp;
3773         switch (mode) {
3774         default:
3775 #if DEBUG
3776                 abort();
3777 #endif
3778         case CUR_DELETE:
3779                 /* job being deleted */
3780                 break;
3781         case CUR_RUNNING:
3782                 /* newly created job or backgrounded job,
3783                  * put after all stopped jobs.
3784                  */
3785                 while (1) {
3786                         jp1 = *jpp;
3787 #if JOBS
3788                         if (!jp1 || jp1->state != JOBSTOPPED)
3789 #endif
3790                                 break;
3791                         jpp = &jp1->prev_job;
3792                 }
3793                 /* FALLTHROUGH */
3794 #if JOBS
3795         case CUR_STOPPED:
3796 #endif
3797                 /* newly stopped job - becomes curjob */
3798                 jp->prev_job = *jpp;
3799                 *jpp = jp;
3800                 break;
3801         }
3802 }
3803
3804 #if JOBS || DEBUG
3805 static int
3806 jobno(const struct job *jp)
3807 {
3808         return jp - jobtab + 1;
3809 }
3810 #endif
3811
3812 /*
3813  * Convert a job name to a job structure.
3814  */
3815 #if !JOBS
3816 #define getjob(name, getctl) getjob(name)
3817 #endif
3818 static struct job *
3819 getjob(const char *name, int getctl)
3820 {
3821         struct job *jp;
3822         struct job *found;
3823         const char *err_msg = "%s: no such job";
3824         unsigned num;
3825         int c;
3826         const char *p;
3827         char *(*match)(const char *, const char *);
3828
3829         jp = curjob;
3830         p = name;
3831         if (!p)
3832                 goto currentjob;
3833
3834         if (*p != '%')
3835                 goto err;
3836
3837         c = *++p;
3838         if (!c)
3839                 goto currentjob;
3840
3841         if (!p[1]) {
3842                 if (c == '+' || c == '%') {
3843  currentjob:
3844                         err_msg = "No current job";
3845                         goto check;
3846                 }
3847                 if (c == '-') {
3848                         if (jp)
3849                                 jp = jp->prev_job;
3850                         err_msg = "No previous job";
3851  check:
3852                         if (!jp)
3853                                 goto err;
3854                         goto gotit;
3855                 }
3856         }
3857
3858         if (is_number(p)) {
3859                 num = atoi(p);
3860                 if (num > 0 && num <= njobs) {
3861                         jp = jobtab + num - 1;
3862                         if (jp->used)
3863                                 goto gotit;
3864                         goto err;
3865                 }
3866         }
3867
3868         match = prefix;
3869         if (*p == '?') {
3870                 match = strstr;
3871                 p++;
3872         }
3873
3874         found = NULL;
3875         while (jp) {
3876                 if (match(jp->ps[0].ps_cmd, p)) {
3877                         if (found)
3878                                 goto err;
3879                         found = jp;
3880                         err_msg = "%s: ambiguous";
3881                 }
3882                 jp = jp->prev_job;
3883         }
3884         if (!found)
3885                 goto err;
3886         jp = found;
3887
3888  gotit:
3889 #if JOBS
3890         err_msg = "job %s not created under job control";
3891         if (getctl && jp->jobctl == 0)
3892                 goto err;
3893 #endif
3894         return jp;
3895  err:
3896         ash_msg_and_raise_error(err_msg, name);
3897 }
3898
3899 /*
3900  * Mark a job structure as unused.
3901  */
3902 static void
3903 freejob(struct job *jp)
3904 {
3905         struct procstat *ps;
3906         int i;
3907
3908         INT_OFF;
3909         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3910                 if (ps->ps_cmd != nullstr)
3911                         free(ps->ps_cmd);
3912         }
3913         if (jp->ps != &jp->ps0)
3914                 free(jp->ps);
3915         jp->used = 0;
3916         set_curjob(jp, CUR_DELETE);
3917         INT_ON;
3918 }
3919
3920 #if JOBS
3921 static void
3922 xtcsetpgrp(int fd, pid_t pgrp)
3923 {
3924         if (tcsetpgrp(fd, pgrp))
3925                 ash_msg_and_raise_perror("can't set tty process group");
3926 }
3927
3928 /*
3929  * Turn job control on and off.
3930  *
3931  * Note:  This code assumes that the third arg to ioctl is a character
3932  * pointer, which is true on Berkeley systems but not System V.  Since
3933  * System V doesn't have job control yet, this isn't a problem now.
3934  *
3935  * Called with interrupts off.
3936  */
3937 static void
3938 setjobctl(int on)
3939 {
3940         int fd;
3941         int pgrp;
3942
3943         if (on == doing_jobctl || rootshell == 0)
3944                 return;
3945         if (on) {
3946                 int ofd;
3947                 ofd = fd = open(_PATH_TTY, O_RDWR);
3948                 if (fd < 0) {
3949         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3950          * That sometimes helps to acquire controlling tty.
3951          * Obviously, a workaround for bugs when someone
3952          * failed to provide a controlling tty to bash! :) */
3953                         fd = 2;
3954                         while (!isatty(fd))
3955                                 if (--fd < 0)
3956                                         goto out;
3957                 }
3958                 /* fd is a tty at this point */
3959                 fd = fcntl(fd, F_DUPFD, 10);
3960                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3961                         close(ofd);
3962                 if (fd < 0)
3963                         goto out; /* F_DUPFD failed */
3964                 close_on_exec_on(fd);
3965                 while (1) { /* while we are in the background */
3966                         pgrp = tcgetpgrp(fd);
3967                         if (pgrp < 0) {
3968  out:
3969                                 ash_msg("can't access tty; job control turned off");
3970                                 mflag = on = 0;
3971                                 goto close;
3972                         }
3973                         if (pgrp == getpgrp())
3974                                 break;
3975                         killpg(0, SIGTTIN);
3976                 }
3977                 initialpgrp = pgrp;
3978
3979                 setsignal(SIGTSTP);
3980                 setsignal(SIGTTOU);
3981                 setsignal(SIGTTIN);
3982                 pgrp = rootpid;
3983                 setpgid(0, pgrp);
3984                 xtcsetpgrp(fd, pgrp);
3985         } else {
3986                 /* turning job control off */
3987                 fd = ttyfd;
3988                 pgrp = initialpgrp;
3989                 /* was xtcsetpgrp, but this can make exiting ash
3990                  * loop forever if pty is already deleted */
3991                 tcsetpgrp(fd, pgrp);
3992                 setpgid(0, pgrp);
3993                 setsignal(SIGTSTP);
3994                 setsignal(SIGTTOU);
3995                 setsignal(SIGTTIN);
3996  close:
3997                 if (fd >= 0)
3998                         close(fd);
3999                 fd = -1;
4000         }
4001         ttyfd = fd;
4002         doing_jobctl = on;
4003 }
4004
4005 static int FAST_FUNC
4006 killcmd(int argc, char **argv)
4007 {
4008         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4009                 int i = 1;
4010                 do {
4011                         if (argv[i][0] == '%') {
4012                                 /*
4013                                  * "kill %N" - job kill
4014                                  * Converting to pgrp / pid kill
4015                                  */
4016                                 struct job *jp;
4017                                 char *dst;
4018                                 int j, n;
4019
4020                                 jp = getjob(argv[i], 0);
4021                                 /*
4022                                  * In jobs started under job control, we signal
4023                                  * entire process group by kill -PGRP_ID.
4024                                  * This happens, f.e., in interactive shell.
4025                                  *
4026                                  * Otherwise, we signal each child via
4027                                  * kill PID1 PID2 PID3.
4028                                  * Testcases:
4029                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4030                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4031                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4032                                  */
4033                                 n = jp->nprocs; /* can't be 0 (I hope) */
4034                                 if (jp->jobctl)
4035                                         n = 1;
4036                                 dst = alloca(n * sizeof(int)*4);
4037                                 argv[i] = dst;
4038                                 for (j = 0; j < n; j++) {
4039                                         struct procstat *ps = &jp->ps[j];
4040                                         /* Skip non-running and not-stopped members
4041                                          * (i.e. dead members) of the job
4042                                          */
4043                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4044                                                 continue;
4045                                         /*
4046                                          * kill_main has matching code to expect
4047                                          * leading space. Needed to not confuse
4048                                          * negative pids with "kill -SIGNAL_NO" syntax
4049                                          */
4050                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4051                                 }
4052                                 *dst = '\0';
4053                         }
4054                 } while (argv[++i]);
4055         }
4056         return kill_main(argc, argv);
4057 }
4058
4059 static void
4060 showpipe(struct job *jp /*, FILE *out*/)
4061 {
4062         struct procstat *ps;
4063         struct procstat *psend;
4064
4065         psend = jp->ps + jp->nprocs;
4066         for (ps = jp->ps + 1; ps < psend; ps++)
4067                 printf(" | %s", ps->ps_cmd);
4068         newline_and_flush(stdout);
4069         flush_stdout_stderr();
4070 }
4071
4072
4073 static int
4074 restartjob(struct job *jp, int mode)
4075 {
4076         struct procstat *ps;
4077         int i;
4078         int status;
4079         pid_t pgid;
4080
4081         INT_OFF;
4082         if (jp->state == JOBDONE)
4083                 goto out;
4084         jp->state = JOBRUNNING;
4085         pgid = jp->ps[0].ps_pid;
4086         if (mode == FORK_FG) {
4087                 get_tty_state();
4088                 xtcsetpgrp(ttyfd, pgid);
4089         }
4090         killpg(pgid, SIGCONT);
4091         ps = jp->ps;
4092         i = jp->nprocs;
4093         do {
4094                 if (WIFSTOPPED(ps->ps_status)) {
4095                         ps->ps_status = -1;
4096                 }
4097                 ps++;
4098         } while (--i);
4099  out:
4100         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4101         INT_ON;
4102         return status;
4103 }
4104
4105 static int FAST_FUNC
4106 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4107 {
4108         struct job *jp;
4109         int mode;
4110         int retval;
4111
4112         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4113         nextopt(nullstr);
4114         argv = argptr;
4115         do {
4116                 jp = getjob(*argv, 1);
4117                 if (mode == FORK_BG) {
4118                         set_curjob(jp, CUR_RUNNING);
4119                         printf("[%d] ", jobno(jp));
4120                 }
4121                 out1str(jp->ps[0].ps_cmd);
4122                 showpipe(jp /*, stdout*/);
4123                 retval = restartjob(jp, mode);
4124         } while (*argv && *++argv);
4125         return retval;
4126 }
4127 #endif
4128
4129 static int
4130 sprint_status48(char *s, int status, int sigonly)
4131 {
4132         int col;
4133         int st;
4134
4135         col = 0;
4136         if (!WIFEXITED(status)) {
4137 #if JOBS
4138                 if (WIFSTOPPED(status))
4139                         st = WSTOPSIG(status);
4140                 else
4141 #endif
4142                         st = WTERMSIG(status);
4143                 if (sigonly) {
4144                         if (st == SIGINT || st == SIGPIPE)
4145                                 goto out;
4146 #if JOBS
4147                         if (WIFSTOPPED(status))
4148                                 goto out;
4149 #endif
4150                 }
4151                 st &= 0x7f;
4152 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4153                 col = fmtstr(s, 32, strsignal(st));
4154                 if (WCOREDUMP(status)) {
4155                         strcpy(s + col, " (core dumped)");
4156                         col += sizeof(" (core dumped)")-1;
4157                 }
4158         } else if (!sigonly) {
4159                 st = WEXITSTATUS(status);
4160                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4161         }
4162  out:
4163         return col;
4164 }
4165
4166 static int
4167 wait_block_or_sig(int *status)
4168 {
4169         int pid;
4170
4171         do {
4172                 sigset_t mask;
4173
4174                 /* Poll all children for changes in their state */
4175                 got_sigchld = 0;
4176                 /* if job control is active, accept stopped processes too */
4177                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4178                 if (pid != 0)
4179                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4180
4181                 /* Children exist, but none are ready. Sleep until interesting signal */
4182 #if 1
4183                 sigfillset(&mask);
4184                 sigprocmask(SIG_SETMASK, &mask, &mask);
4185                 while (!got_sigchld && !pending_sig)
4186                         sigsuspend(&mask);
4187                 sigprocmask(SIG_SETMASK, &mask, NULL);
4188 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4189                 while (!got_sigchld && !pending_sig)
4190                         pause();
4191 #endif
4192
4193                 /* If it was SIGCHLD, poll children again */
4194         } while (got_sigchld);
4195
4196         return pid;
4197 }
4198
4199 #define DOWAIT_NONBLOCK 0
4200 #define DOWAIT_BLOCK    1
4201 #define DOWAIT_BLOCK_OR_SIG 2
4202
4203 static int
4204 dowait(int block, struct job *job)
4205 {
4206         int pid;
4207         int status;
4208         struct job *jp;
4209         struct job *thisjob = NULL;
4210
4211         TRACE(("dowait(0x%x) called\n", block));
4212
4213         /* It's wrong to call waitpid() outside of INT_OFF region:
4214          * signal can arrive just after syscall return and handler can
4215          * longjmp away, losing stop/exit notification processing.
4216          * Thus, for "jobs" builtin, and for waiting for a fg job,
4217          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4218          *
4219          * However, for "wait" builtin it is wrong to simply call waitpid()
4220          * in INT_OFF region: "wait" needs to wait for any running job
4221          * to change state, but should exit on any trap too.
4222          * In INT_OFF region, a signal just before syscall entry can set
4223          * pending_sig variables, but we can't check them, and we would
4224          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4225          *
4226          * Because of this, we run inside INT_OFF, but use a special routine
4227          * which combines waitpid() and sigsuspend().
4228          * This is the reason why we need to have a handler for SIGCHLD:
4229          * SIG_DFL handler does not wake sigsuspend().
4230          */
4231         INT_OFF;
4232         if (block == DOWAIT_BLOCK_OR_SIG) {
4233                 pid = wait_block_or_sig(&status);
4234         } else {
4235                 int wait_flags = 0;
4236                 if (block == DOWAIT_NONBLOCK)
4237                         wait_flags = WNOHANG;
4238                 /* if job control is active, accept stopped processes too */
4239                 if (doing_jobctl)
4240                         wait_flags |= WUNTRACED;
4241                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4242                 pid = waitpid(-1, &status, wait_flags);
4243         }
4244         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4245                                 pid, status, errno, strerror(errno)));
4246         if (pid <= 0)
4247                 goto out;
4248
4249         thisjob = NULL;
4250         for (jp = curjob; jp; jp = jp->prev_job) {
4251                 int jobstate;
4252                 struct procstat *ps;
4253                 struct procstat *psend;
4254                 if (jp->state == JOBDONE)
4255                         continue;
4256                 jobstate = JOBDONE;
4257                 ps = jp->ps;
4258                 psend = ps + jp->nprocs;
4259                 do {
4260                         if (ps->ps_pid == pid) {
4261                                 TRACE(("Job %d: changing status of proc %d "
4262                                         "from 0x%x to 0x%x\n",
4263                                         jobno(jp), pid, ps->ps_status, status));
4264                                 ps->ps_status = status;
4265                                 thisjob = jp;
4266                         }
4267                         if (ps->ps_status == -1)
4268                                 jobstate = JOBRUNNING;
4269 #if JOBS
4270                         if (jobstate == JOBRUNNING)
4271                                 continue;
4272                         if (WIFSTOPPED(ps->ps_status)) {
4273                                 jp->stopstatus = ps->ps_status;
4274                                 jobstate = JOBSTOPPED;
4275                         }
4276 #endif
4277                 } while (++ps < psend);
4278                 if (!thisjob)
4279                         continue;
4280
4281                 /* Found the job where one of its processes changed its state.
4282                  * Is there at least one live and running process in this job? */
4283                 if (jobstate != JOBRUNNING) {
4284                         /* No. All live processes in the job are stopped
4285                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4286                          */
4287                         thisjob->changed = 1;
4288                         if (thisjob->state != jobstate) {
4289                                 TRACE(("Job %d: changing state from %d to %d\n",
4290                                         jobno(thisjob), thisjob->state, jobstate));
4291                                 thisjob->state = jobstate;
4292 #if JOBS
4293                                 if (jobstate == JOBSTOPPED)
4294                                         set_curjob(thisjob, CUR_STOPPED);
4295 #endif
4296                         }
4297                 }
4298                 goto out;
4299         }
4300         /* The process wasn't found in job list */
4301 #if JOBS
4302         if (!WIFSTOPPED(status))
4303                 jobless--;
4304 #endif
4305  out:
4306         INT_ON;
4307
4308         if (thisjob && thisjob == job) {
4309                 char s[48 + 1];
4310                 int len;
4311
4312                 len = sprint_status48(s, status, 1);
4313                 if (len) {
4314                         s[len] = '\n';
4315                         s[len + 1] = '\0';
4316                         out2str(s);
4317                 }
4318         }
4319         return pid;
4320 }
4321
4322 #if JOBS
4323 static void
4324 showjob(struct job *jp, int mode)
4325 {
4326         struct procstat *ps;
4327         struct procstat *psend;
4328         int col;
4329         int indent_col;
4330         char s[16 + 16 + 48];
4331         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4332
4333         ps = jp->ps;
4334
4335         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4336                 /* just output process (group) id of pipeline */
4337                 fprintf(out, "%d\n", ps->ps_pid);
4338                 return;
4339         }
4340
4341         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4342         indent_col = col;
4343
4344         if (jp == curjob)
4345                 s[col - 3] = '+';
4346         else if (curjob && jp == curjob->prev_job)
4347                 s[col - 3] = '-';
4348
4349         if (mode & SHOW_PIDS)
4350                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4351
4352         psend = ps + jp->nprocs;
4353
4354         if (jp->state == JOBRUNNING) {
4355                 strcpy(s + col, "Running");
4356                 col += sizeof("Running") - 1;
4357         } else {
4358                 int status = psend[-1].ps_status;
4359                 if (jp->state == JOBSTOPPED)
4360                         status = jp->stopstatus;
4361                 col += sprint_status48(s + col, status, 0);
4362         }
4363         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4364
4365         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4366          * or prints several "PID             | <cmdN>" lines,
4367          * depending on SHOW_PIDS bit.
4368          * We do not print status of individual processes
4369          * between PID and <cmdN>. bash does it, but not very well:
4370          * first line shows overall job status, not process status,
4371          * making it impossible to know 1st process status.
4372          */
4373         goto start;
4374         do {
4375                 /* for each process */
4376                 s[0] = '\0';
4377                 col = 33;
4378                 if (mode & SHOW_PIDS)
4379                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4380  start:
4381                 fprintf(out, "%s%*c%s%s",
4382                                 s,
4383                                 33 - col >= 0 ? 33 - col : 0, ' ',
4384                                 ps == jp->ps ? "" : "| ",
4385                                 ps->ps_cmd
4386                 );
4387         } while (++ps != psend);
4388         newline_and_flush(out);
4389
4390         jp->changed = 0;
4391
4392         if (jp->state == JOBDONE) {
4393                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4394                 freejob(jp);
4395         }
4396 }
4397
4398 /*
4399  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4400  * statuses have changed since the last call to showjobs.
4401  */
4402 static void
4403 showjobs(int mode)
4404 {
4405         struct job *jp;
4406
4407         TRACE(("showjobs(0x%x) called\n", mode));
4408
4409         /* Handle all finished jobs */
4410         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4411                 continue;
4412
4413         for (jp = curjob; jp; jp = jp->prev_job) {
4414                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4415                         showjob(jp, mode);
4416                 }
4417         }
4418 }
4419
4420 static int FAST_FUNC
4421 jobscmd(int argc UNUSED_PARAM, char **argv)
4422 {
4423         int mode, m;
4424
4425         mode = 0;
4426         while ((m = nextopt("lp")) != '\0') {
4427                 if (m == 'l')
4428                         mode |= SHOW_PIDS;
4429                 else
4430                         mode |= SHOW_ONLY_PGID;
4431         }
4432
4433         argv = argptr;
4434         if (*argv) {
4435                 do
4436                         showjob(getjob(*argv, 0), mode);
4437                 while (*++argv);
4438         } else {
4439                 showjobs(mode);
4440         }
4441
4442         return 0;
4443 }
4444 #endif /* JOBS */
4445
4446 /* Called only on finished or stopped jobs (no members are running) */
4447 static int
4448 getstatus(struct job *job)
4449 {
4450         int status;
4451         int retval;
4452         struct procstat *ps;
4453
4454         /* Fetch last member's status */
4455         ps = job->ps + job->nprocs - 1;
4456         status = ps->ps_status;
4457         if (pipefail) {
4458                 /* "set -o pipefail" mode: use last _nonzero_ status */
4459                 while (status == 0 && --ps >= job->ps)
4460                         status = ps->ps_status;
4461         }
4462
4463         retval = WEXITSTATUS(status);
4464         if (!WIFEXITED(status)) {
4465 #if JOBS
4466                 retval = WSTOPSIG(status);
4467                 if (!WIFSTOPPED(status))
4468 #endif
4469                 {
4470                         /* XXX: limits number of signals */
4471                         retval = WTERMSIG(status);
4472 #if JOBS
4473                         if (retval == SIGINT)
4474                                 job->sigint = 1;
4475 #endif
4476                 }
4477                 retval += 128;
4478         }
4479         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4480                 jobno(job), job->nprocs, status, retval));
4481         return retval;
4482 }
4483
4484 static int FAST_FUNC
4485 waitcmd(int argc UNUSED_PARAM, char **argv)
4486 {
4487         struct job *job;
4488         int retval;
4489         struct job *jp;
4490
4491         nextopt(nullstr);
4492         retval = 0;
4493
4494         argv = argptr;
4495         if (!*argv) {
4496                 /* wait for all jobs */
4497                 for (;;) {
4498                         jp = curjob;
4499                         while (1) {
4500                                 if (!jp) /* no running procs */
4501                                         goto ret;
4502                                 if (jp->state == JOBRUNNING)
4503                                         break;
4504                                 jp->waited = 1;
4505                                 jp = jp->prev_job;
4506                         }
4507         /* man bash:
4508          * "When bash is waiting for an asynchronous command via
4509          * the wait builtin, the reception of a signal for which a trap
4510          * has been set will cause the wait builtin to return immediately
4511          * with an exit status greater than 128, immediately after which
4512          * the trap is executed."
4513          */
4514                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4515         /* if child sends us a signal *and immediately exits*,
4516          * dowait() returns pid > 0. Check this case,
4517          * not "if (dowait() < 0)"!
4518          */
4519                         if (pending_sig)
4520                                 goto sigout;
4521                 }
4522         }
4523
4524         retval = 127;
4525         do {
4526                 if (**argv != '%') {
4527                         pid_t pid = number(*argv);
4528                         job = curjob;
4529                         while (1) {
4530                                 if (!job)
4531                                         goto repeat;
4532                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4533                                         break;
4534                                 job = job->prev_job;
4535                         }
4536                 } else {
4537                         job = getjob(*argv, 0);
4538                 }
4539                 /* loop until process terminated or stopped */
4540                 while (job->state == JOBRUNNING) {
4541                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4542                         if (pending_sig)
4543                                 goto sigout;
4544                 }
4545                 job->waited = 1;
4546                 retval = getstatus(job);
4547  repeat: ;
4548         } while (*++argv);
4549
4550  ret:
4551         return retval;
4552  sigout:
4553         retval = 128 + pending_sig;
4554         return retval;
4555 }
4556
4557 static struct job *
4558 growjobtab(void)
4559 {
4560         size_t len;
4561         ptrdiff_t offset;
4562         struct job *jp, *jq;
4563
4564         len = njobs * sizeof(*jp);
4565         jq = jobtab;
4566         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4567
4568         offset = (char *)jp - (char *)jq;
4569         if (offset) {
4570                 /* Relocate pointers */
4571                 size_t l = len;
4572
4573                 jq = (struct job *)((char *)jq + l);
4574                 while (l) {
4575                         l -= sizeof(*jp);
4576                         jq--;
4577 #define joff(p) ((struct job *)((char *)(p) + l))
4578 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4579                         if (joff(jp)->ps == &jq->ps0)
4580                                 jmove(joff(jp)->ps);
4581                         if (joff(jp)->prev_job)
4582                                 jmove(joff(jp)->prev_job);
4583                 }
4584                 if (curjob)
4585                         jmove(curjob);
4586 #undef joff
4587 #undef jmove
4588         }
4589
4590         njobs += 4;
4591         jobtab = jp;
4592         jp = (struct job *)((char *)jp + len);
4593         jq = jp + 3;
4594         do {
4595                 jq->used = 0;
4596         } while (--jq >= jp);
4597         return jp;
4598 }
4599
4600 /*
4601  * Return a new job structure.
4602  * Called with interrupts off.
4603  */
4604 static struct job *
4605 makejob(/*union node *node,*/ int nprocs)
4606 {
4607         int i;
4608         struct job *jp;
4609
4610         for (i = njobs, jp = jobtab; ; jp++) {
4611                 if (--i < 0) {
4612                         jp = growjobtab();
4613                         break;
4614                 }
4615                 if (jp->used == 0)
4616                         break;
4617                 if (jp->state != JOBDONE || !jp->waited)
4618                         continue;
4619 #if JOBS
4620                 if (doing_jobctl)
4621                         continue;
4622 #endif
4623                 freejob(jp);
4624                 break;
4625         }
4626         memset(jp, 0, sizeof(*jp));
4627 #if JOBS
4628         /* jp->jobctl is a bitfield.
4629          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4630         if (doing_jobctl)
4631                 jp->jobctl = 1;
4632 #endif
4633         jp->prev_job = curjob;
4634         curjob = jp;
4635         jp->used = 1;
4636         jp->ps = &jp->ps0;
4637         if (nprocs > 1) {
4638                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4639         }
4640         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4641                                 jobno(jp)));
4642         return jp;
4643 }
4644
4645 #if JOBS
4646 /*
4647  * Return a string identifying a command (to be printed by the
4648  * jobs command).
4649  */
4650 static char *cmdnextc;
4651
4652 static void
4653 cmdputs(const char *s)
4654 {
4655         static const char vstype[VSTYPE + 1][3] = {
4656                 "", "}", "-", "+", "?", "=",
4657                 "%", "%%", "#", "##"
4658                 IF_BASH_SUBSTR(, ":")
4659                 IF_BASH_PATTERN_SUBST(, "/", "//")
4660         };
4661
4662         const char *p, *str;
4663         char cc[2];
4664         char *nextc;
4665         unsigned char c;
4666         unsigned char subtype = 0;
4667         int quoted = 0;
4668
4669         cc[1] = '\0';
4670         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4671         p = s;
4672         while ((c = *p++) != '\0') {
4673                 str = NULL;
4674                 switch (c) {
4675                 case CTLESC:
4676                         c = *p++;
4677                         break;
4678                 case CTLVAR:
4679                         subtype = *p++;
4680                         if ((subtype & VSTYPE) == VSLENGTH)
4681                                 str = "${#";
4682                         else
4683                                 str = "${";
4684                         goto dostr;
4685                 case CTLENDVAR:
4686                         str = "\"}" + !(quoted & 1);
4687                         quoted >>= 1;
4688                         subtype = 0;
4689                         goto dostr;
4690                 case CTLBACKQ:
4691                         str = "$(...)";
4692                         goto dostr;
4693 #if ENABLE_FEATURE_SH_MATH
4694                 case CTLARI:
4695                         str = "$((";
4696                         goto dostr;
4697                 case CTLENDARI:
4698                         str = "))";
4699                         goto dostr;
4700 #endif
4701                 case CTLQUOTEMARK:
4702                         quoted ^= 1;
4703                         c = '"';
4704                         break;
4705                 case '=':
4706                         if (subtype == 0)
4707                                 break;
4708                         if ((subtype & VSTYPE) != VSNORMAL)
4709                                 quoted <<= 1;
4710                         str = vstype[subtype & VSTYPE];
4711                         if (subtype & VSNUL)
4712                                 c = ':';
4713                         else
4714                                 goto checkstr;
4715                         break;
4716                 case '\'':
4717                 case '\\':
4718                 case '"':
4719                 case '$':
4720                         /* These can only happen inside quotes */
4721                         cc[0] = c;
4722                         str = cc;
4723 //FIXME:
4724 // $ true $$ &
4725 // $ <cr>
4726 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4727                         c = '\\';
4728                         break;
4729                 default:
4730                         break;
4731                 }
4732                 USTPUTC(c, nextc);
4733  checkstr:
4734                 if (!str)
4735                         continue;
4736  dostr:
4737                 while ((c = *str++) != '\0') {
4738                         USTPUTC(c, nextc);
4739                 }
4740         } /* while *p++ not NUL */
4741
4742         if (quoted & 1) {
4743                 USTPUTC('"', nextc);
4744         }
4745         *nextc = 0;
4746         cmdnextc = nextc;
4747 }
4748
4749 /* cmdtxt() and cmdlist() call each other */
4750 static void cmdtxt(union node *n);
4751
4752 static void
4753 cmdlist(union node *np, int sep)
4754 {
4755         for (; np; np = np->narg.next) {
4756                 if (!sep)
4757                         cmdputs(" ");
4758                 cmdtxt(np);
4759                 if (sep && np->narg.next)
4760                         cmdputs(" ");
4761         }
4762 }
4763
4764 static void
4765 cmdtxt(union node *n)
4766 {
4767         union node *np;
4768         struct nodelist *lp;
4769         const char *p;
4770
4771         if (!n)
4772                 return;
4773         switch (n->type) {
4774         default:
4775 #if DEBUG
4776                 abort();
4777 #endif
4778         case NPIPE:
4779                 lp = n->npipe.cmdlist;
4780                 for (;;) {
4781                         cmdtxt(lp->n);
4782                         lp = lp->next;
4783                         if (!lp)
4784                                 break;
4785                         cmdputs(" | ");
4786                 }
4787                 break;
4788         case NSEMI:
4789                 p = "; ";
4790                 goto binop;
4791         case NAND:
4792                 p = " && ";
4793                 goto binop;
4794         case NOR:
4795                 p = " || ";
4796  binop:
4797                 cmdtxt(n->nbinary.ch1);
4798                 cmdputs(p);
4799                 n = n->nbinary.ch2;
4800                 goto donode;
4801         case NREDIR:
4802         case NBACKGND:
4803                 n = n->nredir.n;
4804                 goto donode;
4805         case NNOT:
4806                 cmdputs("!");
4807                 n = n->nnot.com;
4808  donode:
4809                 cmdtxt(n);
4810                 break;
4811         case NIF:
4812                 cmdputs("if ");
4813                 cmdtxt(n->nif.test);
4814                 cmdputs("; then ");
4815                 if (n->nif.elsepart) {
4816                         cmdtxt(n->nif.ifpart);
4817                         cmdputs("; else ");
4818                         n = n->nif.elsepart;
4819                 } else {
4820                         n = n->nif.ifpart;
4821                 }
4822                 p = "; fi";
4823                 goto dotail;
4824         case NSUBSHELL:
4825                 cmdputs("(");
4826                 n = n->nredir.n;
4827                 p = ")";
4828                 goto dotail;
4829         case NWHILE:
4830                 p = "while ";
4831                 goto until;
4832         case NUNTIL:
4833                 p = "until ";
4834  until:
4835                 cmdputs(p);
4836                 cmdtxt(n->nbinary.ch1);
4837                 n = n->nbinary.ch2;
4838                 p = "; done";
4839  dodo:
4840                 cmdputs("; do ");
4841  dotail:
4842                 cmdtxt(n);
4843                 goto dotail2;
4844         case NFOR:
4845                 cmdputs("for ");
4846                 cmdputs(n->nfor.var);
4847                 cmdputs(" in ");
4848                 cmdlist(n->nfor.args, 1);
4849                 n = n->nfor.body;
4850                 p = "; done";
4851                 goto dodo;
4852         case NDEFUN:
4853                 cmdputs(n->ndefun.text);
4854                 p = "() { ... }";
4855                 goto dotail2;
4856         case NCMD:
4857                 cmdlist(n->ncmd.args, 1);
4858                 cmdlist(n->ncmd.redirect, 0);
4859                 break;
4860         case NARG:
4861                 p = n->narg.text;
4862  dotail2:
4863                 cmdputs(p);
4864                 break;
4865         case NHERE:
4866         case NXHERE:
4867                 p = "<<...";
4868                 goto dotail2;
4869         case NCASE:
4870                 cmdputs("case ");
4871                 cmdputs(n->ncase.expr->narg.text);
4872                 cmdputs(" in ");
4873                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4874                         cmdtxt(np->nclist.pattern);
4875                         cmdputs(") ");
4876                         cmdtxt(np->nclist.body);
4877                         cmdputs(";; ");
4878                 }
4879                 p = "esac";
4880                 goto dotail2;
4881         case NTO:
4882                 p = ">";
4883                 goto redir;
4884         case NCLOBBER:
4885                 p = ">|";
4886                 goto redir;
4887         case NAPPEND:
4888                 p = ">>";
4889                 goto redir;
4890 #if BASH_REDIR_OUTPUT
4891         case NTO2:
4892 #endif
4893         case NTOFD:
4894                 p = ">&";
4895                 goto redir;
4896         case NFROM:
4897                 p = "<";
4898                 goto redir;
4899         case NFROMFD:
4900                 p = "<&";
4901                 goto redir;
4902         case NFROMTO:
4903                 p = "<>";
4904  redir:
4905                 cmdputs(utoa(n->nfile.fd));
4906                 cmdputs(p);
4907                 if (n->type == NTOFD || n->type == NFROMFD) {
4908                         if (n->ndup.dupfd >= 0)
4909                                 cmdputs(utoa(n->ndup.dupfd));
4910                         else
4911                                 cmdputs("-");
4912                         break;
4913                 }
4914                 n = n->nfile.fname;
4915                 goto donode;
4916         }
4917 }
4918
4919 static char *
4920 commandtext(union node *n)
4921 {
4922         char *name;
4923
4924         STARTSTACKSTR(cmdnextc);
4925         cmdtxt(n);
4926         name = stackblock();
4927         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4928         return ckstrdup(name);
4929 }
4930 #endif /* JOBS */
4931
4932 /*
4933  * Fork off a subshell.  If we are doing job control, give the subshell its
4934  * own process group.  Jp is a job structure that the job is to be added to.
4935  * N is the command that will be evaluated by the child.  Both jp and n may
4936  * be NULL.  The mode parameter can be one of the following:
4937  *      FORK_FG - Fork off a foreground process.
4938  *      FORK_BG - Fork off a background process.
4939  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4940  *                   process group even if job control is on.
4941  *
4942  * When job control is turned off, background processes have their standard
4943  * input redirected to /dev/null (except for the second and later processes
4944  * in a pipeline).
4945  *
4946  * Called with interrupts off.
4947  */
4948 /*
4949  * Clear traps on a fork.
4950  */
4951 static void
4952 clear_traps(void)
4953 {
4954         char **tp;
4955
4956         INT_OFF;
4957         for (tp = trap; tp < &trap[NSIG]; tp++) {
4958                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4959                         if (trap_ptr == trap)
4960                                 free(*tp);
4961                         /* else: it "belongs" to trap_ptr vector, don't free */
4962                         *tp = NULL;
4963                         if ((tp - trap) != 0)
4964                                 setsignal(tp - trap);
4965                 }
4966         }
4967         may_have_traps = 0;
4968         INT_ON;
4969 }
4970
4971 /* Lives far away from here, needed for forkchild */
4972 static void closescript(void);
4973
4974 /* Called after fork(), in child */
4975 /* jp and n are NULL when called by openhere() for heredoc support */
4976 static NOINLINE void
4977 forkchild(struct job *jp, union node *n, int mode)
4978 {
4979         int oldlvl;
4980
4981         TRACE(("Child shell %d\n", getpid()));
4982         oldlvl = shlvl;
4983         shlvl++;
4984
4985         /* man bash: "Non-builtin commands run by bash have signal handlers
4986          * set to the values inherited by the shell from its parent".
4987          * Do we do it correctly? */
4988
4989         closescript();
4990
4991         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4992          && n && n->type == NCMD        /* is it single cmd? */
4993         /* && n->ncmd.args->type == NARG - always true? */
4994          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4995          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4996         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4997         ) {
4998                 TRACE(("Trap hack\n"));
4999                 /* Awful hack for `trap` or $(trap).
5000                  *
5001                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5002                  * contains an example where "trap" is executed in a subshell:
5003                  *
5004                  * save_traps=$(trap)
5005                  * ...
5006                  * eval "$save_traps"
5007                  *
5008                  * Standard does not say that "trap" in subshell shall print
5009                  * parent shell's traps. It only says that its output
5010                  * must have suitable form, but then, in the above example
5011                  * (which is not supposed to be normative), it implies that.
5012                  *
5013                  * bash (and probably other shell) does implement it
5014                  * (traps are reset to defaults, but "trap" still shows them),
5015                  * but as a result, "trap" logic is hopelessly messed up:
5016                  *
5017                  * # trap
5018                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5019                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5020                  * # true | trap   <--- trap is in subshell - no output (ditto)
5021                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5022                  * trap -- 'echo Ho' SIGWINCH
5023                  * # echo `(trap)`         <--- in subshell in subshell - output
5024                  * trap -- 'echo Ho' SIGWINCH
5025                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5026                  * trap -- 'echo Ho' SIGWINCH
5027                  *
5028                  * The rules when to forget and when to not forget traps
5029                  * get really complex and nonsensical.
5030                  *
5031                  * Our solution: ONLY bare $(trap) or `trap` is special.
5032                  */
5033                 /* Save trap handler strings for trap builtin to print */
5034                 trap_ptr = xmemdup(trap, sizeof(trap));
5035                 /* Fall through into clearing traps */
5036         }
5037         clear_traps();
5038 #if JOBS
5039         /* do job control only in root shell */
5040         doing_jobctl = 0;
5041         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5042                 pid_t pgrp;
5043
5044                 if (jp->nprocs == 0)
5045                         pgrp = getpid();
5046                 else
5047                         pgrp = jp->ps[0].ps_pid;
5048                 /* this can fail because we are doing it in the parent also */
5049                 setpgid(0, pgrp);
5050                 if (mode == FORK_FG)
5051                         xtcsetpgrp(ttyfd, pgrp);
5052                 setsignal(SIGTSTP);
5053                 setsignal(SIGTTOU);
5054         } else
5055 #endif
5056         if (mode == FORK_BG) {
5057                 /* man bash: "When job control is not in effect,
5058                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5059                 ignoresig(SIGINT);
5060                 ignoresig(SIGQUIT);
5061                 if (jp->nprocs == 0) {
5062                         close(0);
5063                         if (open(bb_dev_null, O_RDONLY) != 0)
5064                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5065                 }
5066         }
5067         if (oldlvl == 0) {
5068                 if (iflag) { /* why if iflag only? */
5069                         setsignal(SIGINT);
5070                         setsignal(SIGTERM);
5071                 }
5072                 /* man bash:
5073                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5074                  * commands run by bash have signal handlers
5075                  * set to the values inherited by the shell
5076                  * from its parent".
5077                  * Take care of the second rule: */
5078                 setsignal(SIGQUIT);
5079         }
5080 #if JOBS
5081         if (n && n->type == NCMD
5082          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5083         ) {
5084                 TRACE(("Job hack\n"));
5085                 /* "jobs": we do not want to clear job list for it,
5086                  * instead we remove only _its_ own_ job from job list.
5087                  * This makes "jobs .... | cat" more useful.
5088                  */
5089                 freejob(curjob);
5090                 return;
5091         }
5092 #endif
5093         for (jp = curjob; jp; jp = jp->prev_job)
5094                 freejob(jp);
5095         jobless = 0;
5096 }
5097
5098 /* Called after fork(), in parent */
5099 #if !JOBS
5100 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5101 #endif
5102 static void
5103 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5104 {
5105         TRACE(("In parent shell: child = %d\n", pid));
5106         if (!jp) {
5107                 /* jp is NULL when called by openhere() for heredoc support */
5108                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5109                         continue;
5110                 jobless++;
5111                 return;
5112         }
5113 #if JOBS
5114         if (mode != FORK_NOJOB && jp->jobctl) {
5115                 int pgrp;
5116
5117                 if (jp->nprocs == 0)
5118                         pgrp = pid;
5119                 else
5120                         pgrp = jp->ps[0].ps_pid;
5121                 /* This can fail because we are doing it in the child also */
5122                 setpgid(pid, pgrp);
5123         }
5124 #endif
5125         if (mode == FORK_BG) {
5126                 backgndpid = pid;               /* set $! */
5127                 set_curjob(jp, CUR_RUNNING);
5128         }
5129         if (jp) {
5130                 struct procstat *ps = &jp->ps[jp->nprocs++];
5131                 ps->ps_pid = pid;
5132                 ps->ps_status = -1;
5133                 ps->ps_cmd = nullstr;
5134 #if JOBS
5135                 if (doing_jobctl && n)
5136                         ps->ps_cmd = commandtext(n);
5137 #endif
5138         }
5139 }
5140
5141 /* jp and n are NULL when called by openhere() for heredoc support */
5142 static int
5143 forkshell(struct job *jp, union node *n, int mode)
5144 {
5145         int pid;
5146
5147         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5148         pid = fork();
5149         if (pid < 0) {
5150                 TRACE(("Fork failed, errno=%d", errno));
5151                 if (jp)
5152                         freejob(jp);
5153                 ash_msg_and_raise_perror("can't fork");
5154         }
5155         if (pid == 0) {
5156                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5157                 forkchild(jp, n, mode);
5158         } else {
5159                 forkparent(jp, n, mode, pid);
5160         }
5161         return pid;
5162 }
5163
5164 /*
5165  * Wait for job to finish.
5166  *
5167  * Under job control we have the problem that while a child process
5168  * is running interrupts generated by the user are sent to the child
5169  * but not to the shell.  This means that an infinite loop started by
5170  * an interactive user may be hard to kill.  With job control turned off,
5171  * an interactive user may place an interactive program inside a loop.
5172  * If the interactive program catches interrupts, the user doesn't want
5173  * these interrupts to also abort the loop.  The approach we take here
5174  * is to have the shell ignore interrupt signals while waiting for a
5175  * foreground process to terminate, and then send itself an interrupt
5176  * signal if the child process was terminated by an interrupt signal.
5177  * Unfortunately, some programs want to do a bit of cleanup and then
5178  * exit on interrupt; unless these processes terminate themselves by
5179  * sending a signal to themselves (instead of calling exit) they will
5180  * confuse this approach.
5181  *
5182  * Called with interrupts off.
5183  */
5184 static int
5185 waitforjob(struct job *jp)
5186 {
5187         int st;
5188
5189         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5190
5191         INT_OFF;
5192         while (jp->state == JOBRUNNING) {
5193                 /* In non-interactive shells, we _can_ get
5194                  * a keyboard signal here and be EINTRed,
5195                  * but we just loop back, waiting for command to complete.
5196                  *
5197                  * man bash:
5198                  * "If bash is waiting for a command to complete and receives
5199                  * a signal for which a trap has been set, the trap
5200                  * will not be executed until the command completes."
5201                  *
5202                  * Reality is that even if trap is not set, bash
5203                  * will not act on the signal until command completes.
5204                  * Try this. sleep5intoff.c:
5205                  * #include <signal.h>
5206                  * #include <unistd.h>
5207                  * int main() {
5208                  *         sigset_t set;
5209                  *         sigemptyset(&set);
5210                  *         sigaddset(&set, SIGINT);
5211                  *         sigaddset(&set, SIGQUIT);
5212                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5213                  *         sleep(5);
5214                  *         return 0;
5215                  * }
5216                  * $ bash -c './sleep5intoff; echo hi'
5217                  * ^C^C^C^C <--- pressing ^C once a second
5218                  * $ _
5219                  * $ bash -c './sleep5intoff; echo hi'
5220                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5221                  * $ _
5222                  */
5223                 dowait(DOWAIT_BLOCK, jp);
5224         }
5225         INT_ON;
5226
5227         st = getstatus(jp);
5228 #if JOBS
5229         if (jp->jobctl) {
5230                 xtcsetpgrp(ttyfd, rootpid);
5231                 restore_tty_if_stopped_or_signaled(jp);
5232
5233                 /*
5234                  * This is truly gross.
5235                  * If we're doing job control, then we did a TIOCSPGRP which
5236                  * caused us (the shell) to no longer be in the controlling
5237                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5238                  * intuit from the subprocess exit status whether a SIGINT
5239                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5240                  */
5241                 if (jp->sigint) /* TODO: do the same with all signals */
5242                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5243         }
5244         if (jp->state == JOBDONE)
5245 #endif
5246                 freejob(jp);
5247         return st;
5248 }
5249
5250 /*
5251  * return 1 if there are stopped jobs, otherwise 0
5252  */
5253 static int
5254 stoppedjobs(void)
5255 {
5256         struct job *jp;
5257         int retval;
5258
5259         retval = 0;
5260         if (job_warning)
5261                 goto out;
5262         jp = curjob;
5263         if (jp && jp->state == JOBSTOPPED) {
5264                 out2str("You have stopped jobs.\n");
5265                 job_warning = 2;
5266                 retval++;
5267         }
5268  out:
5269         return retval;
5270 }
5271
5272
5273 /*
5274  * Code for dealing with input/output redirection.
5275  */
5276
5277 #undef EMPTY
5278 #undef CLOSED
5279 #define EMPTY -2                /* marks an unused slot in redirtab */
5280 #define CLOSED -1               /* marks a slot of previously-closed fd */
5281
5282 /*
5283  * Handle here documents.  Normally we fork off a process to write the
5284  * data to a pipe.  If the document is short, we can stuff the data in
5285  * the pipe without forking.
5286  */
5287 /* openhere needs this forward reference */
5288 static void expandhere(union node *arg, int fd);
5289 static int
5290 openhere(union node *redir)
5291 {
5292         int pip[2];
5293         size_t len = 0;
5294
5295         if (pipe(pip) < 0)
5296                 ash_msg_and_raise_perror("can't create pipe");
5297         if (redir->type == NHERE) {
5298                 len = strlen(redir->nhere.doc->narg.text);
5299                 if (len <= PIPE_BUF) {
5300                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5301                         goto out;
5302                 }
5303         }
5304         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5305                 /* child */
5306                 close(pip[0]);
5307                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5308                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5309                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5310                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5311                 signal(SIGPIPE, SIG_DFL);
5312                 if (redir->type == NHERE)
5313                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5314                 else /* NXHERE */
5315                         expandhere(redir->nhere.doc, pip[1]);
5316                 _exit(EXIT_SUCCESS);
5317         }
5318  out:
5319         close(pip[1]);
5320         return pip[0];
5321 }
5322
5323 static int
5324 openredirect(union node *redir)
5325 {
5326         struct stat sb;
5327         char *fname;
5328         int f;
5329
5330         switch (redir->nfile.type) {
5331 /* Can't happen, our single caller does this itself */
5332 //      case NTOFD:
5333 //      case NFROMFD:
5334 //              return -1;
5335         case NHERE:
5336         case NXHERE:
5337                 return openhere(redir);
5338         }
5339
5340         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5341          * allocated space. Do it only when we know it is safe.
5342          */
5343         fname = redir->nfile.expfname;
5344
5345         switch (redir->nfile.type) {
5346         default:
5347 #if DEBUG
5348                 abort();
5349 #endif
5350         case NFROM:
5351                 f = open(fname, O_RDONLY);
5352                 if (f < 0)
5353                         goto eopen;
5354                 break;
5355         case NFROMTO:
5356                 f = open(fname, O_RDWR|O_CREAT, 0666);
5357                 if (f < 0)
5358                         goto ecreate;
5359                 break;
5360         case NTO:
5361 #if BASH_REDIR_OUTPUT
5362         case NTO2:
5363 #endif
5364                 /* Take care of noclobber mode. */
5365                 if (Cflag) {
5366                         if (stat(fname, &sb) < 0) {
5367                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5368                                 if (f < 0)
5369                                         goto ecreate;
5370                         } else if (!S_ISREG(sb.st_mode)) {
5371                                 f = open(fname, O_WRONLY, 0666);
5372                                 if (f < 0)
5373                                         goto ecreate;
5374                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5375                                         close(f);
5376                                         errno = EEXIST;
5377                                         goto ecreate;
5378                                 }
5379                         } else {
5380                                 errno = EEXIST;
5381                                 goto ecreate;
5382                         }
5383                         break;
5384                 }
5385                 /* FALLTHROUGH */
5386         case NCLOBBER:
5387                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5388                 if (f < 0)
5389                         goto ecreate;
5390                 break;
5391         case NAPPEND:
5392                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5393                 if (f < 0)
5394                         goto ecreate;
5395                 break;
5396         }
5397
5398         return f;
5399  ecreate:
5400         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5401  eopen:
5402         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5403 }
5404
5405 /*
5406  * Copy a file descriptor to be >= 10. Throws exception on error.
5407  */
5408 static int
5409 savefd(int from)
5410 {
5411         int newfd;
5412         int err;
5413
5414         newfd = fcntl(from, F_DUPFD, 10);
5415         err = newfd < 0 ? errno : 0;
5416         if (err != EBADF) {
5417                 if (err)
5418                         ash_msg_and_raise_perror("%d", from);
5419                 close(from);
5420                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5421         }
5422
5423         return newfd;
5424 }
5425 static int
5426 dup2_or_raise(int from, int to)
5427 {
5428         int newfd;
5429
5430         newfd = (from != to) ? dup2(from, to) : to;
5431         if (newfd < 0) {
5432                 /* Happens when source fd is not open: try "echo >&99" */
5433                 ash_msg_and_raise_perror("%d", from);
5434         }
5435         return newfd;
5436 }
5437 static int
5438 fcntl_F_DUPFD(int fd, int avoid_fd)
5439 {
5440         int newfd;
5441  repeat:
5442         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5443         if (newfd < 0) {
5444                 if (errno == EBUSY)
5445                         goto repeat;
5446                 if (errno == EINTR)
5447                         goto repeat;
5448         }
5449         return newfd;
5450 }
5451 static int
5452 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5453 {
5454         int newfd;
5455  repeat:
5456         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5457         if (newfd < 0) {
5458                 if (errno == EBUSY)
5459                         goto repeat;
5460                 if (errno == EINTR)
5461                         goto repeat;
5462                 /* fd was not open? */
5463                 if (errno == EBADF)
5464                         return fd;
5465                 ash_msg_and_raise_perror("%d", newfd);
5466         }
5467         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5468         close(fd);
5469         return newfd;
5470 }
5471
5472 /* Struct def and variable are moved down to the first usage site */
5473 struct squirrel {
5474         int orig_fd;
5475         int moved_to;
5476 };
5477 struct redirtab {
5478         struct redirtab *next;
5479         int pair_count;
5480         struct squirrel two_fd[];
5481 };
5482 #define redirlist (G_var.redirlist)
5483
5484 static void
5485 add_squirrel_closed(struct redirtab *sq, int fd)
5486 {
5487         int i;
5488
5489         if (!sq)
5490                 return;
5491
5492         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5493                 /* If we collide with an already moved fd... */
5494                 if (fd == sq->two_fd[i].orig_fd) {
5495                         /* Examples:
5496                          * "echo 3>FILE 3>&- 3>FILE"
5497                          * "echo 3>&- 3>FILE"
5498                          * No need for last redirect to insert
5499                          * another "need to close 3" indicator.
5500                          */
5501                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5502                         return;
5503                 }
5504         }
5505         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5506         sq->two_fd[i].orig_fd = fd;
5507         sq->two_fd[i].moved_to = CLOSED;
5508 }
5509
5510 static int
5511 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5512 {
5513         int i, new_fd;
5514
5515         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5516                 avoid_fd = 9;
5517
5518 #if JOBS
5519         if (fd == ttyfd) {
5520                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5521                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5522                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5523                 return 1; /* "we closed fd" */
5524         }
5525 #endif
5526         /* Are we called from redirect(0)? E.g. redirect
5527          * in a forked child. No need to save fds,
5528          * we aren't going to use them anymore, ok to trash.
5529          */
5530         if (!sq)
5531                 return 0;
5532
5533         /* If this one of script's fds? */
5534         if (fd != 0) {
5535                 struct parsefile *pf = g_parsefile;
5536                 while (pf) {
5537                         /* We skip fd == 0 case because of the following:
5538                          * $ ash  # running ash interactively
5539                          * $ . ./script.sh
5540                          * and in script.sh: "exec 9>&0".
5541                          * Even though top-level pf_fd _is_ 0,
5542                          * it's still ok to use it: "read" builtin uses it,
5543                          * why should we cripple "exec" builtin?
5544                          */
5545                         if (fd == pf->pf_fd) {
5546                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5547                                 return 1; /* "we closed fd" */
5548                         }
5549                         pf = pf->prev;
5550                 }
5551         }
5552
5553         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5554
5555         /* First: do we collide with some already moved fds? */
5556         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5557                 /* If we collide with an already moved fd... */
5558                 if (fd == sq->two_fd[i].moved_to) {
5559                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5560                         sq->two_fd[i].moved_to = new_fd;
5561                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5562                         if (new_fd < 0) /* what? */
5563                                 xfunc_die();
5564                         return 0; /* "we did not close fd" */
5565                 }
5566                 if (fd == sq->two_fd[i].orig_fd) {
5567                         /* Example: echo Hello >/dev/null 1>&2 */
5568                         TRACE(("redirect_fd %d: already moved\n", fd));
5569                         return 0; /* "we did not close fd" */
5570                 }
5571         }
5572
5573         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5574         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5575         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5576         if (new_fd < 0) {
5577                 if (errno != EBADF)
5578                         xfunc_die();
5579                 /* new_fd = CLOSED; - already is -1 */
5580         }
5581         sq->two_fd[i].moved_to = new_fd;
5582         sq->two_fd[i].orig_fd = fd;
5583
5584         /* if we move stderr, let "set -x" code know */
5585         if (fd == preverrout_fd)
5586                 preverrout_fd = new_fd;
5587
5588         return 0; /* "we did not close fd" */
5589 }
5590
5591 static int
5592 internally_opened_fd(int fd, struct redirtab *sq)
5593 {
5594         int i;
5595 #if JOBS
5596         if (fd == ttyfd)
5597                 return 1;
5598 #endif
5599         /* If this one of script's fds? */
5600         if (fd != 0) {
5601                 struct parsefile *pf = g_parsefile;
5602                 while (pf) {
5603                         if (fd == pf->pf_fd)
5604                                 return 1;
5605                         pf = pf->prev;
5606                 }
5607         }
5608
5609         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5610                 if (fd == sq->two_fd[i].moved_to)
5611                         return 1;
5612         }
5613         return 0;
5614 }
5615
5616 /*
5617  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5618  * old file descriptors are stashed away so that the redirection can be
5619  * undone by calling popredir.
5620  */
5621 /* flags passed to redirect */
5622 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5623 static void
5624 redirect(union node *redir, int flags)
5625 {
5626         struct redirtab *sv;
5627
5628         if (!redir)
5629                 return;
5630
5631         sv = NULL;
5632         INT_OFF;
5633         if (flags & REDIR_PUSH)
5634                 sv = redirlist;
5635         do {
5636                 int fd;
5637                 int newfd;
5638                 int close_fd;
5639                 int closed;
5640
5641                 fd = redir->nfile.fd;
5642                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5643                         //bb_error_msg("doing %d > %d", fd, newfd);
5644                         newfd = redir->ndup.dupfd;
5645                         close_fd = -1;
5646                 } else {
5647                         newfd = openredirect(redir); /* always >= 0 */
5648                         if (fd == newfd) {
5649                                 /* open() gave us precisely the fd we wanted.
5650                                  * This means that this fd was not busy
5651                                  * (not opened to anywhere).
5652                                  * Remember to close it on restore:
5653                                  */
5654                                 add_squirrel_closed(sv, fd);
5655                                 continue;
5656                         }
5657                         close_fd = newfd;
5658                 }
5659
5660                 if (fd == newfd)
5661                         continue;
5662
5663                 /* if "N>FILE": move newfd to fd */
5664                 /* if "N>&M": dup newfd to fd */
5665                 /* if "N>&-": close fd (newfd is -1) */
5666
5667  IF_BASH_REDIR_OUTPUT(redirect_more:)
5668
5669                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5670                 if (newfd == -1) {
5671                         /* "N>&-" means "close me" */
5672                         if (!closed) {
5673                                 /* ^^^ optimization: saving may already
5674                                  * have closed it. If not... */
5675                                 close(fd);
5676                         }
5677                 } else {
5678                         /* if newfd is a script fd or saved fd, simulate EBADF */
5679                         if (internally_opened_fd(newfd, sv)) {
5680                                 errno = EBADF;
5681                                 ash_msg_and_raise_perror("%d", newfd);
5682                         }
5683                         dup2_or_raise(newfd, fd);
5684                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5685                                 close(close_fd);
5686 #if BASH_REDIR_OUTPUT
5687                         if (redir->nfile.type == NTO2 && fd == 1) {
5688                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5689                                 fd = 2;
5690                                 newfd = 1;
5691                                 close_fd = -1;
5692                                 goto redirect_more;
5693                         }
5694 #endif
5695                 }
5696         } while ((redir = redir->nfile.next) != NULL);
5697         INT_ON;
5698
5699 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5700 #define REDIR_SAVEFD2 0
5701         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5702         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5703         // not only for calls with flags containing REDIR_SAVEFD2.
5704         // We do this unconditionally (see save_fd_on_redirect()).
5705         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5706         //      preverrout_fd = copied_fd2;
5707 }
5708
5709 static int
5710 redirectsafe(union node *redir, int flags)
5711 {
5712         int err;
5713         volatile int saveint;
5714         struct jmploc *volatile savehandler = exception_handler;
5715         struct jmploc jmploc;
5716
5717         SAVE_INT(saveint);
5718         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5719         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5720         if (!err) {
5721                 exception_handler = &jmploc;
5722                 redirect(redir, flags);
5723         }
5724         exception_handler = savehandler;
5725         if (err && exception_type != EXERROR)
5726                 longjmp(exception_handler->loc, 1);
5727         RESTORE_INT(saveint);
5728         return err;
5729 }
5730
5731 static struct redirtab*
5732 pushredir(union node *redir)
5733 {
5734         struct redirtab *sv;
5735         int i;
5736
5737         if (!redir)
5738                 return redirlist;
5739
5740         i = 0;
5741         do {
5742                 i++;
5743 #if BASH_REDIR_OUTPUT
5744                 if (redir->nfile.type == NTO2)
5745                         i++;
5746 #endif
5747                 redir = redir->nfile.next;
5748         } while (redir);
5749
5750         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5751         sv->pair_count = i;
5752         while (--i >= 0)
5753                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5754         sv->next = redirlist;
5755         redirlist = sv;
5756         return sv->next;
5757 }
5758
5759 /*
5760  * Undo the effects of the last redirection.
5761  */
5762 static void
5763 popredir(int drop)
5764 {
5765         struct redirtab *rp;
5766         int i;
5767
5768         if (redirlist == NULL)
5769                 return;
5770         INT_OFF;
5771         rp = redirlist;
5772         for (i = 0; i < rp->pair_count; i++) {
5773                 int fd = rp->two_fd[i].orig_fd;
5774                 int copy = rp->two_fd[i].moved_to;
5775                 if (copy == CLOSED) {
5776                         if (!drop)
5777                                 close(fd);
5778                         continue;
5779                 }
5780                 if (copy != EMPTY) {
5781                         if (!drop) {
5782                                 /*close(fd);*/
5783                                 dup2_or_raise(copy, fd);
5784                         }
5785                         close(copy);
5786                 }
5787         }
5788         redirlist = rp->next;
5789         free(rp);
5790         INT_ON;
5791 }
5792
5793 static void
5794 unwindredir(struct redirtab *stop)
5795 {
5796         while (redirlist != stop)
5797                 popredir(/*drop:*/ 0);
5798 }
5799
5800
5801 /* ============ Routines to expand arguments to commands
5802  *
5803  * We have to deal with backquotes, shell variables, and file metacharacters.
5804  */
5805
5806 #if ENABLE_FEATURE_SH_MATH
5807 static arith_t
5808 ash_arith(const char *s)
5809 {
5810         arith_state_t math_state;
5811         arith_t result;
5812
5813         math_state.lookupvar = lookupvar;
5814         math_state.setvar    = setvar0;
5815         //math_state.endofname = endofname;
5816
5817         INT_OFF;
5818         result = arith(&math_state, s);
5819         if (math_state.errmsg)
5820                 ash_msg_and_raise_error(math_state.errmsg);
5821         INT_ON;
5822
5823         return result;
5824 }
5825 #endif
5826 #if BASH_SUBSTR
5827 # if ENABLE_FEATURE_SH_MATH
5828 static int substr_atoi(const char *s)
5829 {
5830         arith_t t = ash_arith(s);
5831         if (sizeof(t) > sizeof(int)) {
5832                 /* clamp very large or very large negative nums for ${v:N:M}:
5833                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5834                  */
5835                 if (t > INT_MAX)
5836                         t = INT_MAX;
5837                 if (t < INT_MIN)
5838                         t = INT_MIN;
5839         }
5840         return t;
5841 }
5842 # else
5843 #  define substr_atoi(s) number(s)
5844 # endif
5845 #endif
5846
5847 /*
5848  * expandarg flags
5849  */
5850 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5851 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5852 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5853 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5854 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5855  * POSIX says for this case:
5856  *  Pathname expansion shall not be performed on the word by a
5857  *  non-interactive shell; an interactive shell may perform it, but shall
5858  *  do so only when the expansion would result in one word.
5859  * Currently, our code complies to the above rule by never globbing
5860  * redirection filenames.
5861  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5862  * (this means that on a typical Linux distro, bash almost always
5863  * performs globbing, and thus diverges from what we do).
5864  */
5865 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5866 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5867 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5868 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5869 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5870 /*
5871  * rmescape() flags
5872  */
5873 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5874 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5875 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5876 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5877
5878 /* Add CTLESC when necessary. */
5879 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5880 /* Do not skip NUL characters. */
5881 #define QUOTES_KEEPNUL EXP_TILDE
5882
5883 /*
5884  * Structure specifying which parts of the string should be searched
5885  * for IFS characters.
5886  */
5887 struct ifsregion {
5888         struct ifsregion *next; /* next region in list */
5889         int begoff;             /* offset of start of region */
5890         int endoff;             /* offset of end of region */
5891         int nulonly;            /* search for nul bytes only */
5892 };
5893
5894 struct arglist {
5895         struct strlist *list;
5896         struct strlist **lastp;
5897 };
5898
5899 /* output of current string */
5900 static char *expdest;
5901 /* list of back quote expressions */
5902 static struct nodelist *argbackq;
5903 /* first struct in list of ifs regions */
5904 static struct ifsregion ifsfirst;
5905 /* last struct in list */
5906 static struct ifsregion *ifslastp;
5907 /* holds expanded arg list */
5908 static struct arglist exparg;
5909
5910 /*
5911  * Our own itoa().
5912  * cvtnum() is used even if math support is off (to prepare $? values and such).
5913  */
5914 static int
5915 cvtnum(arith_t num)
5916 {
5917         int len;
5918
5919         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5920         len = sizeof(arith_t) * 3;
5921         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5922         if (sizeof(arith_t) < 4) len += 2;
5923
5924         expdest = makestrspace(len, expdest);
5925         len = fmtstr(expdest, len, ARITH_FMT, num);
5926         STADJUST(len, expdest);
5927         return len;
5928 }
5929
5930 /*
5931  * Break the argument string into pieces based upon IFS and add the
5932  * strings to the argument list.  The regions of the string to be
5933  * searched for IFS characters have been stored by recordregion.
5934  */
5935 static void
5936 ifsbreakup(char *string, struct arglist *arglist)
5937 {
5938         struct ifsregion *ifsp;
5939         struct strlist *sp;
5940         char *start;
5941         char *p;
5942         char *q;
5943         const char *ifs, *realifs;
5944         int ifsspc;
5945         int nulonly;
5946
5947         start = string;
5948         if (ifslastp != NULL) {
5949                 ifsspc = 0;
5950                 nulonly = 0;
5951                 realifs = ifsset() ? ifsval() : defifs;
5952                 ifsp = &ifsfirst;
5953                 do {
5954                         p = string + ifsp->begoff;
5955                         nulonly = ifsp->nulonly;
5956                         ifs = nulonly ? nullstr : realifs;
5957                         ifsspc = 0;
5958                         while (p < string + ifsp->endoff) {
5959                                 q = p;
5960                                 if ((unsigned char)*p == CTLESC)
5961                                         p++;
5962                                 if (!strchr(ifs, *p)) {
5963                                         p++;
5964                                         continue;
5965                                 }
5966                                 if (!nulonly)
5967                                         ifsspc = (strchr(defifs, *p) != NULL);
5968                                 /* Ignore IFS whitespace at start */
5969                                 if (q == start && ifsspc) {
5970                                         p++;
5971                                         start = p;
5972                                         continue;
5973                                 }
5974                                 *q = '\0';
5975                                 sp = stzalloc(sizeof(*sp));
5976                                 sp->text = start;
5977                                 *arglist->lastp = sp;
5978                                 arglist->lastp = &sp->next;
5979                                 p++;
5980                                 if (!nulonly) {
5981                                         for (;;) {
5982                                                 if (p >= string + ifsp->endoff) {
5983                                                         break;
5984                                                 }
5985                                                 q = p;
5986                                                 if ((unsigned char)*p == CTLESC)
5987                                                         p++;
5988                                                 if (strchr(ifs, *p) == NULL) {
5989                                                         p = q;
5990                                                         break;
5991                                                 }
5992                                                 if (strchr(defifs, *p) == NULL) {
5993                                                         if (ifsspc) {
5994                                                                 p++;
5995                                                                 ifsspc = 0;
5996                                                         } else {
5997                                                                 p = q;
5998                                                                 break;
5999                                                         }
6000                                                 } else
6001                                                         p++;
6002                                         }
6003                                 }
6004                                 start = p;
6005                         } /* while */
6006                         ifsp = ifsp->next;
6007                 } while (ifsp != NULL);
6008                 if (nulonly)
6009                         goto add;
6010         }
6011
6012         if (!*start)
6013                 return;
6014
6015  add:
6016         sp = stzalloc(sizeof(*sp));
6017         sp->text = start;
6018         *arglist->lastp = sp;
6019         arglist->lastp = &sp->next;
6020 }
6021
6022 static void
6023 ifsfree(void)
6024 {
6025         struct ifsregion *p = ifsfirst.next;
6026
6027         if (!p)
6028                 goto out;
6029
6030         INT_OFF;
6031         do {
6032                 struct ifsregion *ifsp;
6033                 ifsp = p->next;
6034                 free(p);
6035                 p = ifsp;
6036         } while (p);
6037         ifsfirst.next = NULL;
6038         INT_ON;
6039  out:
6040         ifslastp = NULL;
6041 }
6042
6043 static size_t
6044 esclen(const char *start, const char *p)
6045 {
6046         size_t esc = 0;
6047
6048         while (p > start && (unsigned char)*--p == CTLESC) {
6049                 esc++;
6050         }
6051         return esc;
6052 }
6053
6054 /*
6055  * Remove any CTLESC characters from a string.
6056  */
6057 #if !BASH_PATTERN_SUBST
6058 #define rmescapes(str, flag, slash_position) \
6059         rmescapes(str, flag)
6060 #endif
6061 static char *
6062 rmescapes(char *str, int flag, int *slash_position)
6063 {
6064         static const char qchars[] ALIGN1 = {
6065                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6066
6067         char *p, *q, *r;
6068         unsigned inquotes;
6069         unsigned protect_against_glob;
6070         unsigned globbing;
6071
6072         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6073         if (!p)
6074                 return str;
6075
6076         q = p;
6077         r = str;
6078         if (flag & RMESCAPE_ALLOC) {
6079                 size_t len = p - str;
6080                 size_t fulllen = len + strlen(p) + 1;
6081
6082                 if (flag & RMESCAPE_GROW) {
6083                         int strloc = str - (char *)stackblock();
6084                         r = makestrspace(fulllen, expdest);
6085                         /* p and str may be invalidated by makestrspace */
6086                         str = (char *)stackblock() + strloc;
6087                         p = str + len;
6088                 } else if (flag & RMESCAPE_HEAP) {
6089                         r = ckmalloc(fulllen);
6090                 } else {
6091                         r = stalloc(fulllen);
6092                 }
6093                 q = r;
6094                 if (len > 0) {
6095                         q = (char *)mempcpy(q, str, len);
6096                 }
6097         }
6098
6099         inquotes = 0;
6100         globbing = flag & RMESCAPE_GLOB;
6101         protect_against_glob = globbing;
6102         while (*p) {
6103                 if ((unsigned char)*p == CTLQUOTEMARK) {
6104 // Note: both inquotes and protect_against_glob only affect whether
6105 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6106                         inquotes = ~inquotes;
6107                         p++;
6108                         protect_against_glob = globbing;
6109                         continue;
6110                 }
6111                 if ((unsigned char)*p == CTLESC) {
6112                         p++;
6113 #if DEBUG
6114                         if (*p == '\0')
6115                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6116 #endif
6117                         if (protect_against_glob) {
6118                                 /*
6119                                  * We used to trust glob() and fnmatch() to eat
6120                                  * superfluous escapes (\z where z has no
6121                                  * special meaning anyway). But this causes
6122                                  * bugs such as string of one greek letter rho
6123                                  * (unicode-encoded as two bytes "cf,81")
6124                                  * getting encoded as "cf,CTLESC,81"
6125                                  * and here, converted to "cf,\,81" -
6126                                  * which does not go well with some flavors
6127                                  * of fnmatch() in unicode locales
6128                                  * (for example, glibc <= 2.22).
6129                                  *
6130                                  * Lets add "\" only on the chars which need it.
6131                                  * Testcases for less obvious chars are shown.
6132                                  */
6133                                 if (*p == '*'
6134                                  || *p == '?'
6135                                  || *p == '['
6136                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6137                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6138                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6139                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6140                                 /* Some libc support [^negate], that's why "^" also needs love */
6141                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6142                                 ) {
6143                                         *q++ = '\\';
6144                                 }
6145                         }
6146                 } else if (*p == '\\' && !inquotes) {
6147                         /* naked back slash */
6148                         protect_against_glob = 0;
6149                         goto copy;
6150                 }
6151 #if BASH_PATTERN_SUBST
6152                 else if (slash_position && p == str + *slash_position) {
6153                         /* stop handling globbing */
6154                         globbing = 0;
6155                         *slash_position = q - r;
6156                         slash_position = NULL;
6157                 }
6158 #endif
6159                 protect_against_glob = globbing;
6160  copy:
6161                 *q++ = *p++;
6162         }
6163         *q = '\0';
6164         if (flag & RMESCAPE_GROW) {
6165                 expdest = r;
6166                 STADJUST(q - r + 1, expdest);
6167         }
6168         return r;
6169 }
6170 #define pmatch(a, b) !fnmatch((a), (b), 0)
6171
6172 /*
6173  * Prepare a pattern for a expmeta (internal glob(3)) call.
6174  *
6175  * Returns an stalloced string.
6176  */
6177 static char *
6178 preglob(const char *pattern, int flag)
6179 {
6180         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6181 }
6182
6183 /*
6184  * Put a string on the stack.
6185  */
6186 static void
6187 memtodest(const char *p, size_t len, int syntax, int quotes)
6188 {
6189         char *q;
6190
6191         if (!len)
6192                 return;
6193
6194         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6195
6196         do {
6197                 unsigned char c = *p++;
6198                 if (c) {
6199                         if (quotes & QUOTES_ESC) {
6200                                 int n = SIT(c, syntax);
6201                                 if (n == CCTL
6202                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6203                                      && n == CBACK
6204                                     )
6205                                 ) {
6206                                         USTPUTC(CTLESC, q);
6207                                 }
6208                         }
6209                 } else if (!(quotes & QUOTES_KEEPNUL))
6210                         continue;
6211                 USTPUTC(c, q);
6212         } while (--len);
6213
6214         expdest = q;
6215 }
6216
6217 static size_t
6218 strtodest(const char *p, int syntax, int quotes)
6219 {
6220         size_t len = strlen(p);
6221         memtodest(p, len, syntax, quotes);
6222         return len;
6223 }
6224
6225 /*
6226  * Record the fact that we have to scan this region of the
6227  * string for IFS characters.
6228  */
6229 static void
6230 recordregion(int start, int end, int nulonly)
6231 {
6232         struct ifsregion *ifsp;
6233
6234         if (ifslastp == NULL) {
6235                 ifsp = &ifsfirst;
6236         } else {
6237                 INT_OFF;
6238                 ifsp = ckzalloc(sizeof(*ifsp));
6239                 /*ifsp->next = NULL; - ckzalloc did it */
6240                 ifslastp->next = ifsp;
6241                 INT_ON;
6242         }
6243         ifslastp = ifsp;
6244         ifslastp->begoff = start;
6245         ifslastp->endoff = end;
6246         ifslastp->nulonly = nulonly;
6247 }
6248
6249 static void
6250 removerecordregions(int endoff)
6251 {
6252         if (ifslastp == NULL)
6253                 return;
6254
6255         if (ifsfirst.endoff > endoff) {
6256                 while (ifsfirst.next) {
6257                         struct ifsregion *ifsp;
6258                         INT_OFF;
6259                         ifsp = ifsfirst.next->next;
6260                         free(ifsfirst.next);
6261                         ifsfirst.next = ifsp;
6262                         INT_ON;
6263                 }
6264                 if (ifsfirst.begoff > endoff) {
6265                         ifslastp = NULL;
6266                 } else {
6267                         ifslastp = &ifsfirst;
6268                         ifsfirst.endoff = endoff;
6269                 }
6270                 return;
6271         }
6272
6273         ifslastp = &ifsfirst;
6274         while (ifslastp->next && ifslastp->next->begoff < endoff)
6275                 ifslastp = ifslastp->next;
6276         while (ifslastp->next) {
6277                 struct ifsregion *ifsp;
6278                 INT_OFF;
6279                 ifsp = ifslastp->next->next;
6280                 free(ifslastp->next);
6281                 ifslastp->next = ifsp;
6282                 INT_ON;
6283         }
6284         if (ifslastp->endoff > endoff)
6285                 ifslastp->endoff = endoff;
6286 }
6287
6288 static char *
6289 exptilde(char *startp, char *p, int flags)
6290 {
6291         unsigned char c;
6292         char *name;
6293         struct passwd *pw;
6294         const char *home;
6295         int quotes = flags & QUOTES_ESC;
6296
6297         name = p + 1;
6298
6299         while ((c = *++p) != '\0') {
6300                 switch (c) {
6301                 case CTLESC:
6302                         return startp;
6303                 case CTLQUOTEMARK:
6304                         return startp;
6305                 case ':':
6306                         if (flags & EXP_VARTILDE)
6307                                 goto done;
6308                         break;
6309                 case '/':
6310                 case CTLENDVAR:
6311                         goto done;
6312                 }
6313         }
6314  done:
6315         *p = '\0';
6316         if (*name == '\0') {
6317                 home = lookupvar("HOME");
6318         } else {
6319                 pw = getpwnam(name);
6320                 if (pw == NULL)
6321                         goto lose;
6322                 home = pw->pw_dir;
6323         }
6324         if (!home || !*home)
6325                 goto lose;
6326         *p = c;
6327         strtodest(home, SQSYNTAX, quotes);
6328         return p;
6329  lose:
6330         *p = c;
6331         return startp;
6332 }
6333
6334 /*
6335  * Execute a command inside back quotes.  If it's a builtin command, we
6336  * want to save its output in a block obtained from malloc.  Otherwise
6337  * we fork off a subprocess and get the output of the command via a pipe.
6338  * Should be called with interrupts off.
6339  */
6340 struct backcmd {                /* result of evalbackcmd */
6341         int fd;                 /* file descriptor to read from */
6342         int nleft;              /* number of chars in buffer */
6343         char *buf;              /* buffer */
6344         struct job *jp;         /* job structure for command */
6345 };
6346
6347 /* These forward decls are needed to use "eval" code for backticks handling: */
6348 /* flags in argument to evaltree */
6349 #define EV_EXIT    01           /* exit after evaluating tree */
6350 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6351 static int evaltree(union node *, int);
6352
6353 /* An evaltree() which is known to never return.
6354  * Used to use an alias:
6355  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6356  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6357  */
6358 static ALWAYS_INLINE NORETURN void
6359 evaltreenr(union node *n, int flags)
6360 {
6361         evaltree(n, flags);
6362         bb_unreachable(abort());
6363         /* NOTREACHED */
6364 }
6365
6366 static void FAST_FUNC
6367 evalbackcmd(union node *n, struct backcmd *result)
6368 {
6369         int pip[2];
6370         struct job *jp;
6371
6372         result->fd = -1;
6373         result->buf = NULL;
6374         result->nleft = 0;
6375         result->jp = NULL;
6376         if (n == NULL) {
6377                 goto out;
6378         }
6379
6380         if (pipe(pip) < 0)
6381                 ash_msg_and_raise_perror("can't create pipe");
6382         jp = makejob(/*n,*/ 1);
6383         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6384                 /* child */
6385                 FORCE_INT_ON;
6386                 close(pip[0]);
6387                 if (pip[1] != 1) {
6388                         /*close(1);*/
6389                         dup2_or_raise(pip[1], 1);
6390                         close(pip[1]);
6391                 }
6392 /* TODO: eflag clearing makes the following not abort:
6393  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6394  * which is what bash does (unless it is in POSIX mode).
6395  * dash deleted "eflag = 0" line in the commit
6396  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6397  *  [EVAL] Don't clear eflag in evalbackcmd
6398  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6399  */
6400                 eflag = 0;
6401                 ifsfree();
6402                 evaltreenr(n, EV_EXIT);
6403                 /* NOTREACHED */
6404         }
6405         /* parent */
6406         close(pip[1]);
6407         result->fd = pip[0];
6408         result->jp = jp;
6409
6410  out:
6411         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6412                 result->fd, result->buf, result->nleft, result->jp));
6413 }
6414
6415 /*
6416  * Expand stuff in backwards quotes.
6417  */
6418 static void
6419 expbackq(union node *cmd, int flag)
6420 {
6421         struct backcmd in;
6422         int i;
6423         char buf[128];
6424         char *p;
6425         char *dest;
6426         int startloc;
6427         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6428         struct stackmark smark;
6429
6430         INT_OFF;
6431         startloc = expdest - (char *)stackblock();
6432         pushstackmark(&smark, startloc);
6433         evalbackcmd(cmd, &in);
6434         popstackmark(&smark);
6435
6436         p = in.buf;
6437         i = in.nleft;
6438         if (i == 0)
6439                 goto read;
6440         for (;;) {
6441                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6442  read:
6443                 if (in.fd < 0)
6444                         break;
6445                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6446                 TRACE(("expbackq: read returns %d\n", i));
6447                 if (i <= 0)
6448                         break;
6449                 p = buf;
6450         }
6451
6452         free(in.buf);
6453         if (in.fd >= 0) {
6454                 close(in.fd);
6455                 back_exitstatus = waitforjob(in.jp);
6456         }
6457         INT_ON;
6458
6459         /* Eat all trailing newlines */
6460         dest = expdest;
6461         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6462                 STUNPUTC(dest);
6463         expdest = dest;
6464
6465         if (!(flag & EXP_QUOTED))
6466                 recordregion(startloc, dest - (char *)stackblock(), 0);
6467         TRACE(("evalbackq: size:%d:'%.*s'\n",
6468                 (int)((dest - (char *)stackblock()) - startloc),
6469                 (int)((dest - (char *)stackblock()) - startloc),
6470                 stackblock() + startloc));
6471 }
6472
6473 #if ENABLE_FEATURE_SH_MATH
6474 /*
6475  * Expand arithmetic expression.  Backup to start of expression,
6476  * evaluate, place result in (backed up) result, adjust string position.
6477  */
6478 static void
6479 expari(int flag)
6480 {
6481         char *p, *start;
6482         int begoff;
6483         int len;
6484
6485         /* ifsfree(); */
6486
6487         /*
6488          * This routine is slightly over-complicated for
6489          * efficiency.  Next we scan backwards looking for the
6490          * start of arithmetic.
6491          */
6492         start = stackblock();
6493         p = expdest - 1;
6494         *p = '\0';
6495         p--;
6496         while (1) {
6497                 int esc;
6498
6499                 while ((unsigned char)*p != CTLARI) {
6500                         p--;
6501 #if DEBUG
6502                         if (p < start) {
6503                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6504                         }
6505 #endif
6506                 }
6507
6508                 esc = esclen(start, p);
6509                 if (!(esc % 2)) {
6510                         break;
6511                 }
6512
6513                 p -= esc + 1;
6514         }
6515
6516         begoff = p - start;
6517
6518         removerecordregions(begoff);
6519
6520         expdest = p;
6521
6522         if (flag & QUOTES_ESC)
6523                 rmescapes(p + 1, 0, NULL);
6524
6525         len = cvtnum(ash_arith(p + 1));
6526
6527         if (!(flag & EXP_QUOTED))
6528                 recordregion(begoff, begoff + len, 0);
6529 }
6530 #endif
6531
6532 /* argstr needs it */
6533 static char *evalvar(char *p, int flags);
6534
6535 /*
6536  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6537  * characters to allow for further processing.  Otherwise treat
6538  * $@ like $* since no splitting will be performed.
6539  */
6540 static void
6541 argstr(char *p, int flags)
6542 {
6543         static const char spclchars[] ALIGN1 = {
6544                 '=',
6545                 ':',
6546                 CTLQUOTEMARK,
6547                 CTLENDVAR,
6548                 CTLESC,
6549                 CTLVAR,
6550                 CTLBACKQ,
6551 #if ENABLE_FEATURE_SH_MATH
6552                 CTLENDARI,
6553 #endif
6554                 '\0'
6555         };
6556         const char *reject = spclchars;
6557         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6558         int inquotes;
6559         size_t length;
6560         int startloc;
6561
6562         if (!(flags & EXP_VARTILDE)) {
6563                 reject += 2;
6564         } else if (flags & EXP_VARTILDE2) {
6565                 reject++;
6566         }
6567         inquotes = 0;
6568         length = 0;
6569         if (flags & EXP_TILDE) {
6570                 char *q;
6571
6572                 flags &= ~EXP_TILDE;
6573  tilde:
6574                 q = p;
6575                 if (*q == '~')
6576                         p = exptilde(p, q, flags);
6577         }
6578  start:
6579         startloc = expdest - (char *)stackblock();
6580         for (;;) {
6581                 unsigned char c;
6582
6583                 length += strcspn(p + length, reject);
6584                 c = p[length];
6585                 if (c) {
6586                         if (!(c & 0x80)
6587                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6588                         ) {
6589                                 /* c == '=' || c == ':' || c == CTLENDARI */
6590                                 length++;
6591                         }
6592                 }
6593                 if (length > 0) {
6594                         int newloc;
6595                         expdest = stack_nputstr(p, length, expdest);
6596                         newloc = expdest - (char *)stackblock();
6597                         if (breakall && !inquotes && newloc > startloc) {
6598                                 recordregion(startloc, newloc, 0);
6599                         }
6600                         startloc = newloc;
6601                 }
6602                 p += length + 1;
6603                 length = 0;
6604
6605                 switch (c) {
6606                 case '\0':
6607                         goto breakloop;
6608                 case '=':
6609                         if (flags & EXP_VARTILDE2) {
6610                                 p--;
6611                                 continue;
6612                         }
6613                         flags |= EXP_VARTILDE2;
6614                         reject++;
6615                         /* fall through */
6616                 case ':':
6617                         /*
6618                          * sort of a hack - expand tildes in variable
6619                          * assignments (after the first '=' and after ':'s).
6620                          */
6621                         if (*--p == '~') {
6622                                 goto tilde;
6623                         }
6624                         continue;
6625                 }
6626
6627                 switch (c) {
6628                 case CTLENDVAR: /* ??? */
6629                         goto breakloop;
6630                 case CTLQUOTEMARK:
6631                         inquotes ^= EXP_QUOTED;
6632                         /* "$@" syntax adherence hack */
6633                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6634                                 p = evalvar(p + 1, flags | inquotes) + 1;
6635                                 goto start;
6636                         }
6637  addquote:
6638                         if (flags & QUOTES_ESC) {
6639                                 p--;
6640                                 length++;
6641                                 startloc++;
6642                         }
6643                         break;
6644                 case CTLESC:
6645                         startloc++;
6646                         length++;
6647
6648                         /*
6649                          * Quoted parameter expansion pattern: remove quote
6650                          * unless inside inner quotes or we have a literal
6651                          * backslash.
6652                          */
6653                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6654                             EXP_QPAT && *p != '\\')
6655                                 break;
6656
6657                         goto addquote;
6658                 case CTLVAR:
6659                         TRACE(("argstr: evalvar('%s')\n", p));
6660                         p = evalvar(p, flags | inquotes);
6661                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6662                         goto start;
6663                 case CTLBACKQ:
6664                         expbackq(argbackq->n, flags | inquotes);
6665                         argbackq = argbackq->next;
6666                         goto start;
6667 #if ENABLE_FEATURE_SH_MATH
6668                 case CTLENDARI:
6669                         p--;
6670                         expari(flags | inquotes);
6671                         goto start;
6672 #endif
6673                 }
6674         }
6675  breakloop: ;
6676 }
6677
6678 static char *
6679 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6680                 char *pattern, int quotes, int zero)
6681 {
6682         char *loc, *loc2;
6683         char c;
6684
6685         loc = startp;
6686         loc2 = rmesc;
6687         do {
6688                 int match;
6689                 const char *s = loc2;
6690
6691                 c = *loc2;
6692                 if (zero) {
6693                         *loc2 = '\0';
6694                         s = rmesc;
6695                 }
6696                 match = pmatch(pattern, s);
6697
6698                 *loc2 = c;
6699                 if (match)
6700                         return loc;
6701                 if (quotes && (unsigned char)*loc == CTLESC)
6702                         loc++;
6703                 loc++;
6704                 loc2++;
6705         } while (c);
6706         return NULL;
6707 }
6708
6709 static char *
6710 scanright(char *startp, char *rmesc, char *rmescend,
6711                 char *pattern, int quotes, int match_at_start)
6712 {
6713 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6714         int try2optimize = match_at_start;
6715 #endif
6716         int esc = 0;
6717         char *loc;
6718         char *loc2;
6719
6720         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6721          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6722          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6723          * Logic:
6724          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6725          * and on each iteration they go back two/one char until they reach the beginning.
6726          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6727          */
6728         /* TODO: document in what other circumstances we are called. */
6729
6730         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6731                 int match;
6732                 char c = *loc2;
6733                 const char *s = loc2;
6734                 if (match_at_start) {
6735                         *loc2 = '\0';
6736                         s = rmesc;
6737                 }
6738                 match = pmatch(pattern, s);
6739                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6740                 *loc2 = c;
6741                 if (match)
6742                         return loc;
6743 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6744                 if (try2optimize) {
6745                         /* Maybe we can optimize this:
6746                          * if pattern ends with unescaped *, we can avoid checking
6747                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6748                          * it won't match truncated "raw_value_of_" strings too.
6749                          */
6750                         unsigned plen = strlen(pattern);
6751                         /* Does it end with "*"? */
6752                         if (plen != 0 && pattern[--plen] == '*') {
6753                                 /* "xxxx*" is not escaped */
6754                                 /* "xxx\*" is escaped */
6755                                 /* "xx\\*" is not escaped */
6756                                 /* "x\\\*" is escaped */
6757                                 int slashes = 0;
6758                                 while (plen != 0 && pattern[--plen] == '\\')
6759                                         slashes++;
6760                                 if (!(slashes & 1))
6761                                         break; /* ends with unescaped "*" */
6762                         }
6763                         try2optimize = 0;
6764                 }
6765 #endif
6766                 loc--;
6767                 if (quotes) {
6768                         if (--esc < 0) {
6769                                 esc = esclen(startp, loc);
6770                         }
6771                         if (esc % 2) {
6772                                 esc--;
6773                                 loc--;
6774                         }
6775                 }
6776         }
6777         return NULL;
6778 }
6779
6780 static void varunset(const char *, const char *, const char *, int) NORETURN;
6781 static void
6782 varunset(const char *end, const char *var, const char *umsg, int varflags)
6783 {
6784         const char *msg;
6785         const char *tail;
6786
6787         tail = nullstr;
6788         msg = "parameter not set";
6789         if (umsg) {
6790                 if ((unsigned char)*end == CTLENDVAR) {
6791                         if (varflags & VSNUL)
6792                                 tail = " or null";
6793                 } else {
6794                         msg = umsg;
6795                 }
6796         }
6797         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6798 }
6799
6800 static const char *
6801 subevalvar(char *p, char *varname, int strloc, int subtype,
6802                 int startloc, int varflags, int flag)
6803 {
6804         struct nodelist *saveargbackq = argbackq;
6805         int quotes = flag & QUOTES_ESC;
6806         char *startp;
6807         char *loc;
6808         char *rmesc, *rmescend;
6809         char *str;
6810         int amount, resetloc;
6811         int argstr_flags;
6812         IF_BASH_PATTERN_SUBST(int workloc;)
6813         IF_BASH_PATTERN_SUBST(int slash_pos;)
6814         IF_BASH_PATTERN_SUBST(char *repl;)
6815         int zero;
6816         char *(*scan)(char*, char*, char*, char*, int, int);
6817
6818         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6819         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6820
6821 #if BASH_PATTERN_SUBST
6822         /* For "${v/pattern/repl}", we must find the delimiter _before_
6823          * argstr() call expands possible variable references in pattern:
6824          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6825          */
6826         repl = NULL;
6827         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6828                 /* Find '/' and replace with NUL */
6829                 repl = p;
6830                 for (;;) {
6831                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6832                         if (*repl == '\0') {
6833                                 repl = NULL;
6834                                 break;
6835                         }
6836                         if (*repl == '/') {
6837                                 *repl = '\0';
6838                                 break;
6839                         }
6840                         if ((unsigned char)*repl == CTLESC && repl[1])
6841                                 repl++;
6842                         repl++;
6843                 }
6844         }
6845 #endif
6846         argstr_flags = EXP_TILDE;
6847         if (subtype != VSASSIGN && subtype != VSQUESTION)
6848                 argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE);
6849         argstr(p, argstr_flags);
6850 #if BASH_PATTERN_SUBST
6851         slash_pos = -1;
6852         if (repl) {
6853                 slash_pos = expdest - ((char *)stackblock() + strloc);
6854                 STPUTC('/', expdest);
6855                 argstr(repl + 1, argstr_flags);
6856                 *repl = '/';
6857         }
6858 #endif
6859         STPUTC('\0', expdest);
6860         argbackq = saveargbackq;
6861         startp = (char *)stackblock() + startloc;
6862         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6863
6864         switch (subtype) {
6865         case VSASSIGN:
6866                 setvar0(varname, startp);
6867                 amount = startp - expdest;
6868                 STADJUST(amount, expdest);
6869                 return startp;
6870
6871         case VSQUESTION:
6872                 varunset(p, varname, startp, varflags);
6873                 /* NOTREACHED */
6874
6875 #if BASH_SUBSTR
6876         case VSSUBSTR: {
6877                 int pos, len, orig_len;
6878                 char *colon;
6879
6880                 loc = str = stackblock() + strloc;
6881
6882                 /* Read POS in ${var:POS:LEN} */
6883                 colon = strchr(loc, ':');
6884                 if (colon) *colon = '\0';
6885                 pos = substr_atoi(loc);
6886                 if (colon) *colon = ':';
6887
6888                 /* Read LEN in ${var:POS:LEN} */
6889                 len = str - startp - 1;
6890                 /* *loc != '\0', guaranteed by parser */
6891                 if (quotes) {
6892                         char *ptr;
6893                         /* Adjust the length by the number of escapes */
6894                         for (ptr = startp; ptr < (str - 1); ptr++) {
6895                                 if ((unsigned char)*ptr == CTLESC) {
6896                                         len--;
6897                                         ptr++;
6898                                 }
6899                         }
6900                 }
6901                 orig_len = len;
6902                 if (*loc++ == ':') {
6903                         /* ${var::LEN} */
6904                         len = substr_atoi(loc);
6905                 } else {
6906                         /* Skip POS in ${var:POS:LEN} */
6907                         len = orig_len;
6908                         while (*loc && *loc != ':')
6909                                 loc++;
6910                         if (*loc++ == ':')
6911                                 len = substr_atoi(loc);
6912                 }
6913                 if (pos < 0) {
6914                         /* ${VAR:$((-n)):l} starts n chars from the end */
6915                         pos = orig_len + pos;
6916                 }
6917                 if ((unsigned)pos >= orig_len) {
6918                         /* apart from obvious ${VAR:999999:l},
6919                          * covers ${VAR:$((-9999999)):l} - result is ""
6920                          * (bash compat)
6921                          */
6922                         pos = 0;
6923                         len = 0;
6924                 }
6925                 if (len < 0) {
6926                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6927                         len = (orig_len - pos) + len;
6928                 }
6929                 if ((unsigned)len > (orig_len - pos))
6930                         len = orig_len - pos;
6931
6932                 for (str = startp; pos; str++, pos--) {
6933                         if (quotes && (unsigned char)*str == CTLESC)
6934                                 str++;
6935                 }
6936                 for (loc = startp; len; len--) {
6937                         if (quotes && (unsigned char)*str == CTLESC)
6938                                 *loc++ = *str++;
6939                         *loc++ = *str++;
6940                 }
6941                 *loc = '\0';
6942                 amount = loc - expdest;
6943                 STADJUST(amount, expdest);
6944                 return loc;
6945         }
6946 #endif /* BASH_SUBSTR */
6947         }
6948
6949         resetloc = expdest - (char *)stackblock();
6950
6951 #if BASH_PATTERN_SUBST
6952         repl = NULL;
6953
6954         /* We'll comeback here if we grow the stack while handling
6955          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6956          * stack will need rebasing, and we'll need to remove our work
6957          * areas each time
6958          */
6959  restart:
6960 #endif
6961
6962         amount = expdest - ((char *)stackblock() + resetloc);
6963         STADJUST(-amount, expdest);
6964         startp = (char *)stackblock() + startloc;
6965
6966         rmesc = startp;
6967         rmescend = (char *)stackblock() + strloc;
6968         //bb_error_msg("str7:'%s'", rmescend);
6969         if (quotes) {
6970 //TODO: how to handle slash_pos here if string changes (shortens?)
6971                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
6972                 if (rmesc != startp) {
6973                         rmescend = expdest;
6974                         startp = (char *)stackblock() + startloc;
6975                 }
6976         }
6977         rmescend--;
6978         str = (char *)stackblock() + strloc;
6979         /*
6980          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6981          * The result is a_\_z_c (not a\_\_z_c)!
6982          *
6983          * The search pattern and replace string treat backslashes differently!
6984          * "&slash_pos" causes rmescapes() to work differently on the pattern
6985          * and string.  It's only used on the first call.
6986          */
6987         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
6988         rmescapes(str, RMESCAPE_GLOB,
6989                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
6990         );
6991
6992 #if BASH_PATTERN_SUBST
6993         workloc = expdest - (char *)stackblock();
6994         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6995                 int len;
6996                 char *idx, *end;
6997
6998                 if (!repl) {
6999                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7000                         repl = nullstr;
7001                         if (slash_pos >= 0) {
7002                                 repl = str + slash_pos;
7003                                 *repl++ = '\0';
7004                         }
7005                 }
7006                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7007
7008                 /* If there's no pattern to match, return the expansion unmolested */
7009                 if (str[0] == '\0')
7010                         return NULL;
7011
7012                 len = 0;
7013                 idx = startp;
7014                 end = str - 1;
7015                 while (idx < end) {
7016  try_to_match:
7017                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7018                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7019                         if (!loc) {
7020                                 /* No match, advance */
7021                                 char *restart_detect = stackblock();
7022  skip_matching:
7023                                 STPUTC(*idx, expdest);
7024                                 if (quotes && (unsigned char)*idx == CTLESC) {
7025                                         idx++;
7026                                         len++;
7027                                         STPUTC(*idx, expdest);
7028                                 }
7029                                 if (stackblock() != restart_detect)
7030                                         goto restart;
7031                                 idx++;
7032                                 len++;
7033                                 rmesc++;
7034                                 /* continue; - prone to quadratic behavior, smarter code: */
7035                                 if (idx >= end)
7036                                         break;
7037                                 if (str[0] == '*') {
7038                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7039                                          * it would never match "ong_string" etc, no point in trying.
7040                                          */
7041                                         goto skip_matching;
7042                                 }
7043                                 goto try_to_match;
7044                         }
7045
7046                         if (subtype == VSREPLACEALL) {
7047                                 while (idx < loc) {
7048                                         if (quotes && (unsigned char)*idx == CTLESC)
7049                                                 idx++;
7050                                         idx++;
7051                                         rmesc++;
7052                                 }
7053                         } else {
7054                                 idx = loc;
7055                         }
7056
7057                         //bb_error_msg("repl:'%s'", repl);
7058                         for (loc = (char*)repl; *loc; loc++) {
7059                                 char *restart_detect = stackblock();
7060                                 if (quotes && *loc == '\\') {
7061                                         STPUTC(CTLESC, expdest);
7062                                         len++;
7063                                 }
7064                                 STPUTC(*loc, expdest);
7065                                 if (stackblock() != restart_detect)
7066                                         goto restart;
7067                                 len++;
7068                         }
7069
7070                         if (subtype == VSREPLACE) {
7071                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7072                                 while (*idx) {
7073                                         char *restart_detect = stackblock();
7074                                         STPUTC(*idx, expdest);
7075                                         if (stackblock() != restart_detect)
7076                                                 goto restart;
7077                                         len++;
7078                                         idx++;
7079                                 }
7080                                 break;
7081                         }
7082                 }
7083
7084                 /* We've put the replaced text into a buffer at workloc, now
7085                  * move it to the right place and adjust the stack.
7086                  */
7087                 STPUTC('\0', expdest);
7088                 startp = (char *)stackblock() + startloc;
7089                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7090                 //bb_error_msg("startp:'%s'", startp);
7091                 amount = expdest - (startp + len);
7092                 STADJUST(-amount, expdest);
7093                 return startp;
7094         }
7095 #endif /* BASH_PATTERN_SUBST */
7096
7097         subtype -= VSTRIMRIGHT;
7098 #if DEBUG
7099         if (subtype < 0 || subtype > 7)
7100                 abort();
7101 #endif
7102         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7103         zero = subtype >> 1;
7104         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7105         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7106
7107         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7108         if (loc) {
7109                 if (zero) {
7110                         memmove(startp, loc, str - loc);
7111                         loc = startp + (str - loc) - 1;
7112                 }
7113                 *loc = '\0';
7114                 amount = loc - expdest;
7115                 STADJUST(amount, expdest);
7116         }
7117         return loc;
7118 }
7119
7120 /*
7121  * Add the value of a specialized variable to the stack string.
7122  * name parameter (examples):
7123  * ash -c 'echo $1'      name:'1='
7124  * ash -c 'echo $qwe'    name:'qwe='
7125  * ash -c 'echo $$'      name:'$='
7126  * ash -c 'echo ${$}'    name:'$='
7127  * ash -c 'echo ${$##q}' name:'$=q'
7128  * ash -c 'echo ${#$}'   name:'$='
7129  * note: examples with bad shell syntax:
7130  * ash -c 'echo ${#$1}'  name:'$=1'
7131  * ash -c 'echo ${#1#}'  name:'1=#'
7132  */
7133 static NOINLINE ssize_t
7134 varvalue(char *name, int varflags, int flags, int *quotedp)
7135 {
7136         const char *p;
7137         int num;
7138         int i;
7139         ssize_t len = 0;
7140         int sep;
7141         int quoted = *quotedp;
7142         int subtype = varflags & VSTYPE;
7143         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7144         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7145         int syntax;
7146
7147         sep = (flags & EXP_FULL) << CHAR_BIT;
7148         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7149
7150         switch (*name) {
7151         case '$':
7152                 num = rootpid;
7153                 goto numvar;
7154         case '?':
7155                 num = exitstatus;
7156                 goto numvar;
7157         case '#':
7158                 num = shellparam.nparam;
7159                 goto numvar;
7160         case '!':
7161                 num = backgndpid;
7162                 if (num == 0)
7163                         return -1;
7164  numvar:
7165                 len = cvtnum(num);
7166                 goto check_1char_name;
7167         case '-':
7168                 expdest = makestrspace(NOPTS, expdest);
7169                 for (i = NOPTS - 1; i >= 0; i--) {
7170                         if (optlist[i]) {
7171                                 USTPUTC(optletters(i), expdest);
7172                                 len++;
7173                         }
7174                 }
7175  check_1char_name:
7176 #if 0
7177                 /* handles cases similar to ${#$1} */
7178                 if (name[2] != '\0')
7179                         raise_error_syntax("bad substitution");
7180 #endif
7181                 break;
7182         case '@':
7183                 if (quoted && sep)
7184                         goto param;
7185                 /* fall through */
7186         case '*': {
7187                 char **ap;
7188                 char sepc;
7189
7190                 if (quoted)
7191                         sep = 0;
7192                 sep |= ifsset() ? ifsval()[0] : ' ';
7193  param:
7194                 sepc = sep;
7195                 *quotedp = !sepc;
7196                 ap = shellparam.p;
7197                 if (!ap)
7198                         return -1;
7199                 while ((p = *ap++) != NULL) {
7200                         len += strtodest(p, syntax, quotes);
7201
7202                         if (*ap && sep) {
7203                                 len++;
7204                                 memtodest(&sepc, 1, syntax, quotes);
7205                         }
7206                 }
7207                 break;
7208         } /* case '*' */
7209         case '0':
7210         case '1':
7211         case '2':
7212         case '3':
7213         case '4':
7214         case '5':
7215         case '6':
7216         case '7':
7217         case '8':
7218         case '9':
7219                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7220                 if (num < 0 || num > shellparam.nparam)
7221                         return -1;
7222                 p = num ? shellparam.p[num - 1] : arg0;
7223                 goto value;
7224         default:
7225                 /* NB: name has form "VAR=..." */
7226                 p = lookupvar(name);
7227  value:
7228                 if (!p)
7229                         return -1;
7230
7231                 len = strtodest(p, syntax, quotes);
7232 #if ENABLE_UNICODE_SUPPORT
7233                 if (subtype == VSLENGTH && len > 0) {
7234                         reinit_unicode_for_ash();
7235                         if (unicode_status == UNICODE_ON) {
7236                                 STADJUST(-len, expdest);
7237                                 discard = 0;
7238                                 len = unicode_strlen(p);
7239                         }
7240                 }
7241 #endif
7242                 break;
7243         }
7244
7245         if (discard)
7246                 STADJUST(-len, expdest);
7247         return len;
7248 }
7249
7250 /*
7251  * Expand a variable, and return a pointer to the next character in the
7252  * input string.
7253  */
7254 static char *
7255 evalvar(char *p, int flag)
7256 {
7257         char varflags;
7258         char subtype;
7259         int quoted;
7260         char easy;
7261         char *var;
7262         int patloc;
7263         int startloc;
7264         ssize_t varlen;
7265
7266         varflags = (unsigned char) *p++;
7267         subtype = varflags & VSTYPE;
7268
7269         if (!subtype)
7270                 raise_error_syntax("bad substitution");
7271
7272         quoted = flag & EXP_QUOTED;
7273         var = p;
7274         easy = (!quoted || (*var == '@' && shellparam.nparam));
7275         startloc = expdest - (char *)stackblock();
7276         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7277
7278  again:
7279         varlen = varvalue(var, varflags, flag, &quoted);
7280         if (varflags & VSNUL)
7281                 varlen--;
7282
7283         if (subtype == VSPLUS) {
7284                 varlen = -1 - varlen;
7285                 goto vsplus;
7286         }
7287
7288         if (subtype == VSMINUS) {
7289  vsplus:
7290                 if (varlen < 0) {
7291                         argstr(
7292                                 p,
7293                                 flag | EXP_TILDE | EXP_WORD
7294                         );
7295                         goto end;
7296                 }
7297                 goto record;
7298         }
7299
7300         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7301                 if (varlen >= 0)
7302                         goto record;
7303
7304                 subevalvar(p, var, 0, subtype, startloc, varflags,
7305                            flag & ~QUOTES_ESC);
7306                 varflags &= ~VSNUL;
7307                 /*
7308                  * Remove any recorded regions beyond
7309                  * start of variable
7310                  */
7311                 removerecordregions(startloc);
7312                 goto again;
7313         }
7314
7315         if (varlen < 0 && uflag)
7316                 varunset(p, var, 0, 0);
7317
7318         if (subtype == VSLENGTH) {
7319                 cvtnum(varlen > 0 ? varlen : 0);
7320                 goto record;
7321         }
7322
7323         if (subtype == VSNORMAL) {
7324  record:
7325                 if (!easy)
7326                         goto end;
7327                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7328                 goto end;
7329         }
7330
7331 #if DEBUG
7332         switch (subtype) {
7333         case VSTRIMLEFT:
7334         case VSTRIMLEFTMAX:
7335         case VSTRIMRIGHT:
7336         case VSTRIMRIGHTMAX:
7337 #if BASH_SUBSTR
7338         case VSSUBSTR:
7339 #endif
7340 #if BASH_PATTERN_SUBST
7341         case VSREPLACE:
7342         case VSREPLACEALL:
7343 #endif
7344                 break;
7345         default:
7346                 abort();
7347         }
7348 #endif
7349
7350         if (varlen >= 0) {
7351                 /*
7352                  * Terminate the string and start recording the pattern
7353                  * right after it
7354                  */
7355                 STPUTC('\0', expdest);
7356                 patloc = expdest - (char *)stackblock();
7357                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7358                                 startloc, varflags, flag)) {
7359                         int amount = expdest - (
7360                                 (char *)stackblock() + patloc - 1
7361                         );
7362                         STADJUST(-amount, expdest);
7363                 }
7364                 /* Remove any recorded regions beyond start of variable */
7365                 removerecordregions(startloc);
7366                 goto record;
7367         }
7368
7369  end:
7370         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7371                 int nesting = 1;
7372                 for (;;) {
7373                         unsigned char c = *p++;
7374                         if (c == CTLESC)
7375                                 p++;
7376                         else if (c == CTLBACKQ) {
7377                                 if (varlen >= 0)
7378                                         argbackq = argbackq->next;
7379                         } else if (c == CTLVAR) {
7380                                 if ((*p++ & VSTYPE) != VSNORMAL)
7381                                         nesting++;
7382                         } else if (c == CTLENDVAR) {
7383                                 if (--nesting == 0)
7384                                         break;
7385                         }
7386                 }
7387         }
7388         return p;
7389 }
7390
7391 /*
7392  * Add a file name to the list.
7393  */
7394 static void
7395 addfname(const char *name)
7396 {
7397         struct strlist *sp;
7398
7399         sp = stzalloc(sizeof(*sp));
7400         sp->text = sstrdup(name);
7401         *exparg.lastp = sp;
7402         exparg.lastp = &sp->next;
7403 }
7404
7405 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7406 static int
7407 hasmeta(const char *p)
7408 {
7409         static const char chars[] ALIGN1 = {
7410                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7411         };
7412
7413         for (;;) {
7414                 p = strpbrk(p, chars);
7415                 if (!p)
7416                         break;
7417                 switch ((unsigned char) *p) {
7418                 case CTLQUOTEMARK:
7419                         for (;;) {
7420                                 p++;
7421                                 if (*p == CTLQUOTEMARK)
7422                                         break;
7423                                 if (*p == CTLESC)
7424                                         p++;
7425                                 if (*p == '\0') /* huh? */
7426                                         return 0;
7427                         }
7428                         break;
7429                 case '\\':
7430                 case CTLESC:
7431                         p++;
7432                         if (*p == '\0')
7433                                 return 0;
7434                         break;
7435                 case '[':
7436                         if (!strchr(p + 1, ']')) {
7437                                 /* It's not a properly closed [] pattern,
7438                                  * but other metas may follow. Continue checking.
7439                                  * my[file* _is_ globbed by bash
7440                                  * and matches filenames like "my[file1".
7441                                  */
7442                                 break;
7443                         }
7444                         /* fallthrough */
7445                 default:
7446                 /* case '*': */
7447                 /* case '?': */
7448                         return 1;
7449                 }
7450                 p++;
7451         }
7452
7453         return 0;
7454 }
7455
7456 /* If we want to use glob() from libc... */
7457 #if !ENABLE_ASH_INTERNAL_GLOB
7458
7459 /* Add the result of glob() to the list */
7460 static void
7461 addglob(const glob_t *pglob)
7462 {
7463         char **p = pglob->gl_pathv;
7464
7465         do {
7466                 addfname(*p);
7467         } while (*++p);
7468 }
7469 static void
7470 expandmeta(struct strlist *str /*, int flag*/)
7471 {
7472         /* TODO - EXP_REDIR */
7473
7474         while (str) {
7475                 char *p;
7476                 glob_t pglob;
7477                 int i;
7478
7479                 if (fflag)
7480                         goto nometa;
7481
7482                 if (!hasmeta(str->text))
7483                         goto nometa;
7484
7485                 INT_OFF;
7486                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7487 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7488 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7489 //
7490 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7491 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7492 // Which means you need to unescape the string, right? Not so fast:
7493 // if there _is_ a file named "file\?" (with backslash), it is returned
7494 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7495 // You DON'T KNOW by looking at the result whether you need to unescape it.
7496 //
7497 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7498 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7499 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7500 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7501 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7502 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7503                 i = glob(p, 0, NULL, &pglob);
7504                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7505                 if (p != str->text)
7506                         free(p);
7507                 switch (i) {
7508                 case 0:
7509 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7510                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7511                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7512                                 goto nometa2;
7513 #endif
7514                         addglob(&pglob);
7515                         globfree(&pglob);
7516                         INT_ON;
7517                         break;
7518                 case GLOB_NOMATCH:
7519  //nometa2:
7520                         globfree(&pglob);
7521                         INT_ON;
7522  nometa:
7523                         *exparg.lastp = str;
7524                         rmescapes(str->text, 0, NULL);
7525                         exparg.lastp = &str->next;
7526                         break;
7527                 default:        /* GLOB_NOSPACE */
7528                         globfree(&pglob);
7529                         INT_ON;
7530                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7531                 }
7532                 str = str->next;
7533         }
7534 }
7535
7536 #else
7537 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7538
7539 /*
7540  * Do metacharacter (i.e. *, ?, [...]) expansion.
7541  */
7542 static void
7543 expmeta(char *expdir, char *enddir, char *name)
7544 {
7545         char *p;
7546         const char *cp;
7547         char *start;
7548         char *endname;
7549         int metaflag;
7550         struct stat statb;
7551         DIR *dirp;
7552         struct dirent *dp;
7553         int atend;
7554         int matchdot;
7555         int esc;
7556
7557         metaflag = 0;
7558         start = name;
7559         for (p = name; esc = 0, *p; p += esc + 1) {
7560                 if (*p == '*' || *p == '?')
7561                         metaflag = 1;
7562                 else if (*p == '[') {
7563                         char *q = p + 1;
7564                         if (*q == '!')
7565                                 q++;
7566                         for (;;) {
7567                                 if (*q == '\\')
7568                                         q++;
7569                                 if (*q == '/' || *q == '\0')
7570                                         break;
7571                                 if (*++q == ']') {
7572                                         metaflag = 1;
7573                                         break;
7574                                 }
7575                         }
7576                 } else {
7577                         if (*p == '\\')
7578                                 esc++;
7579                         if (p[esc] == '/') {
7580                                 if (metaflag)
7581                                         break;
7582                                 start = p + esc + 1;
7583                         }
7584                 }
7585         }
7586         if (metaflag == 0) {    /* we've reached the end of the file name */
7587                 if (enddir != expdir)
7588                         metaflag++;
7589                 p = name;
7590                 do {
7591                         if (*p == '\\')
7592                                 p++;
7593                         *enddir++ = *p;
7594                 } while (*p++);
7595                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7596                         addfname(expdir);
7597                 return;
7598         }
7599         endname = p;
7600         if (name < start) {
7601                 p = name;
7602                 do {
7603                         if (*p == '\\')
7604                                 p++;
7605                         *enddir++ = *p++;
7606                 } while (p < start);
7607         }
7608         if (enddir == expdir) {
7609                 cp = ".";
7610         } else if (enddir == expdir + 1 && *expdir == '/') {
7611                 cp = "/";
7612         } else {
7613                 cp = expdir;
7614                 enddir[-1] = '\0';
7615         }
7616         dirp = opendir(cp);
7617         if (dirp == NULL)
7618                 return;
7619         if (enddir != expdir)
7620                 enddir[-1] = '/';
7621         if (*endname == 0) {
7622                 atend = 1;
7623         } else {
7624                 atend = 0;
7625                 *endname = '\0';
7626                 endname += esc + 1;
7627         }
7628         matchdot = 0;
7629         p = start;
7630         if (*p == '\\')
7631                 p++;
7632         if (*p == '.')
7633                 matchdot++;
7634         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7635                 if (dp->d_name[0] == '.' && !matchdot)
7636                         continue;
7637                 if (pmatch(start, dp->d_name)) {
7638                         if (atend) {
7639                                 strcpy(enddir, dp->d_name);
7640                                 addfname(expdir);
7641                         } else {
7642                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7643                                         continue;
7644                                 p[-1] = '/';
7645                                 expmeta(expdir, p, endname);
7646                         }
7647                 }
7648         }
7649         closedir(dirp);
7650         if (!atend)
7651                 endname[-esc - 1] = esc ? '\\' : '/';
7652 }
7653
7654 static struct strlist *
7655 msort(struct strlist *list, int len)
7656 {
7657         struct strlist *p, *q = NULL;
7658         struct strlist **lpp;
7659         int half;
7660         int n;
7661
7662         if (len <= 1)
7663                 return list;
7664         half = len >> 1;
7665         p = list;
7666         for (n = half; --n >= 0;) {
7667                 q = p;
7668                 p = p->next;
7669         }
7670         q->next = NULL;                 /* terminate first half of list */
7671         q = msort(list, half);          /* sort first half of list */
7672         p = msort(p, len - half);               /* sort second half */
7673         lpp = &list;
7674         for (;;) {
7675 #if ENABLE_LOCALE_SUPPORT
7676                 if (strcoll(p->text, q->text) < 0)
7677 #else
7678                 if (strcmp(p->text, q->text) < 0)
7679 #endif
7680                                                 {
7681                         *lpp = p;
7682                         lpp = &p->next;
7683                         p = *lpp;
7684                         if (p == NULL) {
7685                                 *lpp = q;
7686                                 break;
7687                         }
7688                 } else {
7689                         *lpp = q;
7690                         lpp = &q->next;
7691                         q = *lpp;
7692                         if (q == NULL) {
7693                                 *lpp = p;
7694                                 break;
7695                         }
7696                 }
7697         }
7698         return list;
7699 }
7700
7701 /*
7702  * Sort the results of file name expansion.  It calculates the number of
7703  * strings to sort and then calls msort (short for merge sort) to do the
7704  * work.
7705  */
7706 static struct strlist *
7707 expsort(struct strlist *str)
7708 {
7709         int len;
7710         struct strlist *sp;
7711
7712         len = 0;
7713         for (sp = str; sp; sp = sp->next)
7714                 len++;
7715         return msort(str, len);
7716 }
7717
7718 static void
7719 expandmeta(struct strlist *str /*, int flag*/)
7720 {
7721         /* TODO - EXP_REDIR */
7722
7723         while (str) {
7724                 char *expdir;
7725                 struct strlist **savelastp;
7726                 struct strlist *sp;
7727                 char *p;
7728
7729                 if (fflag)
7730                         goto nometa;
7731                 if (!hasmeta(str->text))
7732                         goto nometa;
7733                 savelastp = exparg.lastp;
7734
7735                 INT_OFF;
7736                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7737                 {
7738                         int i = strlen(str->text);
7739 //BUGGY estimation of how long expanded name can be
7740                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7741                 }
7742                 expmeta(expdir, expdir, p);
7743                 free(expdir);
7744                 if (p != str->text)
7745                         free(p);
7746                 INT_ON;
7747                 if (exparg.lastp == savelastp) {
7748                         /*
7749                          * no matches
7750                          */
7751  nometa:
7752                         *exparg.lastp = str;
7753                         rmescapes(str->text, 0, NULL);
7754                         exparg.lastp = &str->next;
7755                 } else {
7756                         *exparg.lastp = NULL;
7757                         *savelastp = sp = expsort(*savelastp);
7758                         while (sp->next != NULL)
7759                                 sp = sp->next;
7760                         exparg.lastp = &sp->next;
7761                 }
7762                 str = str->next;
7763         }
7764 }
7765 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7766
7767 /*
7768  * Perform variable substitution and command substitution on an argument,
7769  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7770  * perform splitting and file name expansion.  When arglist is NULL, perform
7771  * here document expansion.
7772  */
7773 static void
7774 expandarg(union node *arg, struct arglist *arglist, int flag)
7775 {
7776         struct strlist *sp;
7777         char *p;
7778
7779         argbackq = arg->narg.backquote;
7780         STARTSTACKSTR(expdest);
7781         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7782         argstr(arg->narg.text, flag);
7783         p = _STPUTC('\0', expdest);
7784         expdest = p - 1;
7785         if (arglist == NULL) {
7786                 /* here document expanded */
7787                 goto out;
7788         }
7789         p = grabstackstr(p);
7790         TRACE(("expandarg: p:'%s'\n", p));
7791         exparg.lastp = &exparg.list;
7792         /*
7793          * TODO - EXP_REDIR
7794          */
7795         if (flag & EXP_FULL) {
7796                 ifsbreakup(p, &exparg);
7797                 *exparg.lastp = NULL;
7798                 exparg.lastp = &exparg.list;
7799                 expandmeta(exparg.list /*, flag*/);
7800         } else {
7801                 sp = stzalloc(sizeof(*sp));
7802                 sp->text = p;
7803                 *exparg.lastp = sp;
7804                 exparg.lastp = &sp->next;
7805         }
7806         *exparg.lastp = NULL;
7807         if (exparg.list) {
7808                 *arglist->lastp = exparg.list;
7809                 arglist->lastp = exparg.lastp;
7810         }
7811
7812  out:
7813         ifsfree();
7814 }
7815
7816 /*
7817  * Expand shell variables and backquotes inside a here document.
7818  */
7819 static void
7820 expandhere(union node *arg, int fd)
7821 {
7822         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7823         full_write(fd, stackblock(), expdest - (char *)stackblock());
7824 }
7825
7826 /*
7827  * Returns true if the pattern matches the string.
7828  */
7829 static int
7830 patmatch(char *pattern, const char *string)
7831 {
7832         char *p = preglob(pattern, 0);
7833         int r = pmatch(p, string);
7834         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7835         return r;
7836 }
7837
7838 /*
7839  * See if a pattern matches in a case statement.
7840  */
7841 static int
7842 casematch(union node *pattern, char *val)
7843 {
7844         struct stackmark smark;
7845         int result;
7846
7847         setstackmark(&smark);
7848         argbackq = pattern->narg.backquote;
7849         STARTSTACKSTR(expdest);
7850         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7851         STACKSTRNUL(expdest);
7852         ifsfree();
7853         result = patmatch(stackblock(), val);
7854         popstackmark(&smark);
7855         return result;
7856 }
7857
7858
7859 /* ============ find_command */
7860
7861 struct builtincmd {
7862         const char *name;
7863         int (*builtin)(int, char **) FAST_FUNC;
7864         /* unsigned flags; */
7865 };
7866 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7867 /* "regular" builtins always take precedence over commands,
7868  * regardless of PATH=....%builtin... position */
7869 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7870 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7871
7872 struct cmdentry {
7873         smallint cmdtype;       /* CMDxxx */
7874         union param {
7875                 int index;
7876                 /* index >= 0 for commands without path (slashes) */
7877                 /* (TODO: what exactly does the value mean? PATH position?) */
7878                 /* index == -1 for commands with slashes */
7879                 /* index == (-2 - applet_no) for NOFORK applets */
7880                 const struct builtincmd *cmd;
7881                 struct funcnode *func;
7882         } u;
7883 };
7884 /* values of cmdtype */
7885 #define CMDUNKNOWN      -1      /* no entry in table for command */
7886 #define CMDNORMAL       0       /* command is an executable program */
7887 #define CMDFUNCTION     1       /* command is a shell function */
7888 #define CMDBUILTIN      2       /* command is a shell builtin */
7889
7890 /* action to find_command() */
7891 #define DO_ERR          0x01    /* prints errors */
7892 #define DO_ABS          0x02    /* checks absolute paths */
7893 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7894 #define DO_ALTPATH      0x08    /* using alternate path */
7895 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7896
7897 static void find_command(char *, struct cmdentry *, int, const char *);
7898
7899
7900 /* ============ Hashing commands */
7901
7902 /*
7903  * When commands are first encountered, they are entered in a hash table.
7904  * This ensures that a full path search will not have to be done for them
7905  * on each invocation.
7906  *
7907  * We should investigate converting to a linear search, even though that
7908  * would make the command name "hash" a misnomer.
7909  */
7910
7911 struct tblentry {
7912         struct tblentry *next;  /* next entry in hash chain */
7913         union param param;      /* definition of builtin function */
7914         smallint cmdtype;       /* CMDxxx */
7915         char rehash;            /* if set, cd done since entry created */
7916         char cmdname[1];        /* name of command */
7917 };
7918
7919 static struct tblentry **cmdtable;
7920 #define INIT_G_cmdtable() do { \
7921         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7922 } while (0)
7923
7924 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7925
7926
7927 static void
7928 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7929 {
7930 #if ENABLE_FEATURE_SH_STANDALONE
7931         if (applet_no >= 0) {
7932                 if (APPLET_IS_NOEXEC(applet_no)) {
7933                         clearenv();
7934                         while (*envp)
7935                                 putenv(*envp++);
7936                         popredir(/*drop:*/ 1);
7937                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7938                 }
7939                 /* re-exec ourselves with the new arguments */
7940                 execve(bb_busybox_exec_path, argv, envp);
7941                 /* If they called chroot or otherwise made the binary no longer
7942                  * executable, fall through */
7943         }
7944 #endif
7945
7946  repeat:
7947 #ifdef SYSV
7948         do {
7949                 execve(cmd, argv, envp);
7950         } while (errno == EINTR);
7951 #else
7952         execve(cmd, argv, envp);
7953 #endif
7954         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7955                 /* Run "cmd" as a shell script:
7956                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7957                  * "If the execve() function fails with ENOEXEC, the shell
7958                  * shall execute a command equivalent to having a shell invoked
7959                  * with the command name as its first operand,
7960                  * with any remaining arguments passed to the new shell"
7961                  *
7962                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7963                  * just call ourselves.
7964                  *
7965                  * Note that bash reads ~80 chars of the file, and if it sees
7966                  * a zero byte before it sees newline, it doesn't try to
7967                  * interpret it, but fails with "cannot execute binary file"
7968                  * message and exit code 126. For one, this prevents attempts
7969                  * to interpret foreign ELF binaries as shell scripts.
7970                  */
7971                 argv[0] = (char*) cmd;
7972                 cmd = bb_busybox_exec_path;
7973                 /* NB: this is only possible because all callers of shellexec()
7974                  * ensure that the argv[-1] slot exists!
7975                  */
7976                 argv--;
7977                 argv[0] = (char*) "ash";
7978                 goto repeat;
7979         }
7980 }
7981
7982 /*
7983  * Exec a program.  Never returns.  If you change this routine, you may
7984  * have to change the find_command routine as well.
7985  * argv[-1] must exist and be writable! See tryexec() for why.
7986  */
7987 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7988 static void shellexec(char *prog, char **argv, const char *path, int idx)
7989 {
7990         char *cmdname;
7991         int e;
7992         char **envp;
7993         int exerrno;
7994         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7995
7996         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
7997         if (strchr(prog, '/') != NULL
7998 #if ENABLE_FEATURE_SH_STANDALONE
7999          || (applet_no = find_applet_by_name(prog)) >= 0
8000 #endif
8001         ) {
8002                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8003                 if (applet_no >= 0) {
8004                         /* We tried execing ourself, but it didn't work.
8005                          * Maybe /proc/self/exe doesn't exist?
8006                          * Try $PATH search.
8007                          */
8008                         goto try_PATH;
8009                 }
8010                 e = errno;
8011         } else {
8012  try_PATH:
8013                 e = ENOENT;
8014                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8015                         if (--idx < 0 && pathopt == NULL) {
8016                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8017                                 if (errno != ENOENT && errno != ENOTDIR)
8018                                         e = errno;
8019                         }
8020                         stunalloc(cmdname);
8021                 }
8022         }
8023
8024         /* Map to POSIX errors */
8025         switch (e) {
8026         case EACCES:
8027                 exerrno = 126;
8028                 break;
8029         case ENOENT:
8030                 exerrno = 127;
8031                 break;
8032         default:
8033                 exerrno = 2;
8034                 break;
8035         }
8036         exitstatus = exerrno;
8037         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8038                 prog, e, suppress_int));
8039         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8040         /* NOTREACHED */
8041 }
8042
8043 static void
8044 printentry(struct tblentry *cmdp)
8045 {
8046         int idx;
8047         const char *path;
8048         char *name;
8049
8050         idx = cmdp->param.index;
8051         path = pathval();
8052         do {
8053                 name = path_advance(&path, cmdp->cmdname);
8054                 stunalloc(name);
8055         } while (--idx >= 0);
8056         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8057 }
8058
8059 /*
8060  * Clear out command entries.  The argument specifies the first entry in
8061  * PATH which has changed.
8062  */
8063 static void
8064 clearcmdentry(int firstchange)
8065 {
8066         struct tblentry **tblp;
8067         struct tblentry **pp;
8068         struct tblentry *cmdp;
8069
8070         INT_OFF;
8071         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8072                 pp = tblp;
8073                 while ((cmdp = *pp) != NULL) {
8074                         if ((cmdp->cmdtype == CMDNORMAL &&
8075                              cmdp->param.index >= firstchange)
8076                          || (cmdp->cmdtype == CMDBUILTIN &&
8077                              builtinloc >= firstchange)
8078                         ) {
8079                                 *pp = cmdp->next;
8080                                 free(cmdp);
8081                         } else {
8082                                 pp = &cmdp->next;
8083                         }
8084                 }
8085         }
8086         INT_ON;
8087 }
8088
8089 /*
8090  * Locate a command in the command hash table.  If "add" is nonzero,
8091  * add the command to the table if it is not already present.  The
8092  * variable "lastcmdentry" is set to point to the address of the link
8093  * pointing to the entry, so that delete_cmd_entry can delete the
8094  * entry.
8095  *
8096  * Interrupts must be off if called with add != 0.
8097  */
8098 static struct tblentry **lastcmdentry;
8099
8100 static struct tblentry *
8101 cmdlookup(const char *name, int add)
8102 {
8103         unsigned int hashval;
8104         const char *p;
8105         struct tblentry *cmdp;
8106         struct tblentry **pp;
8107
8108         p = name;
8109         hashval = (unsigned char)*p << 4;
8110         while (*p)
8111                 hashval += (unsigned char)*p++;
8112         hashval &= 0x7FFF;
8113         pp = &cmdtable[hashval % CMDTABLESIZE];
8114         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8115                 if (strcmp(cmdp->cmdname, name) == 0)
8116                         break;
8117                 pp = &cmdp->next;
8118         }
8119         if (add && cmdp == NULL) {
8120                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8121                                 + strlen(name)
8122                                 /* + 1 - already done because
8123                                  * tblentry::cmdname is char[1] */);
8124                 /*cmdp->next = NULL; - ckzalloc did it */
8125                 cmdp->cmdtype = CMDUNKNOWN;
8126                 strcpy(cmdp->cmdname, name);
8127         }
8128         lastcmdentry = pp;
8129         return cmdp;
8130 }
8131
8132 /*
8133  * Delete the command entry returned on the last lookup.
8134  */
8135 static void
8136 delete_cmd_entry(void)
8137 {
8138         struct tblentry *cmdp;
8139
8140         INT_OFF;
8141         cmdp = *lastcmdentry;
8142         *lastcmdentry = cmdp->next;
8143         if (cmdp->cmdtype == CMDFUNCTION)
8144                 freefunc(cmdp->param.func);
8145         free(cmdp);
8146         INT_ON;
8147 }
8148
8149 /*
8150  * Add a new command entry, replacing any existing command entry for
8151  * the same name - except special builtins.
8152  */
8153 static void
8154 addcmdentry(char *name, struct cmdentry *entry)
8155 {
8156         struct tblentry *cmdp;
8157
8158         cmdp = cmdlookup(name, 1);
8159         if (cmdp->cmdtype == CMDFUNCTION) {
8160                 freefunc(cmdp->param.func);
8161         }
8162         cmdp->cmdtype = entry->cmdtype;
8163         cmdp->param = entry->u;
8164         cmdp->rehash = 0;
8165 }
8166
8167 static int FAST_FUNC
8168 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8169 {
8170         struct tblentry **pp;
8171         struct tblentry *cmdp;
8172         int c;
8173         struct cmdentry entry;
8174         char *name;
8175
8176         if (nextopt("r") != '\0') {
8177                 clearcmdentry(0);
8178                 return 0;
8179         }
8180
8181         if (*argptr == NULL) {
8182                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8183                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8184                                 if (cmdp->cmdtype == CMDNORMAL)
8185                                         printentry(cmdp);
8186                         }
8187                 }
8188                 return 0;
8189         }
8190
8191         c = 0;
8192         while ((name = *argptr) != NULL) {
8193                 cmdp = cmdlookup(name, 0);
8194                 if (cmdp != NULL
8195                  && (cmdp->cmdtype == CMDNORMAL
8196                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8197                 ) {
8198                         delete_cmd_entry();
8199                 }
8200                 find_command(name, &entry, DO_ERR, pathval());
8201                 if (entry.cmdtype == CMDUNKNOWN)
8202                         c = 1;
8203                 argptr++;
8204         }
8205         return c;
8206 }
8207
8208 /*
8209  * Called when a cd is done.  Marks all commands so the next time they
8210  * are executed they will be rehashed.
8211  */
8212 static void
8213 hashcd(void)
8214 {
8215         struct tblentry **pp;
8216         struct tblentry *cmdp;
8217
8218         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8219                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8220                         if (cmdp->cmdtype == CMDNORMAL
8221                          || (cmdp->cmdtype == CMDBUILTIN
8222                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8223                              && builtinloc > 0)
8224                         ) {
8225                                 cmdp->rehash = 1;
8226                         }
8227                 }
8228         }
8229 }
8230
8231 /*
8232  * Fix command hash table when PATH changed.
8233  * Called before PATH is changed.  The argument is the new value of PATH;
8234  * pathval() still returns the old value at this point.
8235  * Called with interrupts off.
8236  */
8237 static void FAST_FUNC
8238 changepath(const char *new)
8239 {
8240         const char *old;
8241         int firstchange;
8242         int idx;
8243         int idx_bltin;
8244
8245         old = pathval();
8246         firstchange = 9999;     /* assume no change */
8247         idx = 0;
8248         idx_bltin = -1;
8249         for (;;) {
8250                 if (*old != *new) {
8251                         firstchange = idx;
8252                         if ((*old == '\0' && *new == ':')
8253                          || (*old == ':' && *new == '\0')
8254                         ) {
8255                                 firstchange++;
8256                         }
8257                         old = new;      /* ignore subsequent differences */
8258                 }
8259                 if (*new == '\0')
8260                         break;
8261                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8262                         idx_bltin = idx;
8263                 if (*new == ':')
8264                         idx++;
8265                 new++;
8266                 old++;
8267         }
8268         if (builtinloc < 0 && idx_bltin >= 0)
8269                 builtinloc = idx_bltin;             /* zap builtins */
8270         if (builtinloc >= 0 && idx_bltin < 0)
8271                 firstchange = 0;
8272         clearcmdentry(firstchange);
8273         builtinloc = idx_bltin;
8274 }
8275 enum {
8276         TEOF,
8277         TNL,
8278         TREDIR,
8279         TWORD,
8280         TSEMI,
8281         TBACKGND,
8282         TAND,
8283         TOR,
8284         TPIPE,
8285         TLP,
8286         TRP,
8287         TENDCASE,
8288         TENDBQUOTE,
8289         TNOT,
8290         TCASE,
8291         TDO,
8292         TDONE,
8293         TELIF,
8294         TELSE,
8295         TESAC,
8296         TFI,
8297         TFOR,
8298 #if BASH_FUNCTION
8299         TFUNCTION,
8300 #endif
8301         TIF,
8302         TIN,
8303         TTHEN,
8304         TUNTIL,
8305         TWHILE,
8306         TBEGIN,
8307         TEND
8308 };
8309 typedef smallint token_id_t;
8310
8311 /* Nth bit indicates if token marks the end of a list */
8312 enum {
8313         tokendlist = 0
8314         /*  0 */ | (1u << TEOF)
8315         /*  1 */ | (0u << TNL)
8316         /*  2 */ | (0u << TREDIR)
8317         /*  3 */ | (0u << TWORD)
8318         /*  4 */ | (0u << TSEMI)
8319         /*  5 */ | (0u << TBACKGND)
8320         /*  6 */ | (0u << TAND)
8321         /*  7 */ | (0u << TOR)
8322         /*  8 */ | (0u << TPIPE)
8323         /*  9 */ | (0u << TLP)
8324         /* 10 */ | (1u << TRP)
8325         /* 11 */ | (1u << TENDCASE)
8326         /* 12 */ | (1u << TENDBQUOTE)
8327         /* 13 */ | (0u << TNOT)
8328         /* 14 */ | (0u << TCASE)
8329         /* 15 */ | (1u << TDO)
8330         /* 16 */ | (1u << TDONE)
8331         /* 17 */ | (1u << TELIF)
8332         /* 18 */ | (1u << TELSE)
8333         /* 19 */ | (1u << TESAC)
8334         /* 20 */ | (1u << TFI)
8335         /* 21 */ | (0u << TFOR)
8336 #if BASH_FUNCTION
8337         /* 22 */ | (0u << TFUNCTION)
8338 #endif
8339         /* 23 */ | (0u << TIF)
8340         /* 24 */ | (0u << TIN)
8341         /* 25 */ | (1u << TTHEN)
8342         /* 26 */ | (0u << TUNTIL)
8343         /* 27 */ | (0u << TWHILE)
8344         /* 28 */ | (0u << TBEGIN)
8345         /* 29 */ | (1u << TEND)
8346         , /* thus far 29 bits used */
8347 };
8348
8349 static const char *const tokname_array[] = {
8350         "end of file",
8351         "newline",
8352         "redirection",
8353         "word",
8354         ";",
8355         "&",
8356         "&&",
8357         "||",
8358         "|",
8359         "(",
8360         ")",
8361         ";;",
8362         "`",
8363 #define KWDOFFSET 13
8364         /* the following are keywords */
8365         "!",
8366         "case",
8367         "do",
8368         "done",
8369         "elif",
8370         "else",
8371         "esac",
8372         "fi",
8373         "for",
8374 #if BASH_FUNCTION
8375         "function",
8376 #endif
8377         "if",
8378         "in",
8379         "then",
8380         "until",
8381         "while",
8382         "{",
8383         "}",
8384 };
8385
8386 /* Wrapper around strcmp for qsort/bsearch/... */
8387 static int
8388 pstrcmp(const void *a, const void *b)
8389 {
8390         return strcmp((char*)a, *(char**)b);
8391 }
8392
8393 static const char *const *
8394 findkwd(const char *s)
8395 {
8396         return bsearch(s, tokname_array + KWDOFFSET,
8397                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8398                         sizeof(tokname_array[0]), pstrcmp);
8399 }
8400
8401 /*
8402  * Locate and print what a word is...
8403  */
8404 static int
8405 describe_command(char *command, const char *path, int describe_command_verbose)
8406 {
8407         struct cmdentry entry;
8408 #if ENABLE_ASH_ALIAS
8409         const struct alias *ap;
8410 #endif
8411
8412         path = path ? path : pathval();
8413
8414         if (describe_command_verbose) {
8415                 out1str(command);
8416         }
8417
8418         /* First look at the keywords */
8419         if (findkwd(command)) {
8420                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8421                 goto out;
8422         }
8423
8424 #if ENABLE_ASH_ALIAS
8425         /* Then look at the aliases */
8426         ap = lookupalias(command, 0);
8427         if (ap != NULL) {
8428                 if (!describe_command_verbose) {
8429                         out1str("alias ");
8430                         printalias(ap);
8431                         return 0;
8432                 }
8433                 out1fmt(" is an alias for %s", ap->val);
8434                 goto out;
8435         }
8436 #endif
8437         /* Brute force */
8438         find_command(command, &entry, DO_ABS, path);
8439
8440         switch (entry.cmdtype) {
8441         case CMDNORMAL: {
8442                 int j = entry.u.index;
8443                 char *p;
8444                 if (j < 0) {
8445                         p = command;
8446                 } else {
8447                         do {
8448                                 p = path_advance(&path, command);
8449                                 stunalloc(p);
8450                         } while (--j >= 0);
8451                 }
8452                 if (describe_command_verbose) {
8453                         out1fmt(" is %s", p);
8454                 } else {
8455                         out1str(p);
8456                 }
8457                 break;
8458         }
8459
8460         case CMDFUNCTION:
8461                 if (describe_command_verbose) {
8462                         out1str(" is a shell function");
8463                 } else {
8464                         out1str(command);
8465                 }
8466                 break;
8467
8468         case CMDBUILTIN:
8469                 if (describe_command_verbose) {
8470                         out1fmt(" is a %sshell builtin",
8471                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8472                                         "special " : nullstr
8473                         );
8474                 } else {
8475                         out1str(command);
8476                 }
8477                 break;
8478
8479         default:
8480                 if (describe_command_verbose) {
8481                         out1str(": not found\n");
8482                 }
8483                 return 127;
8484         }
8485  out:
8486         out1str("\n");
8487         return 0;
8488 }
8489
8490 static int FAST_FUNC
8491 typecmd(int argc UNUSED_PARAM, char **argv)
8492 {
8493         int i = 1;
8494         int err = 0;
8495         int verbose = 1;
8496
8497         /* type -p ... ? (we don't bother checking for 'p') */
8498         if (argv[1] && argv[1][0] == '-') {
8499                 i++;
8500                 verbose = 0;
8501         }
8502         while (argv[i]) {
8503                 err |= describe_command(argv[i++], NULL, verbose);
8504         }
8505         return err;
8506 }
8507
8508 #if ENABLE_ASH_CMDCMD
8509 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8510 static char **
8511 parse_command_args(char **argv, const char **path)
8512 {
8513         char *cp, c;
8514
8515         for (;;) {
8516                 cp = *++argv;
8517                 if (!cp)
8518                         return NULL;
8519                 if (*cp++ != '-')
8520                         break;
8521                 c = *cp++;
8522                 if (!c)
8523                         break;
8524                 if (c == '-' && !*cp) {
8525                         if (!*++argv)
8526                                 return NULL;
8527                         break;
8528                 }
8529                 do {
8530                         switch (c) {
8531                         case 'p':
8532                                 *path = bb_default_path;
8533                                 break;
8534                         default:
8535                                 /* run 'typecmd' for other options */
8536                                 return NULL;
8537                         }
8538                         c = *cp++;
8539                 } while (c);
8540         }
8541         return argv;
8542 }
8543
8544 static int FAST_FUNC
8545 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8546 {
8547         char *cmd;
8548         int c;
8549         enum {
8550                 VERIFY_BRIEF = 1,
8551                 VERIFY_VERBOSE = 2,
8552         } verify = 0;
8553         const char *path = NULL;
8554
8555         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8556          * never reaches this function.
8557          */
8558
8559         while ((c = nextopt("pvV")) != '\0')
8560                 if (c == 'V')
8561                         verify |= VERIFY_VERBOSE;
8562                 else if (c == 'v')
8563                         /*verify |= VERIFY_BRIEF*/;
8564 #if DEBUG
8565                 else if (c != 'p')
8566                         abort();
8567 #endif
8568                 else
8569                         path = bb_default_path;
8570
8571         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8572         cmd = *argptr;
8573         if (/*verify && */ cmd)
8574                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8575
8576         return 0;
8577 }
8578 #endif
8579
8580
8581 /*static int funcblocksize;     // size of structures in function */
8582 /*static int funcstringsize;    // size of strings in node */
8583 static void *funcblock;         /* block to allocate function from */
8584 static char *funcstring_end;    /* end of block to allocate strings from */
8585
8586 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8587         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8588         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8589         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8590         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8591         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8592         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8593         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8594         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8595         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8596         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8597         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8598         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8599         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8600         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8601         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8602         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8603         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8604 #if BASH_REDIR_OUTPUT
8605         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8606 #endif
8607         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8608         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8609         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8610         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8611         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8612         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8613         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8614         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8615         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8616 };
8617
8618 static int calcsize(int funcblocksize, union node *n);
8619
8620 static int
8621 sizenodelist(int funcblocksize, struct nodelist *lp)
8622 {
8623         while (lp) {
8624                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8625                 funcblocksize = calcsize(funcblocksize, lp->n);
8626                 lp = lp->next;
8627         }
8628         return funcblocksize;
8629 }
8630
8631 static int
8632 calcsize(int funcblocksize, union node *n)
8633 {
8634         if (n == NULL)
8635                 return funcblocksize;
8636         funcblocksize += nodesize[n->type];
8637         switch (n->type) {
8638         case NCMD:
8639                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8640                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8641                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8642                 break;
8643         case NPIPE:
8644                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8645                 break;
8646         case NREDIR:
8647         case NBACKGND:
8648         case NSUBSHELL:
8649                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8650                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8651                 break;
8652         case NAND:
8653         case NOR:
8654         case NSEMI:
8655         case NWHILE:
8656         case NUNTIL:
8657                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8658                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8659                 break;
8660         case NIF:
8661                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8662                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8663                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8664                 break;
8665         case NFOR:
8666                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8667                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8668                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8669                 break;
8670         case NCASE:
8671                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8672                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8673                 break;
8674         case NCLIST:
8675                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8676                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8677                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8678                 break;
8679         case NDEFUN:
8680                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8681                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8682                 break;
8683         case NARG:
8684                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8685                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8686                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8687                 break;
8688         case NTO:
8689 #if BASH_REDIR_OUTPUT
8690         case NTO2:
8691 #endif
8692         case NCLOBBER:
8693         case NFROM:
8694         case NFROMTO:
8695         case NAPPEND:
8696                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8697                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8698                 break;
8699         case NTOFD:
8700         case NFROMFD:
8701                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8702                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8703         break;
8704         case NHERE:
8705         case NXHERE:
8706                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8707                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8708                 break;
8709         case NNOT:
8710                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8711                 break;
8712         };
8713         return funcblocksize;
8714 }
8715
8716 static char *
8717 nodeckstrdup(char *s)
8718 {
8719         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8720         return strcpy(funcstring_end, s);
8721 }
8722
8723 static union node *copynode(union node *);
8724
8725 static struct nodelist *
8726 copynodelist(struct nodelist *lp)
8727 {
8728         struct nodelist *start;
8729         struct nodelist **lpp;
8730
8731         lpp = &start;
8732         while (lp) {
8733                 *lpp = funcblock;
8734                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8735                 (*lpp)->n = copynode(lp->n);
8736                 lp = lp->next;
8737                 lpp = &(*lpp)->next;
8738         }
8739         *lpp = NULL;
8740         return start;
8741 }
8742
8743 static union node *
8744 copynode(union node *n)
8745 {
8746         union node *new;
8747
8748         if (n == NULL)
8749                 return NULL;
8750         new = funcblock;
8751         funcblock = (char *) funcblock + nodesize[n->type];
8752
8753         switch (n->type) {
8754         case NCMD:
8755                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8756                 new->ncmd.args = copynode(n->ncmd.args);
8757                 new->ncmd.assign = copynode(n->ncmd.assign);
8758                 new->ncmd.linno = n->ncmd.linno;
8759                 break;
8760         case NPIPE:
8761                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8762                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8763                 break;
8764         case NREDIR:
8765         case NBACKGND:
8766         case NSUBSHELL:
8767                 new->nredir.redirect = copynode(n->nredir.redirect);
8768                 new->nredir.n = copynode(n->nredir.n);
8769                 new->nredir.linno = n->nredir.linno;
8770                 break;
8771         case NAND:
8772         case NOR:
8773         case NSEMI:
8774         case NWHILE:
8775         case NUNTIL:
8776                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8777                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8778                 break;
8779         case NIF:
8780                 new->nif.elsepart = copynode(n->nif.elsepart);
8781                 new->nif.ifpart = copynode(n->nif.ifpart);
8782                 new->nif.test = copynode(n->nif.test);
8783                 break;
8784         case NFOR:
8785                 new->nfor.var = nodeckstrdup(n->nfor.var);
8786                 new->nfor.body = copynode(n->nfor.body);
8787                 new->nfor.args = copynode(n->nfor.args);
8788                 new->nfor.linno = n->nfor.linno;
8789                 break;
8790         case NCASE:
8791                 new->ncase.cases = copynode(n->ncase.cases);
8792                 new->ncase.expr = copynode(n->ncase.expr);
8793                 new->ncase.linno = n->ncase.linno;
8794                 break;
8795         case NCLIST:
8796                 new->nclist.body = copynode(n->nclist.body);
8797                 new->nclist.pattern = copynode(n->nclist.pattern);
8798                 new->nclist.next = copynode(n->nclist.next);
8799                 break;
8800         case NDEFUN:
8801                 new->ndefun.body = copynode(n->ndefun.body);
8802                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8803                 new->ndefun.linno = n->ndefun.linno;
8804                 break;
8805         case NARG:
8806                 new->narg.backquote = copynodelist(n->narg.backquote);
8807                 new->narg.text = nodeckstrdup(n->narg.text);
8808                 new->narg.next = copynode(n->narg.next);
8809                 break;
8810         case NTO:
8811 #if BASH_REDIR_OUTPUT
8812         case NTO2:
8813 #endif
8814         case NCLOBBER:
8815         case NFROM:
8816         case NFROMTO:
8817         case NAPPEND:
8818                 new->nfile.fname = copynode(n->nfile.fname);
8819                 new->nfile.fd = n->nfile.fd;
8820                 new->nfile.next = copynode(n->nfile.next);
8821                 break;
8822         case NTOFD:
8823         case NFROMFD:
8824                 new->ndup.vname = copynode(n->ndup.vname);
8825                 new->ndup.dupfd = n->ndup.dupfd;
8826                 new->ndup.fd = n->ndup.fd;
8827                 new->ndup.next = copynode(n->ndup.next);
8828                 break;
8829         case NHERE:
8830         case NXHERE:
8831                 new->nhere.doc = copynode(n->nhere.doc);
8832                 new->nhere.fd = n->nhere.fd;
8833                 new->nhere.next = copynode(n->nhere.next);
8834                 break;
8835         case NNOT:
8836                 new->nnot.com = copynode(n->nnot.com);
8837                 break;
8838         };
8839         new->type = n->type;
8840         return new;
8841 }
8842
8843 /*
8844  * Make a copy of a parse tree.
8845  */
8846 static struct funcnode *
8847 copyfunc(union node *n)
8848 {
8849         struct funcnode *f;
8850         size_t blocksize;
8851
8852         /*funcstringsize = 0;*/
8853         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8854         f = ckzalloc(blocksize /* + funcstringsize */);
8855         funcblock = (char *) f + offsetof(struct funcnode, n);
8856         funcstring_end = (char *) f + blocksize;
8857         copynode(n);
8858         /* f->count = 0; - ckzalloc did it */
8859         return f;
8860 }
8861
8862 /*
8863  * Define a shell function.
8864  */
8865 static void
8866 defun(union node *func)
8867 {
8868         struct cmdentry entry;
8869
8870         INT_OFF;
8871         entry.cmdtype = CMDFUNCTION;
8872         entry.u.func = copyfunc(func);
8873         addcmdentry(func->ndefun.text, &entry);
8874         INT_ON;
8875 }
8876
8877 /* Reasons for skipping commands (see comment on breakcmd routine) */
8878 #define SKIPBREAK      (1 << 0)
8879 #define SKIPCONT       (1 << 1)
8880 #define SKIPFUNC       (1 << 2)
8881 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8882 static int skipcount;           /* number of levels to skip */
8883 static int loopnest;            /* current loop nesting level */
8884 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8885
8886 /* Forward decl way out to parsing code - dotrap needs it */
8887 static int evalstring(char *s, int flags);
8888
8889 /* Called to execute a trap.
8890  * Single callsite - at the end of evaltree().
8891  * If we return non-zero, evaltree raises EXEXIT exception.
8892  *
8893  * Perhaps we should avoid entering new trap handlers
8894  * while we are executing a trap handler. [is it a TODO?]
8895  */
8896 static void
8897 dotrap(void)
8898 {
8899         uint8_t *g;
8900         int sig;
8901         uint8_t last_status;
8902
8903         if (!pending_sig)
8904                 return;
8905
8906         last_status = exitstatus;
8907         pending_sig = 0;
8908         barrier();
8909
8910         TRACE(("dotrap entered\n"));
8911         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8912                 char *p;
8913
8914                 if (!*g)
8915                         continue;
8916
8917                 if (evalskip) {
8918                         pending_sig = sig;
8919                         break;
8920                 }
8921
8922                 p = trap[sig];
8923                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8924                  * don't upset it by resetting gotsig[SIGINT-1] */
8925                 if (sig == SIGINT && !p)
8926                         continue;
8927
8928                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8929                 *g = 0;
8930                 if (!p)
8931                         continue;
8932                 evalstring(p, 0);
8933         }
8934         exitstatus = last_status;
8935         TRACE(("dotrap returns\n"));
8936 }
8937
8938 /* forward declarations - evaluation is fairly recursive business... */
8939 static int evalloop(union node *, int);
8940 static int evalfor(union node *, int);
8941 static int evalcase(union node *, int);
8942 static int evalsubshell(union node *, int);
8943 static void expredir(union node *);
8944 static int evalpipe(union node *, int);
8945 static int evalcommand(union node *, int);
8946 static int evalbltin(const struct builtincmd *, int, char **, int);
8947 static void prehash(union node *);
8948
8949 /*
8950  * Evaluate a parse tree.  The value is left in the global variable
8951  * exitstatus.
8952  */
8953 static int
8954 evaltree(union node *n, int flags)
8955 {
8956         int checkexit = 0;
8957         int (*evalfn)(union node *, int);
8958         int status = 0;
8959
8960         if (n == NULL) {
8961                 TRACE(("evaltree(NULL) called\n"));
8962                 goto out;
8963         }
8964         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8965
8966         dotrap();
8967
8968         switch (n->type) {
8969         default:
8970 #if DEBUG
8971                 out1fmt("Node type = %d\n", n->type);
8972                 fflush_all();
8973                 break;
8974 #endif
8975         case NNOT:
8976                 status = !evaltree(n->nnot.com, EV_TESTED);
8977                 goto setstatus;
8978         case NREDIR:
8979                 errlinno = lineno = n->nredir.linno;
8980                 if (funcline)
8981                         lineno -= funcline - 1;
8982                 expredir(n->nredir.redirect);
8983                 pushredir(n->nredir.redirect);
8984                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8985                 if (!status) {
8986                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8987                 }
8988                 if (n->nredir.redirect)
8989                         popredir(/*drop:*/ 0);
8990                 goto setstatus;
8991         case NCMD:
8992                 evalfn = evalcommand;
8993  checkexit:
8994                 if (eflag && !(flags & EV_TESTED))
8995                         checkexit = ~0;
8996                 goto calleval;
8997         case NFOR:
8998                 evalfn = evalfor;
8999                 goto calleval;
9000         case NWHILE:
9001         case NUNTIL:
9002                 evalfn = evalloop;
9003                 goto calleval;
9004         case NSUBSHELL:
9005         case NBACKGND:
9006                 evalfn = evalsubshell;
9007                 goto checkexit;
9008         case NPIPE:
9009                 evalfn = evalpipe;
9010                 goto checkexit;
9011         case NCASE:
9012                 evalfn = evalcase;
9013                 goto calleval;
9014         case NAND:
9015         case NOR:
9016         case NSEMI: {
9017
9018 #if NAND + 1 != NOR
9019 #error NAND + 1 != NOR
9020 #endif
9021 #if NOR + 1 != NSEMI
9022 #error NOR + 1 != NSEMI
9023 #endif
9024                 unsigned is_or = n->type - NAND;
9025                 status = evaltree(
9026                         n->nbinary.ch1,
9027                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9028                 );
9029                 if ((!status) == is_or || evalskip)
9030                         break;
9031                 n = n->nbinary.ch2;
9032  evaln:
9033                 evalfn = evaltree;
9034  calleval:
9035                 status = evalfn(n, flags);
9036                 goto setstatus;
9037         }
9038         case NIF:
9039                 status = evaltree(n->nif.test, EV_TESTED);
9040                 if (evalskip)
9041                         break;
9042                 if (!status) {
9043                         n = n->nif.ifpart;
9044                         goto evaln;
9045                 }
9046                 if (n->nif.elsepart) {
9047                         n = n->nif.elsepart;
9048                         goto evaln;
9049                 }
9050                 status = 0;
9051                 goto setstatus;
9052         case NDEFUN:
9053                 defun(n);
9054                 /* Not necessary. To test it:
9055                  * "false; f() { qwerty; }; echo $?" should print 0.
9056                  */
9057                 /* status = 0; */
9058  setstatus:
9059                 exitstatus = status;
9060                 break;
9061         }
9062  out:
9063         /* Order of checks below is important:
9064          * signal handlers trigger before exit caused by "set -e".
9065          */
9066         dotrap();
9067
9068         if (checkexit & status)
9069                 raise_exception(EXEXIT);
9070         if (flags & EV_EXIT)
9071                 raise_exception(EXEXIT);
9072
9073         TRACE(("leaving evaltree (no interrupts)\n"));
9074         return exitstatus;
9075 }
9076
9077 static int
9078 skiploop(void)
9079 {
9080         int skip = evalskip;
9081
9082         switch (skip) {
9083         case 0:
9084                 break;
9085         case SKIPBREAK:
9086         case SKIPCONT:
9087                 if (--skipcount <= 0) {
9088                         evalskip = 0;
9089                         break;
9090                 }
9091                 skip = SKIPBREAK;
9092                 break;
9093         }
9094         return skip;
9095 }
9096
9097 static int
9098 evalloop(union node *n, int flags)
9099 {
9100         int skip;
9101         int status;
9102
9103         loopnest++;
9104         status = 0;
9105         flags &= EV_TESTED;
9106         do {
9107                 int i;
9108
9109                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9110                 skip = skiploop();
9111                 if (skip == SKIPFUNC)
9112                         status = i;
9113                 if (skip)
9114                         continue;
9115                 if (n->type != NWHILE)
9116                         i = !i;
9117                 if (i != 0)
9118                         break;
9119                 status = evaltree(n->nbinary.ch2, flags);
9120                 skip = skiploop();
9121         } while (!(skip & ~SKIPCONT));
9122         loopnest--;
9123
9124         return status;
9125 }
9126
9127 static int
9128 evalfor(union node *n, int flags)
9129 {
9130         struct arglist arglist;
9131         union node *argp;
9132         struct strlist *sp;
9133         struct stackmark smark;
9134         int status = 0;
9135
9136         errlinno = lineno = n->ncase.linno;
9137         if (funcline)
9138                 lineno -= funcline - 1;
9139
9140         setstackmark(&smark);
9141         arglist.list = NULL;
9142         arglist.lastp = &arglist.list;
9143         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9144                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9145         }
9146         *arglist.lastp = NULL;
9147
9148         loopnest++;
9149         flags &= EV_TESTED;
9150         for (sp = arglist.list; sp; sp = sp->next) {
9151                 setvar0(n->nfor.var, sp->text);
9152                 status = evaltree(n->nfor.body, flags);
9153                 if (skiploop() & ~SKIPCONT)
9154                         break;
9155         }
9156         loopnest--;
9157         popstackmark(&smark);
9158
9159         return status;
9160 }
9161
9162 static int
9163 evalcase(union node *n, int flags)
9164 {
9165         union node *cp;
9166         union node *patp;
9167         struct arglist arglist;
9168         struct stackmark smark;
9169         int status = 0;
9170
9171         errlinno = lineno = n->ncase.linno;
9172         if (funcline)
9173                 lineno -= funcline - 1;
9174
9175         setstackmark(&smark);
9176         arglist.list = NULL;
9177         arglist.lastp = &arglist.list;
9178         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9179         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9180                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9181                         if (casematch(patp, arglist.list->text)) {
9182                                 /* Ensure body is non-empty as otherwise
9183                                  * EV_EXIT may prevent us from setting the
9184                                  * exit status.
9185                                  */
9186                                 if (evalskip == 0 && cp->nclist.body) {
9187                                         status = evaltree(cp->nclist.body, flags);
9188                                 }
9189                                 goto out;
9190                         }
9191                 }
9192         }
9193  out:
9194         popstackmark(&smark);
9195
9196         return status;
9197 }
9198
9199 /*
9200  * Kick off a subshell to evaluate a tree.
9201  */
9202 static int
9203 evalsubshell(union node *n, int flags)
9204 {
9205         struct job *jp;
9206         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9207         int status;
9208
9209         errlinno = lineno = n->nredir.linno;
9210         if (funcline)
9211                 lineno -= funcline - 1;
9212
9213         expredir(n->nredir.redirect);
9214         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9215                 goto nofork;
9216         INT_OFF;
9217         if (backgnd == FORK_FG)
9218                 get_tty_state();
9219         jp = makejob(/*n,*/ 1);
9220         if (forkshell(jp, n, backgnd) == 0) {
9221                 /* child */
9222                 INT_ON;
9223                 flags |= EV_EXIT;
9224                 if (backgnd)
9225                         flags &= ~EV_TESTED;
9226  nofork:
9227                 redirect(n->nredir.redirect, 0);
9228                 evaltreenr(n->nredir.n, flags);
9229                 /* never returns */
9230         }
9231         /* parent */
9232         status = 0;
9233         if (backgnd == FORK_FG)
9234                 status = waitforjob(jp);
9235         INT_ON;
9236         return status;
9237 }
9238
9239 /*
9240  * Compute the names of the files in a redirection list.
9241  */
9242 static void fixredir(union node *, const char *, int);
9243 static void
9244 expredir(union node *n)
9245 {
9246         union node *redir;
9247
9248         for (redir = n; redir; redir = redir->nfile.next) {
9249                 struct arglist fn;
9250
9251                 fn.list = NULL;
9252                 fn.lastp = &fn.list;
9253                 switch (redir->type) {
9254                 case NFROMTO:
9255                 case NFROM:
9256                 case NTO:
9257 #if BASH_REDIR_OUTPUT
9258                 case NTO2:
9259 #endif
9260                 case NCLOBBER:
9261                 case NAPPEND:
9262                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9263                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9264 #if BASH_REDIR_OUTPUT
9265  store_expfname:
9266 #endif
9267 #if 0
9268 // By the design of stack allocator, the loop of this kind:
9269 //      while true; do while true; do break; done </dev/null; done
9270 // will look like a memory leak: ash plans to free expfname's
9271 // of "/dev/null" as soon as it finishes running the loop
9272 // (in this case, never).
9273 // This "fix" is wrong:
9274                         if (redir->nfile.expfname)
9275                                 stunalloc(redir->nfile.expfname);
9276 // It results in corrupted state of stacked allocations.
9277 #endif
9278                         redir->nfile.expfname = fn.list->text;
9279                         break;
9280                 case NFROMFD:
9281                 case NTOFD: /* >& */
9282                         if (redir->ndup.vname) {
9283                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9284                                 if (fn.list == NULL)
9285                                         ash_msg_and_raise_error("redir error");
9286 #if BASH_REDIR_OUTPUT
9287 //FIXME: we used expandarg with different args!
9288                                 if (!isdigit_str9(fn.list->text)) {
9289                                         /* >&file, not >&fd */
9290                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9291                                                 ash_msg_and_raise_error("redir error");
9292                                         redir->type = NTO2;
9293                                         goto store_expfname;
9294                                 }
9295 #endif
9296                                 fixredir(redir, fn.list->text, 1);
9297                         }
9298                         break;
9299                 }
9300         }
9301 }
9302
9303 /*
9304  * Evaluate a pipeline.  All the processes in the pipeline are children
9305  * of the process creating the pipeline.  (This differs from some versions
9306  * of the shell, which make the last process in a pipeline the parent
9307  * of all the rest.)
9308  */
9309 static int
9310 evalpipe(union node *n, int flags)
9311 {
9312         struct job *jp;
9313         struct nodelist *lp;
9314         int pipelen;
9315         int prevfd;
9316         int pip[2];
9317         int status = 0;
9318
9319         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9320         pipelen = 0;
9321         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9322                 pipelen++;
9323         flags |= EV_EXIT;
9324         INT_OFF;
9325         if (n->npipe.pipe_backgnd == 0)
9326                 get_tty_state();
9327         jp = makejob(/*n,*/ pipelen);
9328         prevfd = -1;
9329         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9330                 prehash(lp->n);
9331                 pip[1] = -1;
9332                 if (lp->next) {
9333                         if (pipe(pip) < 0) {
9334                                 close(prevfd);
9335                                 ash_msg_and_raise_perror("can't create pipe");
9336                         }
9337                 }
9338                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9339                         /* child */
9340                         INT_ON;
9341                         if (pip[1] >= 0) {
9342                                 close(pip[0]);
9343                         }
9344                         if (prevfd > 0) {
9345                                 dup2(prevfd, 0);
9346                                 close(prevfd);
9347                         }
9348                         if (pip[1] > 1) {
9349                                 dup2(pip[1], 1);
9350                                 close(pip[1]);
9351                         }
9352                         evaltreenr(lp->n, flags);
9353                         /* never returns */
9354                 }
9355                 /* parent */
9356                 if (prevfd >= 0)
9357                         close(prevfd);
9358                 prevfd = pip[0];
9359                 /* Don't want to trigger debugging */
9360                 if (pip[1] != -1)
9361                         close(pip[1]);
9362         }
9363         if (n->npipe.pipe_backgnd == 0) {
9364                 status = waitforjob(jp);
9365                 TRACE(("evalpipe:  job done exit status %d\n", status));
9366         }
9367         INT_ON;
9368
9369         return status;
9370 }
9371
9372 /*
9373  * Controls whether the shell is interactive or not.
9374  */
9375 static void
9376 setinteractive(int on)
9377 {
9378         static smallint is_interactive;
9379
9380         if (++on == is_interactive)
9381                 return;
9382         is_interactive = on;
9383         setsignal(SIGINT);
9384         setsignal(SIGQUIT);
9385         setsignal(SIGTERM);
9386 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9387         if (is_interactive > 1) {
9388                 /* Looks like they want an interactive shell */
9389                 static smallint did_banner;
9390
9391                 if (!did_banner) {
9392                         /* note: ash and hush share this string */
9393                         out1fmt("\n\n%s %s\n"
9394                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9395                                 "\n",
9396                                 bb_banner,
9397                                 "built-in shell (ash)"
9398                         );
9399                         did_banner = 1;
9400                 }
9401         }
9402 #endif
9403 }
9404
9405 static void
9406 optschanged(void)
9407 {
9408 #if DEBUG
9409         opentrace();
9410 #endif
9411         setinteractive(iflag);
9412         setjobctl(mflag);
9413 #if ENABLE_FEATURE_EDITING_VI
9414         if (viflag)
9415                 line_input_state->flags |= VI_MODE;
9416         else
9417                 line_input_state->flags &= ~VI_MODE;
9418 #else
9419         viflag = 0; /* forcibly keep the option off */
9420 #endif
9421 }
9422
9423 struct localvar_list {
9424         struct localvar_list *next;
9425         struct localvar *lv;
9426 };
9427
9428 static struct localvar_list *localvar_stack;
9429
9430 /*
9431  * Called after a function returns.
9432  * Interrupts must be off.
9433  */
9434 static void
9435 poplocalvars(int keep)
9436 {
9437         struct localvar_list *ll;
9438         struct localvar *lvp, *next;
9439         struct var *vp;
9440
9441         INT_OFF;
9442         ll = localvar_stack;
9443         localvar_stack = ll->next;
9444
9445         next = ll->lv;
9446         free(ll);
9447
9448         while ((lvp = next) != NULL) {
9449                 next = lvp->next;
9450                 vp = lvp->vp;
9451                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9452                 if (keep) {
9453                         int bits = VSTRFIXED;
9454
9455                         if (lvp->flags != VUNSET) {
9456                                 if (vp->var_text == lvp->text)
9457                                         bits |= VTEXTFIXED;
9458                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9459                                         free((char*)lvp->text);
9460                         }
9461
9462                         vp->flags &= ~bits;
9463                         vp->flags |= (lvp->flags & bits);
9464
9465                         if ((vp->flags &
9466                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9467                                 unsetvar(vp->var_text);
9468                 } else if (vp == NULL) {        /* $- saved */
9469                         memcpy(optlist, lvp->text, sizeof(optlist));
9470                         free((char*)lvp->text);
9471                         optschanged();
9472                 } else if (lvp->flags == VUNSET) {
9473                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9474                         unsetvar(vp->var_text);
9475                 } else {
9476                         if (vp->var_func)
9477                                 vp->var_func(var_end(lvp->text));
9478                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9479                                 free((char*)vp->var_text);
9480                         vp->flags = lvp->flags;
9481                         vp->var_text = lvp->text;
9482                 }
9483                 free(lvp);
9484         }
9485         INT_ON;
9486 }
9487
9488 /*
9489  * Create a new localvar environment.
9490  */
9491 static struct localvar_list *
9492 pushlocalvars(void)
9493 {
9494         struct localvar_list *ll;
9495
9496         INT_OFF;
9497         ll = ckzalloc(sizeof(*ll));
9498         /*ll->lv = NULL; - zalloc did it */
9499         ll->next = localvar_stack;
9500         localvar_stack = ll;
9501         INT_ON;
9502
9503         return ll->next;
9504 }
9505
9506 static void
9507 unwindlocalvars(struct localvar_list *stop)
9508 {
9509         while (localvar_stack != stop)
9510                 poplocalvars(0);
9511 }
9512
9513 static int
9514 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9515 {
9516         volatile struct shparam saveparam;
9517         struct jmploc *volatile savehandler;
9518         struct jmploc jmploc;
9519         int e;
9520         int savefuncline;
9521
9522         saveparam = shellparam;
9523         savefuncline = funcline;
9524         savehandler = exception_handler;
9525         e = setjmp(jmploc.loc);
9526         if (e) {
9527                 goto funcdone;
9528         }
9529         INT_OFF;
9530         exception_handler = &jmploc;
9531         shellparam.malloced = 0;
9532         func->count++;
9533         funcline = func->n.ndefun.linno;
9534         INT_ON;
9535         shellparam.nparam = argc - 1;
9536         shellparam.p = argv + 1;
9537 #if ENABLE_ASH_GETOPTS
9538         shellparam.optind = 1;
9539         shellparam.optoff = -1;
9540 #endif
9541         pushlocalvars();
9542         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9543         poplocalvars(0);
9544  funcdone:
9545         INT_OFF;
9546         funcline = savefuncline;
9547         freefunc(func);
9548         freeparam(&shellparam);
9549         shellparam = saveparam;
9550         exception_handler = savehandler;
9551         INT_ON;
9552         evalskip &= ~SKIPFUNC;
9553         return e;
9554 }
9555
9556 /*
9557  * Make a variable a local variable.  When a variable is made local, it's
9558  * value and flags are saved in a localvar structure.  The saved values
9559  * will be restored when the shell function returns.  We handle the name
9560  * "-" as a special case: it makes changes to "set +-options" local
9561  * (options will be restored on return from the function).
9562  */
9563 static void
9564 mklocal(char *name)
9565 {
9566         struct localvar *lvp;
9567         struct var **vpp;
9568         struct var *vp;
9569         char *eq = strchr(name, '=');
9570
9571         INT_OFF;
9572         /* Cater for duplicate "local". Examples:
9573          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9574          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9575          */
9576         lvp = localvar_stack->lv;
9577         while (lvp) {
9578                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9579                         if (eq)
9580                                 setvareq(name, 0);
9581                         /* else:
9582                          * it's a duplicate "local VAR" declaration, do nothing
9583                          */
9584                         goto ret;
9585                 }
9586                 lvp = lvp->next;
9587         }
9588
9589         lvp = ckzalloc(sizeof(*lvp));
9590         if (LONE_DASH(name)) {
9591                 char *p;
9592                 p = ckmalloc(sizeof(optlist));
9593                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9594                 vp = NULL;
9595         } else {
9596                 vpp = hashvar(name);
9597                 vp = *findvar(vpp, name);
9598                 if (vp == NULL) {
9599                         /* variable did not exist yet */
9600                         if (eq)
9601                                 vp = setvareq(name, VSTRFIXED);
9602                         else
9603                                 vp = setvar(name, NULL, VSTRFIXED);
9604                         lvp->flags = VUNSET;
9605                 } else {
9606                         lvp->text = vp->var_text;
9607                         lvp->flags = vp->flags;
9608                         /* make sure neither "struct var" nor string gets freed
9609                          * during (un)setting:
9610                          */
9611                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9612                         if (eq)
9613                                 setvareq(name, 0);
9614                         else
9615                                 /* "local VAR" unsets VAR: */
9616                                 setvar0(name, NULL);
9617                 }
9618         }
9619         lvp->vp = vp;
9620         lvp->next = localvar_stack->lv;
9621         localvar_stack->lv = lvp;
9622  ret:
9623         INT_ON;
9624 }
9625
9626 /*
9627  * The "local" command.
9628  */
9629 static int FAST_FUNC
9630 localcmd(int argc UNUSED_PARAM, char **argv)
9631 {
9632         char *name;
9633
9634         if (!localvar_stack)
9635                 ash_msg_and_raise_error("not in a function");
9636
9637         argv = argptr;
9638         while ((name = *argv++) != NULL) {
9639                 mklocal(name);
9640         }
9641         return 0;
9642 }
9643
9644 static int FAST_FUNC
9645 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9646 {
9647         return 1;
9648 }
9649
9650 static int FAST_FUNC
9651 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9652 {
9653         return 0;
9654 }
9655
9656 static int FAST_FUNC
9657 execcmd(int argc UNUSED_PARAM, char **argv)
9658 {
9659         optionarg = NULL;
9660         while (nextopt("a:") != '\0')
9661                 /* nextopt() sets optionarg to "-a ARGV0" */;
9662
9663         argv = argptr;
9664         if (argv[0]) {
9665                 char *prog;
9666
9667                 iflag = 0;              /* exit on error */
9668                 mflag = 0;
9669                 optschanged();
9670                 /* We should set up signals for "exec CMD"
9671                  * the same way as for "CMD" without "exec".
9672                  * But optschanged->setinteractive->setsignal
9673                  * still thought we are a root shell. Therefore, for example,
9674                  * SIGQUIT is still set to IGN. Fix it:
9675                  */
9676                 shlvl++;
9677                 setsignal(SIGQUIT);
9678                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9679                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9680                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9681
9682                 prog = argv[0];
9683                 if (optionarg)
9684                         argv[0] = optionarg;
9685                 shellexec(prog, argv, pathval(), 0);
9686                 /* NOTREACHED */
9687         }
9688         return 0;
9689 }
9690
9691 /*
9692  * The return command.
9693  */
9694 static int FAST_FUNC
9695 returncmd(int argc UNUSED_PARAM, char **argv)
9696 {
9697         /*
9698          * If called outside a function, do what ksh does;
9699          * skip the rest of the file.
9700          */
9701         evalskip = SKIPFUNC;
9702         return argv[1] ? number(argv[1]) : exitstatus;
9703 }
9704
9705 /* Forward declarations for builtintab[] */
9706 static int breakcmd(int, char **) FAST_FUNC;
9707 static int dotcmd(int, char **) FAST_FUNC;
9708 static int evalcmd(int, char **, int) FAST_FUNC;
9709 static int exitcmd(int, char **) FAST_FUNC;
9710 static int exportcmd(int, char **) FAST_FUNC;
9711 #if ENABLE_ASH_GETOPTS
9712 static int getoptscmd(int, char **) FAST_FUNC;
9713 #endif
9714 #if ENABLE_ASH_HELP
9715 static int helpcmd(int, char **) FAST_FUNC;
9716 #endif
9717 #if MAX_HISTORY
9718 static int historycmd(int, char **) FAST_FUNC;
9719 #endif
9720 #if ENABLE_FEATURE_SH_MATH
9721 static int letcmd(int, char **) FAST_FUNC;
9722 #endif
9723 static int readcmd(int, char **) FAST_FUNC;
9724 static int setcmd(int, char **) FAST_FUNC;
9725 static int shiftcmd(int, char **) FAST_FUNC;
9726 static int timescmd(int, char **) FAST_FUNC;
9727 static int trapcmd(int, char **) FAST_FUNC;
9728 static int umaskcmd(int, char **) FAST_FUNC;
9729 static int unsetcmd(int, char **) FAST_FUNC;
9730 static int ulimitcmd(int, char **) FAST_FUNC;
9731
9732 #define BUILTIN_NOSPEC          "0"
9733 #define BUILTIN_SPECIAL         "1"
9734 #define BUILTIN_REGULAR         "2"
9735 #define BUILTIN_SPEC_REG        "3"
9736 #define BUILTIN_ASSIGN          "4"
9737 #define BUILTIN_SPEC_ASSG       "5"
9738 #define BUILTIN_REG_ASSG        "6"
9739 #define BUILTIN_SPEC_REG_ASSG   "7"
9740
9741 /* Stubs for calling non-FAST_FUNC's */
9742 #if ENABLE_ASH_ECHO
9743 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9744 #endif
9745 #if ENABLE_ASH_PRINTF
9746 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9747 #endif
9748 #if ENABLE_ASH_TEST || BASH_TEST2
9749 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9750 #endif
9751
9752 /* Keep these in proper order since it is searched via bsearch() */
9753 static const struct builtincmd builtintab[] = {
9754         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9755         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9756 #if ENABLE_ASH_TEST
9757         { BUILTIN_REGULAR       "["       , testcmd    },
9758 #endif
9759 #if BASH_TEST2
9760         { BUILTIN_REGULAR       "[["      , testcmd    },
9761 #endif
9762 #if ENABLE_ASH_ALIAS
9763         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9764 #endif
9765 #if JOBS
9766         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9767 #endif
9768         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9769         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9770         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9771 #if ENABLE_ASH_CMDCMD
9772         { BUILTIN_REGULAR       "command" , commandcmd },
9773 #endif
9774         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9775 #if ENABLE_ASH_ECHO
9776         { BUILTIN_REGULAR       "echo"    , echocmd    },
9777 #endif
9778         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9779         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9780         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9781         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9782         { BUILTIN_REGULAR       "false"   , falsecmd   },
9783 #if JOBS
9784         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9785 #endif
9786 #if ENABLE_ASH_GETOPTS
9787         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9788 #endif
9789         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9790 #if ENABLE_ASH_HELP
9791         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9792 #endif
9793 #if MAX_HISTORY
9794         { BUILTIN_NOSPEC        "history" , historycmd },
9795 #endif
9796 #if JOBS
9797         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9798         { BUILTIN_REGULAR       "kill"    , killcmd    },
9799 #endif
9800 #if ENABLE_FEATURE_SH_MATH
9801         { BUILTIN_NOSPEC        "let"     , letcmd     },
9802 #endif
9803         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9804 #if ENABLE_ASH_PRINTF
9805         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9806 #endif
9807         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9808         { BUILTIN_REGULAR       "read"    , readcmd    },
9809         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9810         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9811         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9812         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9813 #if BASH_SOURCE
9814         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9815 #endif
9816 #if ENABLE_ASH_TEST
9817         { BUILTIN_REGULAR       "test"    , testcmd    },
9818 #endif
9819         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9820         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9821         { BUILTIN_REGULAR       "true"    , truecmd    },
9822         { BUILTIN_NOSPEC        "type"    , typecmd    },
9823         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9824         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9825 #if ENABLE_ASH_ALIAS
9826         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9827 #endif
9828         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9829         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9830 };
9831
9832 /* Should match the above table! */
9833 #define COMMANDCMD (builtintab + \
9834         /* . : */       2 + \
9835         /* [ */         1 * ENABLE_ASH_TEST + \
9836         /* [[ */        1 * BASH_TEST2 + \
9837         /* alias */     1 * ENABLE_ASH_ALIAS + \
9838         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9839         /* break cd cddir  */   3)
9840 #define EVALCMD (COMMANDCMD + \
9841         /* command */   1 * ENABLE_ASH_CMDCMD + \
9842         /* continue */  1 + \
9843         /* echo */      1 * ENABLE_ASH_ECHO + \
9844         0)
9845 #define EXECCMD (EVALCMD + \
9846         /* eval */      1)
9847
9848 /*
9849  * Search the table of builtin commands.
9850  */
9851 static int
9852 pstrcmp1(const void *a, const void *b)
9853 {
9854         return strcmp((char*)a, *(char**)b + 1);
9855 }
9856 static struct builtincmd *
9857 find_builtin(const char *name)
9858 {
9859         struct builtincmd *bp;
9860
9861         bp = bsearch(
9862                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9863                 pstrcmp1
9864         );
9865         return bp;
9866 }
9867
9868 /*
9869  * Execute a simple command.
9870  */
9871 static int
9872 isassignment(const char *p)
9873 {
9874         const char *q = endofname(p);
9875         if (p == q)
9876                 return 0;
9877         return *q == '=';
9878 }
9879 static int FAST_FUNC
9880 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9881 {
9882         /* Preserve exitstatus of a previous possible redirection
9883          * as POSIX mandates */
9884         return back_exitstatus;
9885 }
9886 static int
9887 evalcommand(union node *cmd, int flags)
9888 {
9889         static const struct builtincmd null_bltin = {
9890                 "\0\0", bltincmd /* why three NULs? */
9891         };
9892         struct localvar_list *localvar_stop;
9893         struct redirtab *redir_stop;
9894         struct stackmark smark;
9895         union node *argp;
9896         struct arglist arglist;
9897         struct arglist varlist;
9898         char **argv;
9899         int argc;
9900         const struct strlist *sp;
9901         struct cmdentry cmdentry;
9902         struct job *jp;
9903         char *lastarg;
9904         const char *path;
9905         int spclbltin;
9906         int status;
9907         char **nargv;
9908         smallint cmd_is_exec;
9909
9910         errlinno = lineno = cmd->ncmd.linno;
9911         if (funcline)
9912                 lineno -= funcline - 1;
9913
9914         /* First expand the arguments. */
9915         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9916         setstackmark(&smark);
9917         localvar_stop = pushlocalvars();
9918         back_exitstatus = 0;
9919
9920         cmdentry.cmdtype = CMDBUILTIN;
9921         cmdentry.u.cmd = &null_bltin;
9922         varlist.lastp = &varlist.list;
9923         *varlist.lastp = NULL;
9924         arglist.lastp = &arglist.list;
9925         *arglist.lastp = NULL;
9926
9927         argc = 0;
9928         if (cmd->ncmd.args) {
9929                 struct builtincmd *bcmd;
9930                 smallint pseudovarflag;
9931
9932                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9933                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9934
9935                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9936                         struct strlist **spp;
9937
9938                         spp = arglist.lastp;
9939                         if (pseudovarflag && isassignment(argp->narg.text))
9940                                 expandarg(argp, &arglist, EXP_VARTILDE);
9941                         else
9942                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9943
9944                         for (sp = *spp; sp; sp = sp->next)
9945                                 argc++;
9946                 }
9947         }
9948
9949         /* Reserve one extra spot at the front for shellexec. */
9950         nargv = stalloc(sizeof(char *) * (argc + 2));
9951         argv = ++nargv;
9952         for (sp = arglist.list; sp; sp = sp->next) {
9953                 TRACE(("evalcommand arg: %s\n", sp->text));
9954                 *nargv++ = sp->text;
9955         }
9956         *nargv = NULL;
9957
9958         lastarg = NULL;
9959         if (iflag && funcline == 0 && argc > 0)
9960                 lastarg = nargv[-1];
9961
9962         expredir(cmd->ncmd.redirect);
9963         redir_stop = pushredir(cmd->ncmd.redirect);
9964         preverrout_fd = 2;
9965         if (BASH_XTRACEFD && xflag) {
9966                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9967                  * we do not emulate this. We only use its value.
9968                  */
9969                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9970                 if (xtracefd && is_number(xtracefd))
9971                         preverrout_fd = atoi(xtracefd);
9972
9973         }
9974         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9975
9976         path = vpath.var_text;
9977         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9978                 struct strlist **spp;
9979                 char *p;
9980
9981                 spp = varlist.lastp;
9982                 expandarg(argp, &varlist, EXP_VARTILDE);
9983
9984                 mklocal((*spp)->text);
9985
9986                 /*
9987                  * Modify the command lookup path, if a PATH= assignment
9988                  * is present
9989                  */
9990                 p = (*spp)->text;
9991                 if (varcmp(p, path) == 0)
9992                         path = p;
9993         }
9994
9995         /* Print the command if xflag is set. */
9996         if (xflag) {
9997                 const char *pfx = "";
9998
9999                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10000
10001                 sp = varlist.list;
10002                 while (sp) {
10003                         char *varval = sp->text;
10004                         char *eq = strchrnul(varval, '=');
10005                         if (*eq)
10006                                 eq++;
10007                         fdprintf(preverrout_fd, "%s%.*s%s",
10008                                 pfx,
10009                                 (int)(eq - varval), varval,
10010                                 maybe_single_quote(eq)
10011                         );
10012                         sp = sp->next;
10013                         pfx = " ";
10014                 }
10015
10016                 sp = arglist.list;
10017                 while (sp) {
10018                         fdprintf(preverrout_fd, "%s%s",
10019                                 pfx,
10020                                 /* always quote if matches reserved word: */
10021                                 findkwd(sp->text)
10022                                 ? single_quote(sp->text)
10023                                 : maybe_single_quote(sp->text)
10024                         );
10025                         sp = sp->next;
10026                         pfx = " ";
10027                 }
10028                 safe_write(preverrout_fd, "\n", 1);
10029         }
10030
10031         cmd_is_exec = 0;
10032         spclbltin = -1;
10033
10034         /* Now locate the command. */
10035         if (argc) {
10036                 int cmd_flag = DO_ERR;
10037 #if ENABLE_ASH_CMDCMD
10038                 const char *oldpath = path + 5;
10039 #endif
10040                 path += 5;
10041                 for (;;) {
10042                         find_command(argv[0], &cmdentry, cmd_flag, path);
10043                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10044                                 flush_stdout_stderr();
10045                                 status = 127;
10046                                 goto bail;
10047                         }
10048
10049                         /* implement bltin and command here */
10050                         if (cmdentry.cmdtype != CMDBUILTIN)
10051                                 break;
10052                         if (spclbltin < 0)
10053                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10054                         if (cmdentry.u.cmd == EXECCMD)
10055                                 cmd_is_exec = 1;
10056 #if ENABLE_ASH_CMDCMD
10057                         if (cmdentry.u.cmd == COMMANDCMD) {
10058                                 path = oldpath;
10059                                 nargv = parse_command_args(argv, &path);
10060                                 if (!nargv)
10061                                         break;
10062                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10063                                  * nargv => "PROG". path is updated if -p.
10064                                  */
10065                                 argc -= nargv - argv;
10066                                 argv = nargv;
10067                                 cmd_flag |= DO_NOFUNC;
10068                         } else
10069 #endif
10070                                 break;
10071                 }
10072         }
10073
10074         if (status) {
10075  bail:
10076                 exitstatus = status;
10077
10078                 /* We have a redirection error. */
10079                 if (spclbltin > 0)
10080                         raise_exception(EXERROR);
10081
10082                 goto out;
10083         }
10084
10085         /* Execute the command. */
10086         switch (cmdentry.cmdtype) {
10087         default: {
10088
10089 #if ENABLE_FEATURE_SH_STANDALONE \
10090  && ENABLE_FEATURE_SH_NOFORK \
10091  && NUM_APPLETS > 1
10092 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10093  *     around run_nofork_applet() call.
10094  * (2) Should this check also be done in forkshell()?
10095  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10096  */
10097                 /* find_command() encodes applet_no as (-2 - applet_no) */
10098                 int applet_no = (- cmdentry.u.index - 2);
10099                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10100                         char **sv_environ;
10101
10102                         INT_OFF;
10103                         sv_environ = environ;
10104                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10105                         /*
10106                          * Run <applet>_main().
10107                          * Signals (^C) can't interrupt here.
10108                          * Otherwise we can mangle stdio or malloc internal state.
10109                          * This makes applets which can run for a long time
10110                          * and/or wait for user input ineligible for NOFORK:
10111                          * for example, "yes" or "rm" (rm -i waits for input).
10112                          */
10113                         status = run_nofork_applet(applet_no, argv);
10114                         environ = sv_environ;
10115                         /*
10116                          * Try enabling NOFORK for "yes" applet.
10117                          * ^C _will_ stop it (write returns EINTR),
10118                          * but this causes stdout FILE to be stuck
10119                          * and needing clearerr(). What if other applets
10120                          * also can get EINTRs? Do we need to switch
10121                          * our signals to SA_RESTART?
10122                          */
10123                         /*clearerr(stdout);*/
10124                         INT_ON;
10125                         break;
10126                 }
10127 #endif
10128                 /* Can we avoid forking? For example, very last command
10129                  * in a script or a subshell does not need forking,
10130                  * we can just exec it.
10131                  */
10132                 if (!(flags & EV_EXIT) || may_have_traps) {
10133                         /* No, forking off a child is necessary */
10134                         INT_OFF;
10135                         get_tty_state();
10136                         jp = makejob(/*cmd,*/ 1);
10137                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10138                                 /* parent */
10139                                 status = waitforjob(jp);
10140                                 INT_ON;
10141                                 TRACE(("forked child exited with %d\n", status));
10142                                 break;
10143                         }
10144                         /* child */
10145                         FORCE_INT_ON;
10146                         /* fall through to exec'ing external program */
10147                 }
10148                 listsetvar(varlist.list, VEXPORT|VSTACK);
10149                 shellexec(argv[0], argv, path, cmdentry.u.index);
10150                 /* NOTREACHED */
10151         } /* default */
10152         case CMDBUILTIN:
10153                 if (spclbltin > 0 || argc == 0) {
10154                         poplocalvars(1);
10155                         if (cmd_is_exec && argc > 1)
10156                                 listsetvar(varlist.list, VEXPORT);
10157                 }
10158
10159                 /* Tight loop with builtins only:
10160                  * "while kill -0 $child; do true; done"
10161                  * will never exit even if $child died, unless we do this
10162                  * to reap the zombie and make kill detect that it's gone: */
10163                 dowait(DOWAIT_NONBLOCK, NULL);
10164
10165                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10166                         if (exception_type == EXERROR && spclbltin <= 0) {
10167                                 FORCE_INT_ON;
10168                                 goto readstatus;
10169                         }
10170  raise:
10171                         longjmp(exception_handler->loc, 1);
10172                 }
10173                 goto readstatus;
10174
10175         case CMDFUNCTION:
10176                 poplocalvars(1);
10177                 /* See above for the rationale */
10178                 dowait(DOWAIT_NONBLOCK, NULL);
10179                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10180                         goto raise;
10181  readstatus:
10182                 status = exitstatus;
10183                 break;
10184         } /* switch */
10185
10186  out:
10187         if (cmd->ncmd.redirect)
10188                 popredir(/*drop:*/ cmd_is_exec);
10189         unwindredir(redir_stop);
10190         unwindlocalvars(localvar_stop);
10191         if (lastarg) {
10192                 /* dsl: I think this is intended to be used to support
10193                  * '_' in 'vi' command mode during line editing...
10194                  * However I implemented that within libedit itself.
10195                  */
10196                 setvar0("_", lastarg);
10197         }
10198         popstackmark(&smark);
10199
10200         return status;
10201 }
10202
10203 static int
10204 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10205 {
10206         char *volatile savecmdname;
10207         struct jmploc *volatile savehandler;
10208         struct jmploc jmploc;
10209         int status;
10210         int i;
10211
10212         savecmdname = commandname;
10213         savehandler = exception_handler;
10214         i = setjmp(jmploc.loc);
10215         if (i)
10216                 goto cmddone;
10217         exception_handler = &jmploc;
10218         commandname = argv[0];
10219         argptr = argv + 1;
10220         optptr = NULL;                  /* initialize nextopt */
10221         if (cmd == EVALCMD)
10222                 status = evalcmd(argc, argv, flags);
10223         else
10224                 status = (*cmd->builtin)(argc, argv);
10225         flush_stdout_stderr();
10226         status |= ferror(stdout);
10227         exitstatus = status;
10228  cmddone:
10229         clearerr(stdout);
10230         commandname = savecmdname;
10231         exception_handler = savehandler;
10232
10233         return i;
10234 }
10235
10236 static int
10237 goodname(const char *p)
10238 {
10239         return endofname(p)[0] == '\0';
10240 }
10241
10242
10243 /*
10244  * Search for a command.  This is called before we fork so that the
10245  * location of the command will be available in the parent as well as
10246  * the child.  The check for "goodname" is an overly conservative
10247  * check that the name will not be subject to expansion.
10248  */
10249 static void
10250 prehash(union node *n)
10251 {
10252         struct cmdentry entry;
10253
10254         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10255                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10256 }
10257
10258
10259 /* ============ Builtin commands
10260  *
10261  * Builtin commands whose functions are closely tied to evaluation
10262  * are implemented here.
10263  */
10264
10265 /*
10266  * Handle break and continue commands.  Break, continue, and return are
10267  * all handled by setting the evalskip flag.  The evaluation routines
10268  * above all check this flag, and if it is set they start skipping
10269  * commands rather than executing them.  The variable skipcount is
10270  * the number of loops to break/continue, or the number of function
10271  * levels to return.  (The latter is always 1.)  It should probably
10272  * be an error to break out of more loops than exist, but it isn't
10273  * in the standard shell so we don't make it one here.
10274  */
10275 static int FAST_FUNC
10276 breakcmd(int argc UNUSED_PARAM, char **argv)
10277 {
10278         int n = argv[1] ? number(argv[1]) : 1;
10279
10280         if (n <= 0)
10281                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10282         if (n > loopnest)
10283                 n = loopnest;
10284         if (n > 0) {
10285                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10286                 skipcount = n;
10287         }
10288         return 0;
10289 }
10290
10291
10292 /*
10293  * This implements the input routines used by the parser.
10294  */
10295
10296 enum {
10297         INPUT_PUSH_FILE = 1,
10298         INPUT_NOFILE_OK = 2,
10299 };
10300
10301 static smallint checkkwd;
10302 /* values of checkkwd variable */
10303 #define CHKALIAS        0x1
10304 #define CHKKWD          0x2
10305 #define CHKNL           0x4
10306 #define CHKEOFMARK      0x8
10307
10308 /*
10309  * Push a string back onto the input at this current parsefile level.
10310  * We handle aliases this way.
10311  */
10312 #if !ENABLE_ASH_ALIAS
10313 #define pushstring(s, ap) pushstring(s)
10314 #endif
10315 static void
10316 pushstring(char *s, struct alias *ap)
10317 {
10318         struct strpush *sp;
10319         int len;
10320
10321         len = strlen(s);
10322         INT_OFF;
10323         if (g_parsefile->strpush) {
10324                 sp = ckzalloc(sizeof(*sp));
10325                 sp->prev = g_parsefile->strpush;
10326         } else {
10327                 sp = &(g_parsefile->basestrpush);
10328         }
10329         g_parsefile->strpush = sp;
10330         sp->prev_string = g_parsefile->next_to_pgetc;
10331         sp->prev_left_in_line = g_parsefile->left_in_line;
10332         sp->unget = g_parsefile->unget;
10333         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10334 #if ENABLE_ASH_ALIAS
10335         sp->ap = ap;
10336         if (ap) {
10337                 ap->flag |= ALIASINUSE;
10338                 sp->string = s;
10339         }
10340 #endif
10341         g_parsefile->next_to_pgetc = s;
10342         g_parsefile->left_in_line = len;
10343         g_parsefile->unget = 0;
10344         INT_ON;
10345 }
10346
10347 static void
10348 popstring(void)
10349 {
10350         struct strpush *sp = g_parsefile->strpush;
10351
10352         INT_OFF;
10353 #if ENABLE_ASH_ALIAS
10354         if (sp->ap) {
10355                 if (g_parsefile->next_to_pgetc[-1] == ' '
10356                  || g_parsefile->next_to_pgetc[-1] == '\t'
10357                 ) {
10358                         checkkwd |= CHKALIAS;
10359                 }
10360                 if (sp->string != sp->ap->val) {
10361                         free(sp->string);
10362                 }
10363                 sp->ap->flag &= ~ALIASINUSE;
10364                 if (sp->ap->flag & ALIASDEAD) {
10365                         unalias(sp->ap->name);
10366                 }
10367         }
10368 #endif
10369         g_parsefile->next_to_pgetc = sp->prev_string;
10370         g_parsefile->left_in_line = sp->prev_left_in_line;
10371         g_parsefile->unget = sp->unget;
10372         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10373         g_parsefile->strpush = sp->prev;
10374         if (sp != &(g_parsefile->basestrpush))
10375                 free(sp);
10376         INT_ON;
10377 }
10378
10379 static int
10380 preadfd(void)
10381 {
10382         int nr;
10383         char *buf = g_parsefile->buf;
10384
10385         g_parsefile->next_to_pgetc = buf;
10386 #if ENABLE_FEATURE_EDITING
10387  retry:
10388         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10389                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10390         else {
10391 # if ENABLE_ASH_IDLE_TIMEOUT
10392                 int timeout = -1;
10393                 if (iflag) {
10394                         const char *tmout_var = lookupvar("TMOUT");
10395                         if (tmout_var) {
10396                                 timeout = atoi(tmout_var) * 1000;
10397                                 if (timeout <= 0)
10398                                         timeout = -1;
10399                         }
10400                 }
10401                 line_input_state->timeout = timeout;
10402 # endif
10403 # if ENABLE_FEATURE_TAB_COMPLETION
10404                 line_input_state->path_lookup = pathval();
10405 # endif
10406                 reinit_unicode_for_ash();
10407                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10408                 if (nr == 0) {
10409                         /* ^C pressed, "convert" to SIGINT */
10410                         write(STDOUT_FILENO, "^C", 2);
10411                         if (trap[SIGINT]) {
10412                                 buf[0] = '\n';
10413                                 buf[1] = '\0';
10414                                 raise(SIGINT);
10415                                 return 1;
10416                         }
10417                         exitstatus = 128 + SIGINT;
10418                         bb_putchar('\n');
10419                         goto retry;
10420                 }
10421                 if (nr < 0) {
10422                         if (errno == 0) {
10423                                 /* Ctrl+D pressed */
10424                                 nr = 0;
10425                         }
10426 # if ENABLE_ASH_IDLE_TIMEOUT
10427                         else if (errno == EAGAIN && timeout > 0) {
10428                                 puts("\007timed out waiting for input: auto-logout");
10429                                 exitshell();
10430                         }
10431 # endif
10432                 }
10433         }
10434 #else
10435         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10436 #endif
10437
10438 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10439         if (nr < 0) {
10440                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10441                         int flags = fcntl(0, F_GETFL);
10442                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10443                                 flags &= ~O_NONBLOCK;
10444                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10445                                         out2str("sh: turning off NDELAY mode\n");
10446                                         goto retry;
10447                                 }
10448                         }
10449                 }
10450         }
10451 #endif
10452         return nr;
10453 }
10454
10455 /*
10456  * Refill the input buffer and return the next input character:
10457  *
10458  * 1) If a string was pushed back on the input, pop it;
10459  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10460  *    or we are reading from a string so we can't refill the buffer,
10461  *    return EOF.
10462  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10463  * 4) Process input up to the next newline, deleting nul characters.
10464  */
10465 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10466 #define pgetc_debug(...) ((void)0)
10467 static int pgetc(void);
10468 static int
10469 preadbuffer(void)
10470 {
10471         char *q;
10472         int more;
10473
10474         if (g_parsefile->strpush) {
10475 #if ENABLE_ASH_ALIAS
10476                 if (g_parsefile->left_in_line == -1
10477                  && g_parsefile->strpush->ap
10478                  && g_parsefile->next_to_pgetc[-1] != ' '
10479                  && g_parsefile->next_to_pgetc[-1] != '\t'
10480                 ) {
10481                         pgetc_debug("preadbuffer PEOA");
10482                         return PEOA;
10483                 }
10484 #endif
10485                 popstring();
10486                 return pgetc();
10487         }
10488         /* on both branches above g_parsefile->left_in_line < 0.
10489          * "pgetc" needs refilling.
10490          */
10491
10492         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10493          * pungetc() may increment it a few times.
10494          * Assuming it won't increment it to less than -90.
10495          */
10496         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10497                 pgetc_debug("preadbuffer PEOF1");
10498                 /* even in failure keep left_in_line and next_to_pgetc
10499                  * in lock step, for correct multi-layer pungetc.
10500                  * left_in_line was decremented before preadbuffer(),
10501                  * must inc next_to_pgetc: */
10502                 g_parsefile->next_to_pgetc++;
10503                 return PEOF;
10504         }
10505
10506         more = g_parsefile->left_in_buffer;
10507         if (more <= 0) {
10508                 flush_stdout_stderr();
10509  again:
10510                 more = preadfd();
10511                 if (more <= 0) {
10512                         /* don't try reading again */
10513                         g_parsefile->left_in_line = -99;
10514                         pgetc_debug("preadbuffer PEOF2");
10515                         g_parsefile->next_to_pgetc++;
10516                         return PEOF;
10517                 }
10518         }
10519
10520         /* Find out where's the end of line.
10521          * Set g_parsefile->left_in_line
10522          * and g_parsefile->left_in_buffer acordingly.
10523          * NUL chars are deleted.
10524          */
10525         q = g_parsefile->next_to_pgetc;
10526         for (;;) {
10527                 char c;
10528
10529                 more--;
10530
10531                 c = *q;
10532                 if (c == '\0') {
10533                         memmove(q, q + 1, more);
10534                 } else {
10535                         q++;
10536                         if (c == '\n') {
10537                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10538                                 break;
10539                         }
10540                 }
10541
10542                 if (more <= 0) {
10543                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10544                         if (g_parsefile->left_in_line < 0)
10545                                 goto again;
10546                         break;
10547                 }
10548         }
10549         g_parsefile->left_in_buffer = more;
10550
10551         if (vflag) {
10552                 char save = *q;
10553                 *q = '\0';
10554                 out2str(g_parsefile->next_to_pgetc);
10555                 *q = save;
10556         }
10557
10558         pgetc_debug("preadbuffer at %d:%p'%s'",
10559                         g_parsefile->left_in_line,
10560                         g_parsefile->next_to_pgetc,
10561                         g_parsefile->next_to_pgetc);
10562         return (unsigned char)*g_parsefile->next_to_pgetc++;
10563 }
10564
10565 static void
10566 nlprompt(void)
10567 {
10568         g_parsefile->linno++;
10569         setprompt_if(doprompt, 2);
10570 }
10571 static void
10572 nlnoprompt(void)
10573 {
10574         g_parsefile->linno++;
10575         needprompt = doprompt;
10576 }
10577
10578 static int
10579 pgetc(void)
10580 {
10581         int c;
10582
10583         pgetc_debug("pgetc at %d:%p'%s'",
10584                         g_parsefile->left_in_line,
10585                         g_parsefile->next_to_pgetc,
10586                         g_parsefile->next_to_pgetc);
10587         if (g_parsefile->unget)
10588                 return g_parsefile->lastc[--g_parsefile->unget];
10589
10590         if (--g_parsefile->left_in_line >= 0)
10591                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10592         else
10593                 c = preadbuffer();
10594
10595         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10596         g_parsefile->lastc[0] = c;
10597
10598         return c;
10599 }
10600
10601 #if ENABLE_ASH_ALIAS
10602 static int
10603 pgetc_without_PEOA(void)
10604 {
10605         int c;
10606         do {
10607                 pgetc_debug("pgetc at %d:%p'%s'",
10608                                 g_parsefile->left_in_line,
10609                                 g_parsefile->next_to_pgetc,
10610                                 g_parsefile->next_to_pgetc);
10611                 c = pgetc();
10612         } while (c == PEOA);
10613         return c;
10614 }
10615 #else
10616 # define pgetc_without_PEOA() pgetc()
10617 #endif
10618
10619 /*
10620  * Undo a call to pgetc.  Only two characters may be pushed back.
10621  * PEOF may be pushed back.
10622  */
10623 static void
10624 pungetc(void)
10625 {
10626         g_parsefile->unget++;
10627 }
10628
10629 /* This one eats backslash+newline */
10630 static int
10631 pgetc_eatbnl(void)
10632 {
10633         int c;
10634
10635         while ((c = pgetc()) == '\\') {
10636                 if (pgetc() != '\n') {
10637                         pungetc();
10638                         break;
10639                 }
10640
10641                 nlprompt();
10642         }
10643
10644         return c;
10645 }
10646
10647 /*
10648  * To handle the "." command, a stack of input files is used.  Pushfile
10649  * adds a new entry to the stack and popfile restores the previous level.
10650  */
10651 static void
10652 pushfile(void)
10653 {
10654         struct parsefile *pf;
10655
10656         pf = ckzalloc(sizeof(*pf));
10657         pf->prev = g_parsefile;
10658         pf->pf_fd = -1;
10659         /*pf->strpush = NULL; - ckzalloc did it */
10660         /*pf->basestrpush.prev = NULL;*/
10661         /*pf->unget = 0;*/
10662         g_parsefile = pf;
10663 }
10664
10665 static void
10666 popfile(void)
10667 {
10668         struct parsefile *pf = g_parsefile;
10669
10670         if (pf == &basepf)
10671                 return;
10672
10673         INT_OFF;
10674         if (pf->pf_fd >= 0)
10675                 close(pf->pf_fd);
10676         free(pf->buf);
10677         while (pf->strpush)
10678                 popstring();
10679         g_parsefile = pf->prev;
10680         free(pf);
10681         INT_ON;
10682 }
10683
10684 /*
10685  * Return to top level.
10686  */
10687 static void
10688 popallfiles(void)
10689 {
10690         while (g_parsefile != &basepf)
10691                 popfile();
10692 }
10693
10694 /*
10695  * Close the file(s) that the shell is reading commands from.  Called
10696  * after a fork is done.
10697  */
10698 static void
10699 closescript(void)
10700 {
10701         popallfiles();
10702         if (g_parsefile->pf_fd > 0) {
10703                 close(g_parsefile->pf_fd);
10704                 g_parsefile->pf_fd = 0;
10705         }
10706 }
10707
10708 /*
10709  * Like setinputfile, but takes an open file descriptor.  Call this with
10710  * interrupts off.
10711  */
10712 static void
10713 setinputfd(int fd, int push)
10714 {
10715         if (push) {
10716                 pushfile();
10717                 g_parsefile->buf = NULL;
10718         }
10719         g_parsefile->pf_fd = fd;
10720         if (g_parsefile->buf == NULL)
10721                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10722         g_parsefile->left_in_buffer = 0;
10723         g_parsefile->left_in_line = 0;
10724         g_parsefile->linno = 1;
10725 }
10726
10727 /*
10728  * Set the input to take input from a file.  If push is set, push the
10729  * old input onto the stack first.
10730  */
10731 static int
10732 setinputfile(const char *fname, int flags)
10733 {
10734         int fd;
10735
10736         INT_OFF;
10737         fd = open(fname, O_RDONLY);
10738         if (fd < 0) {
10739                 if (flags & INPUT_NOFILE_OK)
10740                         goto out;
10741                 exitstatus = 127;
10742                 ash_msg_and_raise_perror("can't open '%s'", fname);
10743         }
10744         if (fd < 10)
10745                 fd = savefd(fd);
10746         else
10747                 close_on_exec_on(fd);
10748         setinputfd(fd, flags & INPUT_PUSH_FILE);
10749  out:
10750         INT_ON;
10751         return fd;
10752 }
10753
10754 /*
10755  * Like setinputfile, but takes input from a string.
10756  */
10757 static void
10758 setinputstring(char *string)
10759 {
10760         INT_OFF;
10761         pushfile();
10762         g_parsefile->next_to_pgetc = string;
10763         g_parsefile->left_in_line = strlen(string);
10764         g_parsefile->buf = NULL;
10765         g_parsefile->linno = 1;
10766         INT_ON;
10767 }
10768
10769
10770 /*
10771  * Routines to check for mail.
10772  */
10773
10774 #if ENABLE_ASH_MAIL
10775
10776 /* Hash of mtimes of mailboxes */
10777 static unsigned mailtime_hash;
10778 /* Set if MAIL or MAILPATH is changed. */
10779 static smallint mail_var_path_changed;
10780
10781 /*
10782  * Print appropriate message(s) if mail has arrived.
10783  * If mail_var_path_changed is set,
10784  * then the value of MAIL has mail_var_path_changed,
10785  * so we just update the values.
10786  */
10787 static void
10788 chkmail(void)
10789 {
10790         const char *mpath;
10791         char *p;
10792         char *q;
10793         unsigned new_hash;
10794         struct stackmark smark;
10795         struct stat statb;
10796
10797         setstackmark(&smark);
10798         mpath = mpathset() ? mpathval() : mailval();
10799         new_hash = 0;
10800         for (;;) {
10801                 p = path_advance(&mpath, nullstr);
10802                 if (p == NULL)
10803                         break;
10804                 if (*p == '\0')
10805                         continue;
10806                 for (q = p; *q; q++)
10807                         continue;
10808 #if DEBUG
10809                 if (q[-1] != '/')
10810                         abort();
10811 #endif
10812                 q[-1] = '\0';                   /* delete trailing '/' */
10813                 if (stat(p, &statb) < 0) {
10814                         continue;
10815                 }
10816                 /* Very simplistic "hash": just a sum of all mtimes */
10817                 new_hash += (unsigned)statb.st_mtime;
10818         }
10819         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10820                 if (mailtime_hash != 0)
10821                         out2str("you have mail\n");
10822                 mailtime_hash = new_hash;
10823         }
10824         mail_var_path_changed = 0;
10825         popstackmark(&smark);
10826 }
10827
10828 static void FAST_FUNC
10829 changemail(const char *val UNUSED_PARAM)
10830 {
10831         mail_var_path_changed = 1;
10832 }
10833
10834 #endif /* ASH_MAIL */
10835
10836
10837 /* ============ ??? */
10838
10839 /*
10840  * Set the shell parameters.
10841  */
10842 static void
10843 setparam(char **argv)
10844 {
10845         char **newparam;
10846         char **ap;
10847         int nparam;
10848
10849         for (nparam = 0; argv[nparam]; nparam++)
10850                 continue;
10851         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10852         while (*argv) {
10853                 *ap++ = ckstrdup(*argv++);
10854         }
10855         *ap = NULL;
10856         freeparam(&shellparam);
10857         shellparam.malloced = 1;
10858         shellparam.nparam = nparam;
10859         shellparam.p = newparam;
10860 #if ENABLE_ASH_GETOPTS
10861         shellparam.optind = 1;
10862         shellparam.optoff = -1;
10863 #endif
10864 }
10865
10866 /*
10867  * Process shell options.  The global variable argptr contains a pointer
10868  * to the argument list; we advance it past the options.
10869  *
10870  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10871  * For a non-interactive shell, an error condition encountered
10872  * by a special built-in ... shall cause the shell to write a diagnostic message
10873  * to standard error and exit as shown in the following table:
10874  * Error                                           Special Built-In
10875  * ...
10876  * Utility syntax error (option or operand error)  Shall exit
10877  * ...
10878  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10879  * we see that bash does not do that (set "finishes" with error code 1 instead,
10880  * and shell continues), and people rely on this behavior!
10881  * Testcase:
10882  * set -o barfoo 2>/dev/null
10883  * echo $?
10884  *
10885  * Oh well. Let's mimic that.
10886  */
10887 static int
10888 plus_minus_o(char *name, int val)
10889 {
10890         int i;
10891
10892         if (name) {
10893                 for (i = 0; i < NOPTS; i++) {
10894                         if (strcmp(name, optnames(i)) == 0) {
10895                                 optlist[i] = val;
10896                                 return 0;
10897                         }
10898                 }
10899                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10900                 return 1;
10901         }
10902         for (i = 0; i < NOPTS; i++) {
10903                 if (val) {
10904                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10905                 } else {
10906                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10907                 }
10908         }
10909         return 0;
10910 }
10911 static void
10912 setoption(int flag, int val)
10913 {
10914         int i;
10915
10916         for (i = 0; i < NOPTS; i++) {
10917                 if (optletters(i) == flag) {
10918                         optlist[i] = val;
10919                         return;
10920                 }
10921         }
10922         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10923         /* NOTREACHED */
10924 }
10925 static int
10926 options(int cmdline, int *login_sh)
10927 {
10928         char *p;
10929         int val;
10930         int c;
10931
10932         if (cmdline)
10933                 minusc = NULL;
10934         while ((p = *argptr) != NULL) {
10935                 c = *p++;
10936                 if (c != '-' && c != '+')
10937                         break;
10938                 argptr++;
10939                 val = 0; /* val = 0 if c == '+' */
10940                 if (c == '-') {
10941                         val = 1;
10942                         if (p[0] == '\0' || LONE_DASH(p)) {
10943                                 if (!cmdline) {
10944                                         /* "-" means turn off -x and -v */
10945                                         if (p[0] == '\0')
10946                                                 xflag = vflag = 0;
10947                                         /* "--" means reset params */
10948                                         else if (*argptr == NULL)
10949                                                 setparam(argptr);
10950                                 }
10951                                 break;    /* "-" or "--" terminates options */
10952                         }
10953                 }
10954                 /* first char was + or - */
10955                 while ((c = *p++) != '\0') {
10956                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10957                         if (c == 'c' && cmdline) {
10958                                 minusc = p;     /* command is after shell args */
10959                         } else if (c == 'o') {
10960                                 if (plus_minus_o(*argptr, val)) {
10961                                         /* it already printed err message */
10962                                         return 1; /* error */
10963                                 }
10964                                 if (*argptr)
10965                                         argptr++;
10966                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10967                                 if (login_sh)
10968                                         *login_sh = 1;
10969                         /* bash does not accept +-login, we also won't */
10970                         } else if (cmdline && val && (c == '-')) { /* long options */
10971                                 if (strcmp(p, "login") == 0) {
10972                                         if (login_sh)
10973                                                 *login_sh = 1;
10974                                 }
10975                                 break;
10976                         } else {
10977                                 setoption(c, val);
10978                         }
10979                 }
10980         }
10981         return 0;
10982 }
10983
10984 /*
10985  * The shift builtin command.
10986  */
10987 static int FAST_FUNC
10988 shiftcmd(int argc UNUSED_PARAM, char **argv)
10989 {
10990         int n;
10991         char **ap1, **ap2;
10992
10993         n = 1;
10994         if (argv[1])
10995                 n = number(argv[1]);
10996         if (n > shellparam.nparam)
10997                 return 1;
10998         INT_OFF;
10999         shellparam.nparam -= n;
11000         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11001                 if (shellparam.malloced)
11002                         free(*ap1);
11003         }
11004         ap2 = shellparam.p;
11005         while ((*ap2++ = *ap1++) != NULL)
11006                 continue;
11007 #if ENABLE_ASH_GETOPTS
11008         shellparam.optind = 1;
11009         shellparam.optoff = -1;
11010 #endif
11011         INT_ON;
11012         return 0;
11013 }
11014
11015 /*
11016  * POSIX requires that 'set' (but not export or readonly) output the
11017  * variables in lexicographic order - by the locale's collating order (sigh).
11018  * Maybe we could keep them in an ordered balanced binary tree
11019  * instead of hashed lists.
11020  * For now just roll 'em through qsort for printing...
11021  */
11022 static int
11023 showvars(const char *sep_prefix, int on, int off)
11024 {
11025         const char *sep;
11026         char **ep, **epend;
11027
11028         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11029         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11030
11031         sep = *sep_prefix ? " " : sep_prefix;
11032
11033         for (; ep < epend; ep++) {
11034                 const char *p;
11035                 const char *q;
11036
11037                 p = endofname(*ep);
11038 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11039  * makes "export -p" to have output not suitable for "eval":
11040  * import os
11041  * os.environ["test-test"]="test"
11042  * if os.fork() == 0:
11043  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11044  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11045  */
11046                 q = nullstr;
11047                 if (*p == '=')
11048                         q = single_quote(++p);
11049                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11050         }
11051         return 0;
11052 }
11053
11054 /*
11055  * The set command builtin.
11056  */
11057 static int FAST_FUNC
11058 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11059 {
11060         int retval;
11061
11062         if (!argv[1])
11063                 return showvars(nullstr, 0, VUNSET);
11064
11065         INT_OFF;
11066         retval = options(/*cmdline:*/ 0, NULL);
11067         if (retval == 0) { /* if no parse error... */
11068                 optschanged();
11069                 if (*argptr != NULL) {
11070                         setparam(argptr);
11071                 }
11072         }
11073         INT_ON;
11074         return retval;
11075 }
11076
11077 #if ENABLE_ASH_RANDOM_SUPPORT
11078 static void FAST_FUNC
11079 change_random(const char *value)
11080 {
11081         uint32_t t;
11082
11083         if (value == NULL) {
11084                 /* "get", generate */
11085                 t = next_random(&random_gen);
11086                 /* set without recursion */
11087                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11088                 vrandom.flags &= ~VNOFUNC;
11089         } else {
11090                 /* set/reset */
11091                 t = strtoul(value, NULL, 10);
11092                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11093         }
11094 }
11095 #endif
11096
11097 #if ENABLE_ASH_GETOPTS
11098 static int
11099 getopts(char *optstr, char *optvar, char **optfirst)
11100 {
11101         char *p, *q;
11102         char c = '?';
11103         int done = 0;
11104         char sbuf[2];
11105         char **optnext;
11106         int ind = shellparam.optind;
11107         int off = shellparam.optoff;
11108
11109         sbuf[1] = '\0';
11110
11111         shellparam.optind = -1;
11112         optnext = optfirst + ind - 1;
11113
11114         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11115                 p = NULL;
11116         else
11117                 p = optnext[-1] + off;
11118         if (p == NULL || *p == '\0') {
11119                 /* Current word is done, advance */
11120                 p = *optnext;
11121                 if (p == NULL || *p != '-' || *++p == '\0') {
11122  atend:
11123                         unsetvar("OPTARG");
11124                         p = NULL;
11125                         done = 1;
11126                         goto out;
11127                 }
11128                 optnext++;
11129                 if (LONE_DASH(p))        /* check for "--" */
11130                         goto atend;
11131         }
11132
11133         c = *p++;
11134         for (q = optstr; *q != c;) {
11135                 if (*q == '\0') {
11136                         /* OPTERR is a bashism */
11137                         const char *cp = lookupvar("OPTERR");
11138                         if ((cp && LONE_CHAR(cp, '0'))
11139                          || (optstr[0] == ':')
11140                         ) {
11141                                 sbuf[0] = c;
11142                                 /*sbuf[1] = '\0'; - already is */
11143                                 setvar0("OPTARG", sbuf);
11144                         } else {
11145                                 fprintf(stderr, "Illegal option -%c\n", c);
11146                                 unsetvar("OPTARG");
11147                         }
11148                         c = '?';
11149                         goto out;
11150                 }
11151                 if (*++q == ':')
11152                         q++;
11153         }
11154
11155         if (*++q == ':') {
11156                 if (*p == '\0' && (p = *optnext) == NULL) {
11157                         /* OPTERR is a bashism */
11158                         const char *cp = lookupvar("OPTERR");
11159                         if ((cp && LONE_CHAR(cp, '0'))
11160                          || (optstr[0] == ':')
11161                         ) {
11162                                 sbuf[0] = c;
11163                                 /*sbuf[1] = '\0'; - already is */
11164                                 setvar0("OPTARG", sbuf);
11165                                 c = ':';
11166                         } else {
11167                                 fprintf(stderr, "No arg for -%c option\n", c);
11168                                 unsetvar("OPTARG");
11169                                 c = '?';
11170                         }
11171                         goto out;
11172                 }
11173
11174                 if (p == *optnext)
11175                         optnext++;
11176                 setvar0("OPTARG", p);
11177                 p = NULL;
11178         } else
11179                 setvar0("OPTARG", nullstr);
11180  out:
11181         ind = optnext - optfirst + 1;
11182         setvar("OPTIND", itoa(ind), VNOFUNC);
11183         sbuf[0] = c;
11184         /*sbuf[1] = '\0'; - already is */
11185         setvar0(optvar, sbuf);
11186
11187         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11188         shellparam.optind = ind;
11189
11190         return done;
11191 }
11192
11193 /*
11194  * The getopts builtin.  Shellparam.optnext points to the next argument
11195  * to be processed.  Shellparam.optptr points to the next character to
11196  * be processed in the current argument.  If shellparam.optnext is NULL,
11197  * then it's the first time getopts has been called.
11198  */
11199 static int FAST_FUNC
11200 getoptscmd(int argc, char **argv)
11201 {
11202         char **optbase;
11203
11204         if (argc < 3)
11205                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11206         if (argc == 3) {
11207                 optbase = shellparam.p;
11208                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11209                         shellparam.optind = 1;
11210                         shellparam.optoff = -1;
11211                 }
11212         } else {
11213                 optbase = &argv[3];
11214                 if ((unsigned)shellparam.optind > argc - 2) {
11215                         shellparam.optind = 1;
11216                         shellparam.optoff = -1;
11217                 }
11218         }
11219
11220         return getopts(argv[1], argv[2], optbase);
11221 }
11222 #endif /* ASH_GETOPTS */
11223
11224
11225 /* ============ Shell parser */
11226
11227 struct heredoc {
11228         struct heredoc *next;   /* next here document in list */
11229         union node *here;       /* redirection node */
11230         char *eofmark;          /* string indicating end of input */
11231         smallint striptabs;     /* if set, strip leading tabs */
11232 };
11233
11234 static smallint tokpushback;           /* last token pushed back */
11235 static smallint quoteflag;             /* set if (part of) last token was quoted */
11236 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11237 static struct heredoc *heredoclist;    /* list of here documents to read */
11238 static char *wordtext;                 /* text of last word returned by readtoken */
11239 static struct nodelist *backquotelist;
11240 static union node *redirnode;
11241 static struct heredoc *heredoc;
11242
11243 static const char *
11244 tokname(char *buf, int tok)
11245 {
11246         if (tok < TSEMI)
11247                 return tokname_array[tok];
11248         sprintf(buf, "\"%s\"", tokname_array[tok]);
11249         return buf;
11250 }
11251
11252 /* raise_error_unexpected_syntax:
11253  * Called when an unexpected token is read during the parse.  The argument
11254  * is the token that is expected, or -1 if more than one type of token can
11255  * occur at this point.
11256  */
11257 static void raise_error_unexpected_syntax(int) NORETURN;
11258 static void
11259 raise_error_unexpected_syntax(int token)
11260 {
11261         char msg[64];
11262         char buf[16];
11263         int l;
11264
11265         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11266         if (token >= 0)
11267                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11268         raise_error_syntax(msg);
11269         /* NOTREACHED */
11270 }
11271
11272 /* parsing is heavily cross-recursive, need these forward decls */
11273 static union node *andor(void);
11274 static union node *pipeline(void);
11275 static union node *parse_command(void);
11276 static void parseheredoc(void);
11277 static int peektoken(void);
11278 static int readtoken(void);
11279
11280 static union node *
11281 list(int nlflag)
11282 {
11283         union node *n1, *n2, *n3;
11284         int tok;
11285
11286         n1 = NULL;
11287         for (;;) {
11288                 switch (peektoken()) {
11289                 case TNL:
11290                         if (!(nlflag & 1))
11291                                 break;
11292                         parseheredoc();
11293                         return n1;
11294
11295                 case TEOF:
11296                         if (!n1 && (nlflag & 1))
11297                                 n1 = NODE_EOF;
11298                         parseheredoc();
11299                         return n1;
11300                 }
11301
11302                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11303                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11304                         return n1;
11305                 nlflag |= 2;
11306
11307                 n2 = andor();
11308                 tok = readtoken();
11309                 if (tok == TBACKGND) {
11310                         if (n2->type == NPIPE) {
11311                                 n2->npipe.pipe_backgnd = 1;
11312                         } else {
11313                                 if (n2->type != NREDIR) {
11314                                         n3 = stzalloc(sizeof(struct nredir));
11315                                         n3->nredir.n = n2;
11316                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11317                                         n2 = n3;
11318                                 }
11319                                 n2->type = NBACKGND;
11320                         }
11321                 }
11322                 if (n1 == NULL) {
11323                         n1 = n2;
11324                 } else {
11325                         n3 = stzalloc(sizeof(struct nbinary));
11326                         n3->type = NSEMI;
11327                         n3->nbinary.ch1 = n1;
11328                         n3->nbinary.ch2 = n2;
11329                         n1 = n3;
11330                 }
11331                 switch (tok) {
11332                 case TNL:
11333                 case TEOF:
11334                         tokpushback = 1;
11335                         /* fall through */
11336                 case TBACKGND:
11337                 case TSEMI:
11338                         break;
11339                 default:
11340                         if ((nlflag & 1))
11341                                 raise_error_unexpected_syntax(-1);
11342                         tokpushback = 1;
11343                         return n1;
11344                 }
11345         }
11346 }
11347
11348 static union node *
11349 andor(void)
11350 {
11351         union node *n1, *n2, *n3;
11352         int t;
11353
11354         n1 = pipeline();
11355         for (;;) {
11356                 t = readtoken();
11357                 if (t == TAND) {
11358                         t = NAND;
11359                 } else if (t == TOR) {
11360                         t = NOR;
11361                 } else {
11362                         tokpushback = 1;
11363                         return n1;
11364                 }
11365                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11366                 n2 = pipeline();
11367                 n3 = stzalloc(sizeof(struct nbinary));
11368                 n3->type = t;
11369                 n3->nbinary.ch1 = n1;
11370                 n3->nbinary.ch2 = n2;
11371                 n1 = n3;
11372         }
11373 }
11374
11375 static union node *
11376 pipeline(void)
11377 {
11378         union node *n1, *n2, *pipenode;
11379         struct nodelist *lp, *prev;
11380         int negate;
11381
11382         negate = 0;
11383         TRACE(("pipeline: entered\n"));
11384         if (readtoken() == TNOT) {
11385                 negate = !negate;
11386                 checkkwd = CHKKWD | CHKALIAS;
11387         } else
11388                 tokpushback = 1;
11389         n1 = parse_command();
11390         if (readtoken() == TPIPE) {
11391                 pipenode = stzalloc(sizeof(struct npipe));
11392                 pipenode->type = NPIPE;
11393                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11394                 lp = stzalloc(sizeof(struct nodelist));
11395                 pipenode->npipe.cmdlist = lp;
11396                 lp->n = n1;
11397                 do {
11398                         prev = lp;
11399                         lp = stzalloc(sizeof(struct nodelist));
11400                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11401                         lp->n = parse_command();
11402                         prev->next = lp;
11403                 } while (readtoken() == TPIPE);
11404                 lp->next = NULL;
11405                 n1 = pipenode;
11406         }
11407         tokpushback = 1;
11408         if (negate) {
11409                 n2 = stzalloc(sizeof(struct nnot));
11410                 n2->type = NNOT;
11411                 n2->nnot.com = n1;
11412                 return n2;
11413         }
11414         return n1;
11415 }
11416
11417 static union node *
11418 makename(void)
11419 {
11420         union node *n;
11421
11422         n = stzalloc(sizeof(struct narg));
11423         n->type = NARG;
11424         /*n->narg.next = NULL; - stzalloc did it */
11425         n->narg.text = wordtext;
11426         n->narg.backquote = backquotelist;
11427         return n;
11428 }
11429
11430 static void
11431 fixredir(union node *n, const char *text, int err)
11432 {
11433         int fd;
11434
11435         TRACE(("Fix redir %s %d\n", text, err));
11436         if (!err)
11437                 n->ndup.vname = NULL;
11438
11439         fd = bb_strtou(text, NULL, 10);
11440         if (!errno && fd >= 0)
11441                 n->ndup.dupfd = fd;
11442         else if (LONE_DASH(text))
11443                 n->ndup.dupfd = -1;
11444         else {
11445                 if (err)
11446                         raise_error_syntax("bad fd number");
11447                 n->ndup.vname = makename();
11448         }
11449 }
11450
11451 static void
11452 parsefname(void)
11453 {
11454         union node *n = redirnode;
11455
11456         if (n->type == NHERE)
11457                 checkkwd = CHKEOFMARK;
11458         if (readtoken() != TWORD)
11459                 raise_error_unexpected_syntax(-1);
11460         if (n->type == NHERE) {
11461                 struct heredoc *here = heredoc;
11462                 struct heredoc *p;
11463
11464                 if (quoteflag == 0)
11465                         n->type = NXHERE;
11466                 TRACE(("Here document %d\n", n->type));
11467                 rmescapes(wordtext, 0, NULL);
11468                 here->eofmark = wordtext;
11469                 here->next = NULL;
11470                 if (heredoclist == NULL)
11471                         heredoclist = here;
11472                 else {
11473                         for (p = heredoclist; p->next; p = p->next)
11474                                 continue;
11475                         p->next = here;
11476                 }
11477         } else if (n->type == NTOFD || n->type == NFROMFD) {
11478                 fixredir(n, wordtext, 0);
11479         } else {
11480                 n->nfile.fname = makename();
11481         }
11482 }
11483
11484 static union node *
11485 simplecmd(void)
11486 {
11487         union node *args, **app;
11488         union node *n = NULL;
11489         union node *vars, **vpp;
11490         union node **rpp, *redir;
11491         int savecheckkwd;
11492         int savelinno;
11493 #if BASH_TEST2
11494         smallint double_brackets_flag = 0;
11495 #endif
11496         IF_BASH_FUNCTION(smallint function_flag = 0;)
11497
11498         args = NULL;
11499         app = &args;
11500         vars = NULL;
11501         vpp = &vars;
11502         redir = NULL;
11503         rpp = &redir;
11504
11505         savecheckkwd = CHKALIAS;
11506         savelinno = g_parsefile->linno;
11507         for (;;) {
11508                 int t;
11509                 checkkwd = savecheckkwd;
11510                 t = readtoken();
11511                 switch (t) {
11512 #if BASH_FUNCTION
11513                 case TFUNCTION:
11514                         if (peektoken() != TWORD)
11515                                 raise_error_unexpected_syntax(TWORD);
11516                         function_flag = 1;
11517                         break;
11518 #endif
11519 #if BASH_TEST2
11520                 case TAND: /* "&&" */
11521                 case TOR: /* "||" */
11522                         if (!double_brackets_flag) {
11523                                 tokpushback = 1;
11524                                 goto out;
11525                         }
11526                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11527 #endif
11528                 case TWORD:
11529                         n = stzalloc(sizeof(struct narg));
11530                         n->type = NARG;
11531                         /*n->narg.next = NULL; - stzalloc did it */
11532                         n->narg.text = wordtext;
11533 #if BASH_TEST2
11534                         if (strcmp("[[", wordtext) == 0)
11535                                 double_brackets_flag = 1;
11536                         else if (strcmp("]]", wordtext) == 0)
11537                                 double_brackets_flag = 0;
11538 #endif
11539                         n->narg.backquote = backquotelist;
11540                         if (savecheckkwd && isassignment(wordtext)) {
11541                                 *vpp = n;
11542                                 vpp = &n->narg.next;
11543                         } else {
11544                                 *app = n;
11545                                 app = &n->narg.next;
11546                                 savecheckkwd = 0;
11547                         }
11548 #if BASH_FUNCTION
11549                         if (function_flag) {
11550                                 checkkwd = CHKNL | CHKKWD;
11551                                 switch (peektoken()) {
11552                                 case TBEGIN:
11553                                 case TIF:
11554                                 case TCASE:
11555                                 case TUNTIL:
11556                                 case TWHILE:
11557                                 case TFOR:
11558                                         goto do_func;
11559                                 case TLP:
11560                                         function_flag = 0;
11561                                         break;
11562                                 case TWORD:
11563                                         if (strcmp("[[", wordtext) == 0)
11564                                                 goto do_func;
11565                                         /* fall through */
11566                                 default:
11567                                         raise_error_unexpected_syntax(-1);
11568                                 }
11569                         }
11570 #endif
11571                         break;
11572                 case TREDIR:
11573                         *rpp = n = redirnode;
11574                         rpp = &n->nfile.next;
11575                         parsefname();   /* read name of redirection file */
11576                         break;
11577                 case TLP:
11578  IF_BASH_FUNCTION(do_func:)
11579                         if (args && app == &args->narg.next
11580                          && !vars && !redir
11581                         ) {
11582                                 struct builtincmd *bcmd;
11583                                 const char *name;
11584
11585                                 /* We have a function */
11586                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11587                                         raise_error_unexpected_syntax(TRP);
11588                                 name = n->narg.text;
11589                                 if (!goodname(name)
11590                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11591                                 ) {
11592                                         raise_error_syntax("bad function name");
11593                                 }
11594                                 n->type = NDEFUN;
11595                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11596                                 n->ndefun.text = n->narg.text;
11597                                 n->ndefun.linno = g_parsefile->linno;
11598                                 n->ndefun.body = parse_command();
11599                                 return n;
11600                         }
11601                         IF_BASH_FUNCTION(function_flag = 0;)
11602                         /* fall through */
11603                 default:
11604                         tokpushback = 1;
11605                         goto out;
11606                 }
11607         }
11608  out:
11609         *app = NULL;
11610         *vpp = NULL;
11611         *rpp = NULL;
11612         n = stzalloc(sizeof(struct ncmd));
11613         n->type = NCMD;
11614         n->ncmd.linno = savelinno;
11615         n->ncmd.args = args;
11616         n->ncmd.assign = vars;
11617         n->ncmd.redirect = redir;
11618         return n;
11619 }
11620
11621 static union node *
11622 parse_command(void)
11623 {
11624         union node *n1, *n2;
11625         union node *ap, **app;
11626         union node *cp, **cpp;
11627         union node *redir, **rpp;
11628         union node **rpp2;
11629         int t;
11630         int savelinno;
11631
11632         redir = NULL;
11633         rpp2 = &redir;
11634
11635         savelinno = g_parsefile->linno;
11636
11637         switch (readtoken()) {
11638         default:
11639                 raise_error_unexpected_syntax(-1);
11640                 /* NOTREACHED */
11641         case TIF:
11642                 n1 = stzalloc(sizeof(struct nif));
11643                 n1->type = NIF;
11644                 n1->nif.test = list(0);
11645                 if (readtoken() != TTHEN)
11646                         raise_error_unexpected_syntax(TTHEN);
11647                 n1->nif.ifpart = list(0);
11648                 n2 = n1;
11649                 while (readtoken() == TELIF) {
11650                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11651                         n2 = n2->nif.elsepart;
11652                         n2->type = NIF;
11653                         n2->nif.test = list(0);
11654                         if (readtoken() != TTHEN)
11655                                 raise_error_unexpected_syntax(TTHEN);
11656                         n2->nif.ifpart = list(0);
11657                 }
11658                 if (lasttoken == TELSE)
11659                         n2->nif.elsepart = list(0);
11660                 else {
11661                         n2->nif.elsepart = NULL;
11662                         tokpushback = 1;
11663                 }
11664                 t = TFI;
11665                 break;
11666         case TWHILE:
11667         case TUNTIL: {
11668                 int got;
11669                 n1 = stzalloc(sizeof(struct nbinary));
11670                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11671                 n1->nbinary.ch1 = list(0);
11672                 got = readtoken();
11673                 if (got != TDO) {
11674                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11675                                         got == TWORD ? wordtext : ""));
11676                         raise_error_unexpected_syntax(TDO);
11677                 }
11678                 n1->nbinary.ch2 = list(0);
11679                 t = TDONE;
11680                 break;
11681         }
11682         case TFOR:
11683                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11684                         raise_error_syntax("bad for loop variable");
11685                 n1 = stzalloc(sizeof(struct nfor));
11686                 n1->type = NFOR;
11687                 n1->nfor.linno = savelinno;
11688                 n1->nfor.var = wordtext;
11689                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11690                 if (readtoken() == TIN) {
11691                         app = &ap;
11692                         while (readtoken() == TWORD) {
11693                                 n2 = stzalloc(sizeof(struct narg));
11694                                 n2->type = NARG;
11695                                 /*n2->narg.next = NULL; - stzalloc did it */
11696                                 n2->narg.text = wordtext;
11697                                 n2->narg.backquote = backquotelist;
11698                                 *app = n2;
11699                                 app = &n2->narg.next;
11700                         }
11701                         *app = NULL;
11702                         n1->nfor.args = ap;
11703                         if (lasttoken != TNL && lasttoken != TSEMI)
11704                                 raise_error_unexpected_syntax(-1);
11705                 } else {
11706                         n2 = stzalloc(sizeof(struct narg));
11707                         n2->type = NARG;
11708                         /*n2->narg.next = NULL; - stzalloc did it */
11709                         n2->narg.text = (char *)dolatstr;
11710                         /*n2->narg.backquote = NULL;*/
11711                         n1->nfor.args = n2;
11712                         /*
11713                          * Newline or semicolon here is optional (but note
11714                          * that the original Bourne shell only allowed NL).
11715                          */
11716                         if (lasttoken != TSEMI)
11717                                 tokpushback = 1;
11718                 }
11719                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11720                 if (readtoken() != TDO)
11721                         raise_error_unexpected_syntax(TDO);
11722                 n1->nfor.body = list(0);
11723                 t = TDONE;
11724                 break;
11725         case TCASE:
11726                 n1 = stzalloc(sizeof(struct ncase));
11727                 n1->type = NCASE;
11728                 n1->ncase.linno = savelinno;
11729                 if (readtoken() != TWORD)
11730                         raise_error_unexpected_syntax(TWORD);
11731                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11732                 n2->type = NARG;
11733                 /*n2->narg.next = NULL; - stzalloc did it */
11734                 n2->narg.text = wordtext;
11735                 n2->narg.backquote = backquotelist;
11736                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11737                 if (readtoken() != TIN)
11738                         raise_error_unexpected_syntax(TIN);
11739                 cpp = &n1->ncase.cases;
11740  next_case:
11741                 checkkwd = CHKNL | CHKKWD;
11742                 t = readtoken();
11743                 while (t != TESAC) {
11744                         if (lasttoken == TLP)
11745                                 readtoken();
11746                         *cpp = cp = stzalloc(sizeof(struct nclist));
11747                         cp->type = NCLIST;
11748                         app = &cp->nclist.pattern;
11749                         for (;;) {
11750                                 *app = ap = stzalloc(sizeof(struct narg));
11751                                 ap->type = NARG;
11752                                 /*ap->narg.next = NULL; - stzalloc did it */
11753                                 ap->narg.text = wordtext;
11754                                 ap->narg.backquote = backquotelist;
11755                                 if (readtoken() != TPIPE)
11756                                         break;
11757                                 app = &ap->narg.next;
11758                                 readtoken();
11759                         }
11760                         //ap->narg.next = NULL;
11761                         if (lasttoken != TRP)
11762                                 raise_error_unexpected_syntax(TRP);
11763                         cp->nclist.body = list(2);
11764
11765                         cpp = &cp->nclist.next;
11766
11767                         checkkwd = CHKNL | CHKKWD;
11768                         t = readtoken();
11769                         if (t != TESAC) {
11770                                 if (t != TENDCASE)
11771                                         raise_error_unexpected_syntax(TENDCASE);
11772                                 goto next_case;
11773                         }
11774                 }
11775                 *cpp = NULL;
11776                 goto redir;
11777         case TLP:
11778                 n1 = stzalloc(sizeof(struct nredir));
11779                 n1->type = NSUBSHELL;
11780                 n1->nredir.linno = savelinno;
11781                 n1->nredir.n = list(0);
11782                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11783                 t = TRP;
11784                 break;
11785         case TBEGIN:
11786                 n1 = list(0);
11787                 t = TEND;
11788                 break;
11789         IF_BASH_FUNCTION(case TFUNCTION:)
11790         case TWORD:
11791         case TREDIR:
11792                 tokpushback = 1;
11793                 return simplecmd();
11794         }
11795
11796         if (readtoken() != t)
11797                 raise_error_unexpected_syntax(t);
11798
11799  redir:
11800         /* Now check for redirection which may follow command */
11801         checkkwd = CHKKWD | CHKALIAS;
11802         rpp = rpp2;
11803         while (readtoken() == TREDIR) {
11804                 *rpp = n2 = redirnode;
11805                 rpp = &n2->nfile.next;
11806                 parsefname();
11807         }
11808         tokpushback = 1;
11809         *rpp = NULL;
11810         if (redir) {
11811                 if (n1->type != NSUBSHELL) {
11812                         n2 = stzalloc(sizeof(struct nredir));
11813                         n2->type = NREDIR;
11814                         n2->nredir.linno = savelinno;
11815                         n2->nredir.n = n1;
11816                         n1 = n2;
11817                 }
11818                 n1->nredir.redirect = redir;
11819         }
11820         return n1;
11821 }
11822
11823 #if BASH_DOLLAR_SQUOTE
11824 static int
11825 decode_dollar_squote(void)
11826 {
11827         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11828         int c, cnt;
11829         char *p;
11830         char buf[4];
11831
11832         c = pgetc();
11833         p = strchr(C_escapes, c);
11834         if (p) {
11835                 buf[0] = c;
11836                 p = buf;
11837                 cnt = 3;
11838                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11839                         do {
11840                                 c = pgetc();
11841                                 *++p = c;
11842                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11843                         pungetc();
11844                 } else if (c == 'x') { /* \xHH */
11845                         do {
11846                                 c = pgetc();
11847                                 *++p = c;
11848                         } while (isxdigit(c) && --cnt);
11849                         pungetc();
11850                         if (cnt == 3) { /* \x but next char is "bad" */
11851                                 c = 'x';
11852                                 goto unrecognized;
11853                         }
11854                 } else { /* simple seq like \\ or \t */
11855                         p++;
11856                 }
11857                 *p = '\0';
11858                 p = buf;
11859                 c = bb_process_escape_sequence((void*)&p);
11860         } else { /* unrecognized "\z": print both chars unless ' or " */
11861                 if (c != '\'' && c != '"') {
11862  unrecognized:
11863                         c |= 0x100; /* "please encode \, then me" */
11864                 }
11865         }
11866         return c;
11867 }
11868 #endif
11869
11870 /* Used by expandstr to get here-doc like behaviour. */
11871 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11872
11873 static ALWAYS_INLINE int
11874 realeofmark(const char *eofmark)
11875 {
11876         return eofmark && eofmark != FAKEEOFMARK;
11877 }
11878
11879 /*
11880  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11881  * is not NULL, read a here document.  In the latter case, eofmark is the
11882  * word which marks the end of the document and striptabs is true if
11883  * leading tabs should be stripped from the document.  The argument c
11884  * is the first character of the input token or document.
11885  *
11886  * Because C does not have internal subroutines, I have simulated them
11887  * using goto's to implement the subroutine linkage.  The following macros
11888  * will run code that appears at the end of readtoken1.
11889  */
11890 #define CHECKEND()      {goto checkend; checkend_return:;}
11891 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11892 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11893 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11894 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11895 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11896 static int
11897 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11898 {
11899         /* NB: syntax parameter fits into smallint */
11900         /* c parameter is an unsigned char or PEOF or PEOA */
11901         char *out;
11902         size_t len;
11903         struct nodelist *bqlist;
11904         smallint quotef;
11905         smallint dblquote;
11906         smallint oldstyle;
11907         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11908         smallint pssyntax;   /* we are expanding a prompt string */
11909         int varnest;         /* levels of variables expansion */
11910         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11911         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11912         int dqvarnest;       /* levels of variables expansion within double quotes */
11913         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11914
11915         bqlist = NULL;
11916         quotef = 0;
11917         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11918 #if ENABLE_ASH_EXPAND_PRMT
11919         pssyntax = (syntax == PSSYNTAX);
11920         if (pssyntax)
11921                 syntax = DQSYNTAX;
11922 #else
11923         pssyntax = 0; /* constant */
11924 #endif
11925         dblquote = (syntax == DQSYNTAX);
11926         varnest = 0;
11927         IF_FEATURE_SH_MATH(arinest = 0;)
11928         IF_FEATURE_SH_MATH(parenlevel = 0;)
11929         dqvarnest = 0;
11930
11931         STARTSTACKSTR(out);
11932  loop:
11933         /* For each line, until end of word */
11934         CHECKEND();     /* set c to PEOF if at end of here document */
11935         for (;;) {      /* until end of line or end of word */
11936                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11937                 switch (SIT(c, syntax)) {
11938                 case CNL:       /* '\n' */
11939                         if (syntax == BASESYNTAX)
11940                                 goto endword;   /* exit outer loop */
11941                         USTPUTC(c, out);
11942                         nlprompt();
11943                         c = pgetc();
11944                         goto loop;              /* continue outer loop */
11945                 case CWORD:
11946                         USTPUTC(c, out);
11947                         break;
11948                 case CCTL:
11949 #if BASH_DOLLAR_SQUOTE
11950                         if (c == '\\' && bash_dollar_squote) {
11951                                 c = decode_dollar_squote();
11952                                 if (c == '\0') {
11953                                         /* skip $'\000', $'\x00' (like bash) */
11954                                         break;
11955                                 }
11956                                 if (c & 0x100) {
11957                                         /* Unknown escape. Encode as '\z' */
11958                                         c = (unsigned char)c;
11959                                         if (eofmark == NULL || dblquote)
11960                                                 USTPUTC(CTLESC, out);
11961                                         USTPUTC('\\', out);
11962                                 }
11963                         }
11964 #endif
11965                         if (eofmark == NULL || dblquote)
11966                                 USTPUTC(CTLESC, out);
11967                         USTPUTC(c, out);
11968                         break;
11969                 case CBACK:     /* backslash */
11970                         c = pgetc_without_PEOA();
11971                         if (c == PEOF) {
11972                                 USTPUTC(CTLESC, out);
11973                                 USTPUTC('\\', out);
11974                                 pungetc();
11975                         } else if (c == '\n') {
11976                                 nlprompt();
11977                         } else {
11978                                 if (pssyntax && c == '$') {
11979                                         USTPUTC(CTLESC, out);
11980                                         USTPUTC('\\', out);
11981                                 }
11982                                 /* Backslash is retained if we are in "str" and next char isn't special */
11983                                 if (dblquote
11984                                  && c != '\\'
11985                                  && c != '`'
11986                                  && c != '$'
11987                                  && (c != '"' || eofmark != NULL)
11988                                 ) {
11989                                         USTPUTC('\\', out);
11990                                 }
11991                                 USTPUTC(CTLESC, out);
11992                                 USTPUTC(c, out);
11993                                 quotef = 1;
11994                         }
11995                         break;
11996                 case CSQUOTE:
11997                         syntax = SQSYNTAX;
11998  quotemark:
11999                         if (eofmark == NULL) {
12000                                 USTPUTC(CTLQUOTEMARK, out);
12001                         }
12002                         break;
12003                 case CDQUOTE:
12004                         syntax = DQSYNTAX;
12005                         dblquote = 1;
12006                         goto quotemark;
12007                 case CENDQUOTE:
12008                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12009                         if (eofmark != NULL && varnest == 0) {
12010                                 USTPUTC(c, out);
12011                         } else {
12012                                 if (dqvarnest == 0) {
12013                                         syntax = BASESYNTAX;
12014                                         dblquote = 0;
12015                                 }
12016                                 quotef = 1;
12017                                 goto quotemark;
12018                         }
12019                         break;
12020                 case CVAR:      /* '$' */
12021                         PARSESUB();             /* parse substitution */
12022                         break;
12023                 case CENDVAR:   /* '}' */
12024                         if (varnest > 0) {
12025                                 varnest--;
12026                                 if (dqvarnest > 0) {
12027                                         dqvarnest--;
12028                                 }
12029                                 c = CTLENDVAR;
12030                         }
12031                         USTPUTC(c, out);
12032                         break;
12033 #if ENABLE_FEATURE_SH_MATH
12034                 case CLP:       /* '(' in arithmetic */
12035                         parenlevel++;
12036                         USTPUTC(c, out);
12037                         break;
12038                 case CRP:       /* ')' in arithmetic */
12039                         if (parenlevel > 0) {
12040                                 parenlevel--;
12041                         } else {
12042                                 if (pgetc_eatbnl() == ')') {
12043                                         c = CTLENDARI;
12044                                         if (--arinest == 0) {
12045                                                 syntax = prevsyntax;
12046                                         }
12047                                 } else {
12048                                         /*
12049                                          * unbalanced parens
12050                                          * (don't 2nd guess - no error)
12051                                          */
12052                                         pungetc();
12053                                 }
12054                         }
12055                         USTPUTC(c, out);
12056                         break;
12057 #endif
12058                 case CBQUOTE:   /* '`' */
12059                         PARSEBACKQOLD();
12060                         break;
12061                 case CENDFILE:
12062                         goto endword;           /* exit outer loop */
12063                 case CIGN:
12064                         break;
12065                 default:
12066                         if (varnest == 0) {
12067 #if BASH_REDIR_OUTPUT
12068                                 if (c == '&') {
12069 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12070                                         if (pgetc() == '>')
12071                                                 c = 0x100 + '>'; /* flag &> */
12072                                         pungetc();
12073                                 }
12074 #endif
12075                                 goto endword;   /* exit outer loop */
12076                         }
12077                         IF_ASH_ALIAS(if (c != PEOA))
12078                                 USTPUTC(c, out);
12079                 }
12080                 c = pgetc();
12081         } /* for (;;) */
12082  endword:
12083
12084 #if ENABLE_FEATURE_SH_MATH
12085         if (syntax == ARISYNTAX)
12086                 raise_error_syntax("missing '))'");
12087 #endif
12088         if (syntax != BASESYNTAX && eofmark == NULL)
12089                 raise_error_syntax("unterminated quoted string");
12090         if (varnest != 0) {
12091                 /* { */
12092                 raise_error_syntax("missing '}'");
12093         }
12094         USTPUTC('\0', out);
12095         len = out - (char *)stackblock();
12096         out = stackblock();
12097         if (eofmark == NULL) {
12098                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12099                  && quotef == 0
12100                 ) {
12101                         if (isdigit_str9(out)) {
12102                                 PARSEREDIR(); /* passed as params: out, c */
12103                                 lasttoken = TREDIR;
12104                                 return lasttoken;
12105                         }
12106                         /* else: non-number X seen, interpret it
12107                          * as "NNNX>file" = "NNNX >file" */
12108                 }
12109                 pungetc();
12110         }
12111         quoteflag = quotef;
12112         backquotelist = bqlist;
12113         grabstackblock(len);
12114         wordtext = out;
12115         lasttoken = TWORD;
12116         return lasttoken;
12117 /* end of readtoken routine */
12118
12119 /*
12120  * Check to see whether we are at the end of the here document.  When this
12121  * is called, c is set to the first character of the next input line.  If
12122  * we are at the end of the here document, this routine sets the c to PEOF.
12123  */
12124 checkend: {
12125         if (realeofmark(eofmark)) {
12126                 int markloc;
12127                 char *p;
12128
12129 #if ENABLE_ASH_ALIAS
12130                 if (c == PEOA)
12131                         c = pgetc_without_PEOA();
12132 #endif
12133                 if (striptabs) {
12134                         while (c == '\t') {
12135                                 c = pgetc_without_PEOA();
12136                         }
12137                 }
12138
12139                 markloc = out - (char *)stackblock();
12140                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12141                         if (c != *p)
12142                                 goto more_heredoc;
12143
12144                         c = pgetc_without_PEOA();
12145                 }
12146
12147                 if (c == '\n' || c == PEOF) {
12148                         c = PEOF;
12149                         g_parsefile->linno++;
12150                         needprompt = doprompt;
12151                 } else {
12152                         int len_here;
12153
12154  more_heredoc:
12155                         p = (char *)stackblock() + markloc + 1;
12156                         len_here = out - p;
12157
12158                         if (len_here) {
12159                                 len_here -= (c >= PEOF);
12160                                 c = p[-1];
12161
12162                                 if (len_here) {
12163                                         char *str;
12164
12165                                         str = alloca(len_here + 1);
12166                                         *(char *)mempcpy(str, p, len_here) = '\0';
12167
12168                                         pushstring(str, NULL);
12169                                 }
12170                         }
12171                 }
12172
12173                 STADJUST((char *)stackblock() + markloc - out, out);
12174         }
12175         goto checkend_return;
12176 }
12177
12178 /*
12179  * Parse a redirection operator.  The variable "out" points to a string
12180  * specifying the fd to be redirected.  The variable "c" contains the
12181  * first character of the redirection operator.
12182  */
12183 parseredir: {
12184         /* out is already checked to be a valid number or "" */
12185         int fd = (*out == '\0' ? -1 : atoi(out));
12186         union node *np;
12187
12188         np = stzalloc(sizeof(struct nfile));
12189         if (c == '>') {
12190                 np->nfile.fd = 1;
12191                 c = pgetc();
12192                 if (c == '>')
12193                         np->type = NAPPEND;
12194                 else if (c == '|')
12195                         np->type = NCLOBBER;
12196                 else if (c == '&')
12197                         np->type = NTOFD;
12198                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12199                 else {
12200                         np->type = NTO;
12201                         pungetc();
12202                 }
12203         }
12204 #if BASH_REDIR_OUTPUT
12205         else if (c == 0x100 + '>') { /* this flags &> redirection */
12206                 np->nfile.fd = 1;
12207                 pgetc(); /* this is '>', no need to check */
12208                 np->type = NTO2;
12209         }
12210 #endif
12211         else { /* c == '<' */
12212                 /*np->nfile.fd = 0; - stzalloc did it */
12213                 c = pgetc();
12214                 switch (c) {
12215                 case '<':
12216                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12217                                 np = stzalloc(sizeof(struct nhere));
12218                                 /*np->nfile.fd = 0; - stzalloc did it */
12219                         }
12220                         np->type = NHERE;
12221                         heredoc = stzalloc(sizeof(struct heredoc));
12222                         heredoc->here = np;
12223                         c = pgetc();
12224                         if (c == '-') {
12225                                 heredoc->striptabs = 1;
12226                         } else {
12227                                 /*heredoc->striptabs = 0; - stzalloc did it */
12228                                 pungetc();
12229                         }
12230                         break;
12231
12232                 case '&':
12233                         np->type = NFROMFD;
12234                         break;
12235
12236                 case '>':
12237                         np->type = NFROMTO;
12238                         break;
12239
12240                 default:
12241                         np->type = NFROM;
12242                         pungetc();
12243                         break;
12244                 }
12245         }
12246         if (fd >= 0)
12247                 np->nfile.fd = fd;
12248         redirnode = np;
12249         goto parseredir_return;
12250 }
12251
12252 /*
12253  * Parse a substitution.  At this point, we have read the dollar sign
12254  * and nothing else.
12255  */
12256
12257 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12258  * (assuming ascii char codes, as the original implementation did) */
12259 #define is_special(c) \
12260         (((unsigned)(c) - 33 < 32) \
12261                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12262 parsesub: {
12263         unsigned char subtype;
12264         int typeloc;
12265
12266         c = pgetc_eatbnl();
12267         if ((checkkwd & CHKEOFMARK)
12268          || c > 255 /* PEOA or PEOF */
12269          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12270         ) {
12271 #if BASH_DOLLAR_SQUOTE
12272                 if (syntax != DQSYNTAX && c == '\'')
12273                         bash_dollar_squote = 1;
12274                 else
12275 #endif
12276                         USTPUTC('$', out);
12277                 pungetc();
12278         } else if (c == '(') {
12279                 /* $(command) or $((arith)) */
12280                 if (pgetc_eatbnl() == '(') {
12281 #if ENABLE_FEATURE_SH_MATH
12282                         PARSEARITH();
12283 #else
12284                         raise_error_syntax("support for $((arith)) is disabled");
12285 #endif
12286                 } else {
12287                         pungetc();
12288                         PARSEBACKQNEW();
12289                 }
12290         } else {
12291                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12292                 USTPUTC(CTLVAR, out);
12293                 typeloc = out - (char *)stackblock();
12294                 STADJUST(1, out);
12295                 subtype = VSNORMAL;
12296                 if (c == '{') {
12297                         c = pgetc_eatbnl();
12298                         subtype = 0;
12299                 }
12300  varname:
12301                 if (is_name(c)) {
12302                         /* $[{[#]]NAME[}] */
12303                         do {
12304                                 STPUTC(c, out);
12305                                 c = pgetc_eatbnl();
12306                         } while (is_in_name(c));
12307                 } else if (isdigit(c)) {
12308                         /* $[{[#]]NUM[}] */
12309                         do {
12310                                 STPUTC(c, out);
12311                                 c = pgetc_eatbnl();
12312                         } while (isdigit(c));
12313                 } else {
12314                         /* $[{[#]]<specialchar>[}] */
12315                         int cc = c;
12316
12317                         c = pgetc_eatbnl();
12318                         if (!subtype && cc == '#') {
12319                                 subtype = VSLENGTH;
12320                                 if (c == '_' || isalnum(c))
12321                                         goto varname;
12322                                 cc = c;
12323                                 c = pgetc_eatbnl();
12324                                 if (cc == '}' || c != '}') {
12325                                         pungetc();
12326                                         subtype = 0;
12327                                         c = cc;
12328                                         cc = '#';
12329                                 }
12330                         }
12331
12332                         if (!is_special(cc)) {
12333                                 if (subtype == VSLENGTH)
12334                                         subtype = 0;
12335                                 goto badsub;
12336                         }
12337
12338                         USTPUTC(cc, out);
12339                 }
12340
12341                 if (c != '}' && subtype == VSLENGTH) {
12342                         /* ${#VAR didn't end with } */
12343                         goto badsub;
12344                 }
12345
12346                 if (subtype == 0) {
12347                         static const char types[] ALIGN1 = "}-+?=";
12348                         /* ${VAR...} but not $VAR or ${#VAR} */
12349                         /* c == first char after VAR */
12350                         switch (c) {
12351                         case ':':
12352                                 c = pgetc_eatbnl();
12353 #if BASH_SUBSTR
12354                                 /* This check is only needed to not misinterpret
12355                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12356                                  * constructs.
12357                                  */
12358                                 if (!strchr(types, c)) {
12359                                         subtype = VSSUBSTR;
12360                                         pungetc();
12361                                         break; /* "goto badsub" is bigger (!) */
12362                                 }
12363 #endif
12364                                 subtype = VSNUL;
12365                                 /*FALLTHROUGH*/
12366                         default: {
12367                                 const char *p = strchr(types, c);
12368                                 if (p == NULL)
12369                                         break;
12370                                 subtype |= p - types + VSNORMAL;
12371                                 break;
12372                         }
12373                         case '%':
12374                         case '#': {
12375                                 int cc = c;
12376                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12377                                 c = pgetc_eatbnl();
12378                                 if (c != cc)
12379                                         goto badsub;
12380                                 subtype++;
12381                                 break;
12382                         }
12383 #if BASH_PATTERN_SUBST
12384                         case '/':
12385                                 /* ${v/[/]pattern/repl} */
12386 //TODO: encode pattern and repl separately.
12387 // Currently ${v/$var_with_slash/repl} is horribly broken
12388                                 subtype = VSREPLACE;
12389                                 c = pgetc_eatbnl();
12390                                 if (c != '/')
12391                                         goto badsub;
12392                                 subtype++; /* VSREPLACEALL */
12393                                 break;
12394 #endif
12395                         }
12396                 } else {
12397  badsub:
12398                         pungetc();
12399                 }
12400                 ((unsigned char *)stackblock())[typeloc] = subtype;
12401                 if (subtype != VSNORMAL) {
12402                         varnest++;
12403                         if (dblquote)
12404                                 dqvarnest++;
12405                 }
12406                 STPUTC('=', out);
12407         }
12408         goto parsesub_return;
12409 }
12410
12411 /*
12412  * Called to parse command substitutions.  Newstyle is set if the command
12413  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12414  * list of commands (passed by reference), and savelen is the number of
12415  * characters on the top of the stack which must be preserved.
12416  */
12417 parsebackq: {
12418         struct nodelist **nlpp;
12419         union node *n;
12420         char *str;
12421         size_t savelen;
12422         smallint saveprompt = 0;
12423
12424         str = NULL;
12425         savelen = out - (char *)stackblock();
12426         if (savelen > 0) {
12427                 /*
12428                  * FIXME: this can allocate very large block on stack and SEGV.
12429                  * Example:
12430                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12431                  * allocates 100kb for every command subst. With about
12432                  * a hundred command substitutions stack overflows.
12433                  * With larger prepended string, SEGV happens sooner.
12434                  */
12435                 str = alloca(savelen);
12436                 memcpy(str, stackblock(), savelen);
12437         }
12438
12439         if (oldstyle) {
12440                 /* We must read until the closing backquote, giving special
12441                  * treatment to some slashes, and then push the string and
12442                  * reread it as input, interpreting it normally.
12443                  */
12444                 char *pout;
12445                 size_t psavelen;
12446                 char *pstr;
12447
12448                 STARTSTACKSTR(pout);
12449                 for (;;) {
12450                         int pc;
12451
12452                         setprompt_if(needprompt, 2);
12453                         pc = pgetc();
12454                         switch (pc) {
12455                         case '`':
12456                                 goto done;
12457
12458                         case '\\':
12459                                 pc = pgetc();
12460                                 if (pc == '\n') {
12461                                         nlprompt();
12462                                         /*
12463                                          * If eating a newline, avoid putting
12464                                          * the newline into the new character
12465                                          * stream (via the STPUTC after the
12466                                          * switch).
12467                                          */
12468                                         continue;
12469                                 }
12470                                 if (pc != '\\' && pc != '`' && pc != '$'
12471                                  && (!dblquote || pc != '"')
12472                                 ) {
12473                                         STPUTC('\\', pout);
12474                                 }
12475                                 if (pc <= 255 /* not PEOA or PEOF */) {
12476                                         break;
12477                                 }
12478                                 /* fall through */
12479
12480                         case PEOF:
12481                         IF_ASH_ALIAS(case PEOA:)
12482                                 raise_error_syntax("EOF in backquote substitution");
12483
12484                         case '\n':
12485                                 nlnoprompt();
12486                                 break;
12487
12488                         default:
12489                                 break;
12490                         }
12491                         STPUTC(pc, pout);
12492                 }
12493  done:
12494                 STPUTC('\0', pout);
12495                 psavelen = pout - (char *)stackblock();
12496                 if (psavelen > 0) {
12497                         pstr = grabstackstr(pout);
12498                         setinputstring(pstr);
12499                 }
12500         }
12501         nlpp = &bqlist;
12502         while (*nlpp)
12503                 nlpp = &(*nlpp)->next;
12504         *nlpp = stzalloc(sizeof(**nlpp));
12505         /* (*nlpp)->next = NULL; - stzalloc did it */
12506
12507         if (oldstyle) {
12508                 saveprompt = doprompt;
12509                 doprompt = 0;
12510         }
12511
12512         n = list(2);
12513
12514         if (oldstyle)
12515                 doprompt = saveprompt;
12516         else if (readtoken() != TRP)
12517                 raise_error_unexpected_syntax(TRP);
12518
12519         (*nlpp)->n = n;
12520         if (oldstyle) {
12521                 /*
12522                  * Start reading from old file again, ignoring any pushed back
12523                  * tokens left from the backquote parsing
12524                  */
12525                 popfile();
12526                 tokpushback = 0;
12527         }
12528         while (stackblocksize() <= savelen)
12529                 growstackblock();
12530         STARTSTACKSTR(out);
12531         if (str) {
12532                 memcpy(out, str, savelen);
12533                 STADJUST(savelen, out);
12534         }
12535         USTPUTC(CTLBACKQ, out);
12536         if (oldstyle)
12537                 goto parsebackq_oldreturn;
12538         goto parsebackq_newreturn;
12539 }
12540
12541 #if ENABLE_FEATURE_SH_MATH
12542 /*
12543  * Parse an arithmetic expansion (indicate start of one and set state)
12544  */
12545 parsearith: {
12546         if (++arinest == 1) {
12547                 prevsyntax = syntax;
12548                 syntax = ARISYNTAX;
12549         }
12550         USTPUTC(CTLARI, out);
12551         goto parsearith_return;
12552 }
12553 #endif
12554 } /* end of readtoken */
12555
12556 /*
12557  * Read the next input token.
12558  * If the token is a word, we set backquotelist to the list of cmds in
12559  *      backquotes.  We set quoteflag to true if any part of the word was
12560  *      quoted.
12561  * If the token is TREDIR, then we set redirnode to a structure containing
12562  *      the redirection.
12563  *
12564  * [Change comment:  here documents and internal procedures]
12565  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12566  *  word parsing code into a separate routine.  In this case, readtoken
12567  *  doesn't need to have any internal procedures, but parseword does.
12568  *  We could also make parseoperator in essence the main routine, and
12569  *  have parseword (readtoken1?) handle both words and redirection.]
12570  */
12571 #define NEW_xxreadtoken
12572 #ifdef NEW_xxreadtoken
12573 /* singles must be first! */
12574 static const char xxreadtoken_chars[7] ALIGN1 = {
12575         '\n', '(', ')', /* singles */
12576         '&', '|', ';',  /* doubles */
12577         0
12578 };
12579
12580 #define xxreadtoken_singles 3
12581 #define xxreadtoken_doubles 3
12582
12583 static const char xxreadtoken_tokens[] ALIGN1 = {
12584         TNL, TLP, TRP,          /* only single occurrence allowed */
12585         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12586         TEOF,                   /* corresponds to trailing nul */
12587         TAND, TOR, TENDCASE     /* if double occurrence */
12588 };
12589
12590 static int
12591 xxreadtoken(void)
12592 {
12593         int c;
12594
12595         if (tokpushback) {
12596                 tokpushback = 0;
12597                 return lasttoken;
12598         }
12599         setprompt_if(needprompt, 2);
12600         for (;;) {                      /* until token or start of word found */
12601                 c = pgetc();
12602                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12603                         continue;
12604
12605                 if (c == '#') {
12606                         while ((c = pgetc()) != '\n' && c != PEOF)
12607                                 continue;
12608                         pungetc();
12609                 } else if (c == '\\') {
12610                         if (pgetc() != '\n') {
12611                                 pungetc();
12612                                 break; /* return readtoken1(...) */
12613                         }
12614                         nlprompt();
12615                 } else {
12616                         const char *p;
12617
12618                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12619                         if (c != PEOF) {
12620                                 if (c == '\n') {
12621                                         nlnoprompt();
12622                                 }
12623
12624                                 p = strchr(xxreadtoken_chars, c);
12625                                 if (p == NULL)
12626                                         break; /* return readtoken1(...) */
12627
12628                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12629                                         int cc = pgetc();
12630                                         if (cc == c) {    /* double occurrence? */
12631                                                 p += xxreadtoken_doubles + 1;
12632                                         } else {
12633                                                 pungetc();
12634 #if BASH_REDIR_OUTPUT
12635                                                 if (c == '&' && cc == '>') /* &> */
12636                                                         break; /* return readtoken1(...) */
12637 #endif
12638                                         }
12639                                 }
12640                         }
12641                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12642                         return lasttoken;
12643                 }
12644         } /* for (;;) */
12645
12646         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12647 }
12648 #else /* old xxreadtoken */
12649 #define RETURN(token)   return lasttoken = token
12650 static int
12651 xxreadtoken(void)
12652 {
12653         int c;
12654
12655         if (tokpushback) {
12656                 tokpushback = 0;
12657                 return lasttoken;
12658         }
12659         setprompt_if(needprompt, 2);
12660         for (;;) {      /* until token or start of word found */
12661                 c = pgetc();
12662                 switch (c) {
12663                 case ' ': case '\t':
12664                 IF_ASH_ALIAS(case PEOA:)
12665                         continue;
12666                 case '#':
12667                         while ((c = pgetc()) != '\n' && c != PEOF)
12668                                 continue;
12669                         pungetc();
12670                         continue;
12671                 case '\\':
12672                         if (pgetc() == '\n') {
12673                                 nlprompt();
12674                                 continue;
12675                         }
12676                         pungetc();
12677                         goto breakloop;
12678                 case '\n':
12679                         nlnoprompt();
12680                         RETURN(TNL);
12681                 case PEOF:
12682                         RETURN(TEOF);
12683                 case '&':
12684                         if (pgetc() == '&')
12685                                 RETURN(TAND);
12686                         pungetc();
12687                         RETURN(TBACKGND);
12688                 case '|':
12689                         if (pgetc() == '|')
12690                                 RETURN(TOR);
12691                         pungetc();
12692                         RETURN(TPIPE);
12693                 case ';':
12694                         if (pgetc() == ';')
12695                                 RETURN(TENDCASE);
12696                         pungetc();
12697                         RETURN(TSEMI);
12698                 case '(':
12699                         RETURN(TLP);
12700                 case ')':
12701                         RETURN(TRP);
12702                 default:
12703                         goto breakloop;
12704                 }
12705         }
12706  breakloop:
12707         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12708 #undef RETURN
12709 }
12710 #endif /* old xxreadtoken */
12711
12712 static int
12713 readtoken(void)
12714 {
12715         int t;
12716         int kwd = checkkwd;
12717 #if DEBUG
12718         smallint alreadyseen = tokpushback;
12719 #endif
12720
12721 #if ENABLE_ASH_ALIAS
12722  top:
12723 #endif
12724
12725         t = xxreadtoken();
12726
12727         /*
12728          * eat newlines
12729          */
12730         if (kwd & CHKNL) {
12731                 while (t == TNL) {
12732                         parseheredoc();
12733                         t = xxreadtoken();
12734                 }
12735         }
12736
12737         if (t != TWORD || quoteflag) {
12738                 goto out;
12739         }
12740
12741         /*
12742          * check for keywords
12743          */
12744         if (kwd & CHKKWD) {
12745                 const char *const *pp;
12746
12747                 pp = findkwd(wordtext);
12748                 if (pp) {
12749                         lasttoken = t = pp - tokname_array;
12750                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12751                         goto out;
12752                 }
12753         }
12754
12755         if (checkkwd & CHKALIAS) {
12756 #if ENABLE_ASH_ALIAS
12757                 struct alias *ap;
12758                 ap = lookupalias(wordtext, 1);
12759                 if (ap != NULL) {
12760                         if (*ap->val) {
12761                                 pushstring(ap->val, ap);
12762                         }
12763                         goto top;
12764                 }
12765 #endif
12766         }
12767  out:
12768         checkkwd = 0;
12769 #if DEBUG
12770         if (!alreadyseen)
12771                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12772         else
12773                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12774 #endif
12775         return t;
12776 }
12777
12778 static int
12779 peektoken(void)
12780 {
12781         int t;
12782
12783         t = readtoken();
12784         tokpushback = 1;
12785         return t;
12786 }
12787
12788 /*
12789  * Read and parse a command.  Returns NODE_EOF on end of file.
12790  * (NULL is a valid parse tree indicating a blank line.)
12791  */
12792 static union node *
12793 parsecmd(int interact)
12794 {
12795         tokpushback = 0;
12796         checkkwd = 0;
12797         heredoclist = 0;
12798         doprompt = interact;
12799         setprompt_if(doprompt, doprompt);
12800         needprompt = 0;
12801         return list(1);
12802 }
12803
12804 /*
12805  * Input any here documents.
12806  */
12807 static void
12808 parseheredoc(void)
12809 {
12810         struct heredoc *here;
12811         union node *n;
12812
12813         here = heredoclist;
12814         heredoclist = NULL;
12815
12816         while (here) {
12817                 setprompt_if(needprompt, 2);
12818                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12819                                 here->eofmark, here->striptabs);
12820                 n = stzalloc(sizeof(struct narg));
12821                 n->narg.type = NARG;
12822                 /*n->narg.next = NULL; - stzalloc did it */
12823                 n->narg.text = wordtext;
12824                 n->narg.backquote = backquotelist;
12825                 here->here->nhere.doc = n;
12826                 here = here->next;
12827         }
12828 }
12829
12830
12831 static const char *
12832 expandstr(const char *ps, int syntax_type)
12833 {
12834         union node n;
12835         int saveprompt;
12836
12837         /* XXX Fix (char *) cast. */
12838         setinputstring((char *)ps);
12839
12840         saveprompt = doprompt;
12841         doprompt = 0;
12842
12843         /* readtoken1() might die horribly.
12844          * Try a prompt with syntactically wrong command:
12845          * PS1='$(date "+%H:%M:%S) > '
12846          */
12847         {
12848                 volatile int saveint;
12849                 struct jmploc *volatile savehandler = exception_handler;
12850                 struct jmploc jmploc;
12851                 SAVE_INT(saveint);
12852                 if (setjmp(jmploc.loc) == 0) {
12853                         exception_handler = &jmploc;
12854                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12855                 }
12856                 exception_handler = savehandler;
12857                 RESTORE_INT(saveint);
12858         }
12859
12860         doprompt = saveprompt;
12861
12862         popfile();
12863
12864         n.narg.type = NARG;
12865         n.narg.next = NULL;
12866         n.narg.text = wordtext;
12867         n.narg.backquote = backquotelist;
12868
12869         expandarg(&n, NULL, EXP_QUOTED);
12870         return stackblock();
12871 }
12872
12873 static inline int
12874 parser_eof(void)
12875 {
12876         return tokpushback && lasttoken == TEOF;
12877 }
12878
12879 /*
12880  * Execute a command or commands contained in a string.
12881  */
12882 static int
12883 evalstring(char *s, int flags)
12884 {
12885         struct jmploc *volatile savehandler;
12886         struct jmploc jmploc;
12887         int ex;
12888
12889         union node *n;
12890         struct stackmark smark;
12891         int status;
12892
12893         s = sstrdup(s);
12894         setinputstring(s);
12895         setstackmark(&smark);
12896
12897         status = 0;
12898         /* On exception inside execution loop, we must popfile().
12899          * Try interactively:
12900          *      readonly a=a
12901          *      command eval "a=b"  # throws "is read only" error
12902          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12903          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12904          */
12905         savehandler = exception_handler;
12906         ex = setjmp(jmploc.loc);
12907         if (ex)
12908                 goto out;
12909         exception_handler = &jmploc;
12910
12911         while ((n = parsecmd(0)) != NODE_EOF) {
12912                 int i;
12913
12914                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12915                 if (n)
12916                         status = i;
12917                 popstackmark(&smark);
12918                 if (evalskip)
12919                         break;
12920         }
12921  out:
12922         popstackmark(&smark);
12923         popfile();
12924         stunalloc(s);
12925
12926         exception_handler = savehandler;
12927         if (ex)
12928                 longjmp(exception_handler->loc, ex);
12929
12930         return status;
12931 }
12932
12933 /*
12934  * The eval command.
12935  */
12936 static int FAST_FUNC
12937 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12938 {
12939         char *p;
12940         char *concat;
12941
12942         if (argv[1]) {
12943                 p = argv[1];
12944                 argv += 2;
12945                 if (argv[0]) {
12946                         STARTSTACKSTR(concat);
12947                         for (;;) {
12948                                 concat = stack_putstr(p, concat);
12949                                 p = *argv++;
12950                                 if (p == NULL)
12951                                         break;
12952                                 STPUTC(' ', concat);
12953                         }
12954                         STPUTC('\0', concat);
12955                         p = grabstackstr(concat);
12956                 }
12957                 return evalstring(p, flags & EV_TESTED);
12958         }
12959         return 0;
12960 }
12961
12962 /*
12963  * Read and execute commands.
12964  * "Top" is nonzero for the top level command loop;
12965  * it turns on prompting if the shell is interactive.
12966  */
12967 static int
12968 cmdloop(int top)
12969 {
12970         union node *n;
12971         struct stackmark smark;
12972         int inter;
12973         int status = 0;
12974         int numeof = 0;
12975
12976         TRACE(("cmdloop(%d) called\n", top));
12977         for (;;) {
12978                 int skip;
12979
12980                 setstackmark(&smark);
12981 #if JOBS
12982                 if (doing_jobctl)
12983                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12984 #endif
12985                 inter = 0;
12986                 if (iflag && top) {
12987                         inter++;
12988                         chkmail();
12989                 }
12990                 n = parsecmd(inter);
12991 #if DEBUG
12992                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12993                         showtree(n);
12994 #endif
12995                 if (n == NODE_EOF) {
12996                         if (!top || numeof >= 50)
12997                                 break;
12998                         if (!stoppedjobs()) {
12999                                 if (!Iflag)
13000                                         break;
13001                                 out2str("\nUse \"exit\" to leave shell.\n");
13002                         }
13003                         numeof++;
13004                 } else if (nflag == 0) {
13005                         int i;
13006
13007                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13008                         job_warning >>= 1;
13009                         numeof = 0;
13010                         i = evaltree(n, 0);
13011                         if (n)
13012                                 status = i;
13013                 }
13014                 popstackmark(&smark);
13015                 skip = evalskip;
13016
13017                 if (skip) {
13018                         evalskip &= ~SKIPFUNC;
13019                         break;
13020                 }
13021         }
13022         return status;
13023 }
13024
13025 /*
13026  * Take commands from a file.  To be compatible we should do a path
13027  * search for the file, which is necessary to find sub-commands.
13028  */
13029 static char *
13030 find_dot_file(char *name)
13031 {
13032         char *fullname;
13033         const char *path = pathval();
13034         struct stat statb;
13035
13036         /* don't try this for absolute or relative paths */
13037         if (strchr(name, '/'))
13038                 return name;
13039
13040         while ((fullname = path_advance(&path, name)) != NULL) {
13041                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13042                         /*
13043                          * Don't bother freeing here, since it will
13044                          * be freed by the caller.
13045                          */
13046                         return fullname;
13047                 }
13048                 if (fullname != name)
13049                         stunalloc(fullname);
13050         }
13051         /* not found in PATH */
13052
13053 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13054         return name;
13055 #else
13056         ash_msg_and_raise_error("%s: not found", name);
13057         /* NOTREACHED */
13058 #endif
13059 }
13060
13061 static int FAST_FUNC
13062 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13063 {
13064         /* "false; . empty_file; echo $?" should print 0, not 1: */
13065         int status = 0;
13066         char *fullname;
13067         char **argv;
13068         char *args_need_save;
13069         volatile struct shparam saveparam;
13070
13071 //???
13072 //      struct strlist *sp;
13073 //      for (sp = cmdenviron; sp; sp = sp->next)
13074 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13075
13076         nextopt(nullstr); /* handle possible "--" */
13077         argv = argptr;
13078
13079         if (!argv[0]) {
13080                 /* bash says: "bash: .: filename argument required" */
13081                 return 2; /* bash compat */
13082         }
13083
13084         /* This aborts if file isn't found, which is POSIXly correct.
13085          * bash returns exitcode 1 instead.
13086          */
13087         fullname = find_dot_file(argv[0]);
13088         argv++;
13089         args_need_save = argv[0];
13090         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13091                 int argc;
13092                 saveparam = shellparam;
13093                 shellparam.malloced = 0;
13094                 argc = 1;
13095                 while (argv[argc])
13096                         argc++;
13097                 shellparam.nparam = argc;
13098                 shellparam.p = argv;
13099         };
13100
13101         /* This aborts if file can't be opened, which is POSIXly correct.
13102          * bash returns exitcode 1 instead.
13103          */
13104         setinputfile(fullname, INPUT_PUSH_FILE);
13105         commandname = fullname;
13106         status = cmdloop(0);
13107         popfile();
13108
13109         if (args_need_save) {
13110                 freeparam(&shellparam);
13111                 shellparam = saveparam;
13112         };
13113
13114         return status;
13115 }
13116
13117 static int FAST_FUNC
13118 exitcmd(int argc UNUSED_PARAM, char **argv)
13119 {
13120         if (stoppedjobs())
13121                 return 0;
13122         if (argv[1])
13123                 exitstatus = number(argv[1]);
13124         raise_exception(EXEXIT);
13125         /* NOTREACHED */
13126 }
13127
13128 /*
13129  * Read a file containing shell functions.
13130  */
13131 static void
13132 readcmdfile(char *name)
13133 {
13134         setinputfile(name, INPUT_PUSH_FILE);
13135         cmdloop(0);
13136         popfile();
13137 }
13138
13139
13140 /* ============ find_command inplementation */
13141
13142 /*
13143  * Resolve a command name.  If you change this routine, you may have to
13144  * change the shellexec routine as well.
13145  */
13146 static void
13147 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13148 {
13149         struct tblentry *cmdp;
13150         int idx;
13151         int prev;
13152         char *fullname;
13153         struct stat statb;
13154         int e;
13155         int updatetbl;
13156         struct builtincmd *bcmd;
13157
13158         /* If name contains a slash, don't use PATH or hash table */
13159         if (strchr(name, '/') != NULL) {
13160                 entry->u.index = -1;
13161                 if (act & DO_ABS) {
13162                         while (stat(name, &statb) < 0) {
13163 #ifdef SYSV
13164                                 if (errno == EINTR)
13165                                         continue;
13166 #endif
13167                                 entry->cmdtype = CMDUNKNOWN;
13168                                 return;
13169                         }
13170                 }
13171                 entry->cmdtype = CMDNORMAL;
13172                 return;
13173         }
13174
13175 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13176
13177         updatetbl = (path == pathval());
13178         if (!updatetbl) {
13179                 act |= DO_ALTPATH;
13180                 if (strstr(path, "%builtin") != NULL)
13181                         act |= DO_ALTBLTIN;
13182         }
13183
13184         /* If name is in the table, check answer will be ok */
13185         cmdp = cmdlookup(name, 0);
13186         if (cmdp != NULL) {
13187                 int bit;
13188
13189                 switch (cmdp->cmdtype) {
13190                 default:
13191 #if DEBUG
13192                         abort();
13193 #endif
13194                 case CMDNORMAL:
13195                         bit = DO_ALTPATH;
13196                         break;
13197                 case CMDFUNCTION:
13198                         bit = DO_NOFUNC;
13199                         break;
13200                 case CMDBUILTIN:
13201                         bit = DO_ALTBLTIN;
13202                         break;
13203                 }
13204                 if (act & bit) {
13205                         updatetbl = 0;
13206                         cmdp = NULL;
13207                 } else if (cmdp->rehash == 0)
13208                         /* if not invalidated by cd, we're done */
13209                         goto success;
13210         }
13211
13212         /* If %builtin not in path, check for builtin next */
13213         bcmd = find_builtin(name);
13214         if (bcmd) {
13215                 if (IS_BUILTIN_REGULAR(bcmd))
13216                         goto builtin_success;
13217                 if (act & DO_ALTPATH) {
13218                         if (!(act & DO_ALTBLTIN))
13219                                 goto builtin_success;
13220                 } else if (builtinloc <= 0) {
13221                         goto builtin_success;
13222                 }
13223         }
13224
13225 #if ENABLE_FEATURE_SH_STANDALONE
13226         {
13227                 int applet_no = find_applet_by_name(name);
13228                 if (applet_no >= 0) {
13229                         entry->cmdtype = CMDNORMAL;
13230                         entry->u.index = -2 - applet_no;
13231                         return;
13232                 }
13233         }
13234 #endif
13235
13236         /* We have to search path. */
13237         prev = -1;              /* where to start */
13238         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13239                 if (cmdp->cmdtype == CMDBUILTIN)
13240                         prev = builtinloc;
13241                 else
13242                         prev = cmdp->param.index;
13243         }
13244
13245         e = ENOENT;
13246         idx = -1;
13247  loop:
13248         while ((fullname = path_advance(&path, name)) != NULL) {
13249                 stunalloc(fullname);
13250                 /* NB: code below will still use fullname
13251                  * despite it being "unallocated" */
13252                 idx++;
13253                 if (pathopt) {
13254                         if (prefix(pathopt, "builtin")) {
13255                                 if (bcmd)
13256                                         goto builtin_success;
13257                                 continue;
13258                         }
13259                         if ((act & DO_NOFUNC)
13260                          || !prefix(pathopt, "func")
13261                         ) {     /* ignore unimplemented options */
13262                                 continue;
13263                         }
13264                 }
13265                 /* if rehash, don't redo absolute path names */
13266                 if (fullname[0] == '/' && idx <= prev) {
13267                         if (idx < prev)
13268                                 continue;
13269                         TRACE(("searchexec \"%s\": no change\n", name));
13270                         goto success;
13271                 }
13272                 while (stat(fullname, &statb) < 0) {
13273 #ifdef SYSV
13274                         if (errno == EINTR)
13275                                 continue;
13276 #endif
13277                         if (errno != ENOENT && errno != ENOTDIR)
13278                                 e = errno;
13279                         goto loop;
13280                 }
13281                 e = EACCES;     /* if we fail, this will be the error */
13282                 if (!S_ISREG(statb.st_mode))
13283                         continue;
13284                 if (pathopt) {          /* this is a %func directory */
13285                         stalloc(strlen(fullname) + 1);
13286                         /* NB: stalloc will return space pointed by fullname
13287                          * (because we don't have any intervening allocations
13288                          * between stunalloc above and this stalloc) */
13289                         readcmdfile(fullname);
13290                         cmdp = cmdlookup(name, 0);
13291                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13292                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13293                         stunalloc(fullname);
13294                         goto success;
13295                 }
13296                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13297                 if (!updatetbl) {
13298                         entry->cmdtype = CMDNORMAL;
13299                         entry->u.index = idx;
13300                         return;
13301                 }
13302                 INT_OFF;
13303                 cmdp = cmdlookup(name, 1);
13304                 cmdp->cmdtype = CMDNORMAL;
13305                 cmdp->param.index = idx;
13306                 INT_ON;
13307                 goto success;
13308         }
13309
13310         /* We failed.  If there was an entry for this command, delete it */
13311         if (cmdp && updatetbl)
13312                 delete_cmd_entry();
13313         if (act & DO_ERR) {
13314 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13315                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13316                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13317                         char *argv[3];
13318                         argv[0] = (char*) "command_not_found_handle";
13319                         argv[1] = name;
13320                         argv[2] = NULL;
13321                         evalfun(hookp->param.func, 2, argv, 0);
13322                         entry->cmdtype = CMDUNKNOWN;
13323                         return;
13324                 }
13325 #endif
13326                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13327         }
13328         entry->cmdtype = CMDUNKNOWN;
13329         return;
13330
13331  builtin_success:
13332         if (!updatetbl) {
13333                 entry->cmdtype = CMDBUILTIN;
13334                 entry->u.cmd = bcmd;
13335                 return;
13336         }
13337         INT_OFF;
13338         cmdp = cmdlookup(name, 1);
13339         cmdp->cmdtype = CMDBUILTIN;
13340         cmdp->param.cmd = bcmd;
13341         INT_ON;
13342  success:
13343         cmdp->rehash = 0;
13344         entry->cmdtype = cmdp->cmdtype;
13345         entry->u = cmdp->param;
13346 }
13347
13348
13349 /*
13350  * The trap builtin.
13351  */
13352 static int FAST_FUNC
13353 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13354 {
13355         char *action;
13356         char **ap;
13357         int signo, exitcode;
13358
13359         nextopt(nullstr);
13360         ap = argptr;
13361         if (!*ap) {
13362                 for (signo = 0; signo < NSIG; signo++) {
13363                         char *tr = trap_ptr[signo];
13364                         if (tr) {
13365                                 /* note: bash adds "SIG", but only if invoked
13366                                  * as "bash". If called as "sh", or if set -o posix,
13367                                  * then it prints short signal names.
13368                                  * We are printing short names: */
13369                                 out1fmt("trap -- %s %s\n",
13370                                                 single_quote(tr),
13371                                                 get_signame(signo));
13372                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13373                  * In this case, we will exit very soon, no need to free(). */
13374                                 /* if (trap_ptr != trap && tp[0]) */
13375                                 /*      free(tr); */
13376                         }
13377                 }
13378                 /*
13379                 if (trap_ptr != trap) {
13380                         free(trap_ptr);
13381                         trap_ptr = trap;
13382                 }
13383                 */
13384                 return 0;
13385         }
13386
13387         /* Why the second check?
13388          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13389          * In this case, NUM is signal no, not an action.
13390          */
13391         action = NULL;
13392         if (ap[1] && !is_number(ap[0]))
13393                 action = *ap++;
13394
13395         exitcode = 0;
13396         while (*ap) {
13397                 signo = get_signum(*ap);
13398                 if (signo < 0) {
13399                         /* Mimic bash message exactly */
13400                         ash_msg("%s: invalid signal specification", *ap);
13401                         exitcode = 1;
13402                         goto next;
13403                 }
13404                 INT_OFF;
13405                 if (action) {
13406                         if (LONE_DASH(action))
13407                                 action = NULL;
13408                         else {
13409                                 if (action[0]) /* not NULL and not "" and not "-" */
13410                                         may_have_traps = 1;
13411                                 action = ckstrdup(action);
13412                         }
13413                 }
13414                 free(trap[signo]);
13415                 trap[signo] = action;
13416                 if (signo != 0)
13417                         setsignal(signo);
13418                 INT_ON;
13419  next:
13420                 ap++;
13421         }
13422         return exitcode;
13423 }
13424
13425
13426 /* ============ Builtins */
13427
13428 #if ENABLE_ASH_HELP
13429 static int FAST_FUNC
13430 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13431 {
13432         unsigned col;
13433         unsigned i;
13434
13435         out1fmt(
13436                 "Built-in commands:\n"
13437                 "------------------\n");
13438         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13439                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13440                                         builtintab[i].name + 1);
13441                 if (col > 60) {
13442                         out1fmt("\n");
13443                         col = 0;
13444                 }
13445         }
13446 # if ENABLE_FEATURE_SH_STANDALONE
13447         {
13448                 const char *a = applet_names;
13449                 while (*a) {
13450                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13451                         if (col > 60) {
13452                                 out1fmt("\n");
13453                                 col = 0;
13454                         }
13455                         while (*a++ != '\0')
13456                                 continue;
13457                 }
13458         }
13459 # endif
13460         newline_and_flush(stdout);
13461         return EXIT_SUCCESS;
13462 }
13463 #endif
13464
13465 #if MAX_HISTORY
13466 static int FAST_FUNC
13467 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13468 {
13469         show_history(line_input_state);
13470         return EXIT_SUCCESS;
13471 }
13472 #endif
13473
13474 /*
13475  * The export and readonly commands.
13476  */
13477 static int FAST_FUNC
13478 exportcmd(int argc UNUSED_PARAM, char **argv)
13479 {
13480         struct var *vp;
13481         char *name;
13482         const char *p;
13483         char **aptr;
13484         char opt;
13485         int flag;
13486         int flag_off;
13487
13488         /* "readonly" in bash accepts, but ignores -n.
13489          * We do the same: it saves a conditional in nextopt's param.
13490          */
13491         flag_off = 0;
13492         while ((opt = nextopt("np")) != '\0') {
13493                 if (opt == 'n')
13494                         flag_off = VEXPORT;
13495         }
13496         flag = VEXPORT;
13497         if (argv[0][0] == 'r') {
13498                 flag = VREADONLY;
13499                 flag_off = 0; /* readonly ignores -n */
13500         }
13501         flag_off = ~flag_off;
13502
13503         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13504         {
13505                 aptr = argptr;
13506                 name = *aptr;
13507                 if (name) {
13508                         do {
13509                                 p = strchr(name, '=');
13510                                 if (p != NULL) {
13511                                         p++;
13512                                 } else {
13513                                         vp = *findvar(hashvar(name), name);
13514                                         if (vp) {
13515                                                 vp->flags = ((vp->flags | flag) & flag_off);
13516                                                 continue;
13517                                         }
13518                                 }
13519                                 setvar(name, p, (flag & flag_off));
13520                         } while ((name = *++aptr) != NULL);
13521                         return 0;
13522                 }
13523         }
13524
13525         /* No arguments. Show the list of exported or readonly vars.
13526          * -n is ignored.
13527          */
13528         showvars(argv[0], flag, 0);
13529         return 0;
13530 }
13531
13532 /*
13533  * Delete a function if it exists.
13534  */
13535 static void
13536 unsetfunc(const char *name)
13537 {
13538         struct tblentry *cmdp;
13539
13540         cmdp = cmdlookup(name, 0);
13541         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13542                 delete_cmd_entry();
13543 }
13544
13545 /*
13546  * The unset builtin command.  We unset the function before we unset the
13547  * variable to allow a function to be unset when there is a readonly variable
13548  * with the same name.
13549  */
13550 static int FAST_FUNC
13551 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13552 {
13553         char **ap;
13554         int i;
13555         int flag = 0;
13556
13557         while ((i = nextopt("vf")) != 0) {
13558                 flag = i;
13559         }
13560
13561         for (ap = argptr; *ap; ap++) {
13562                 if (flag != 'f') {
13563                         unsetvar(*ap);
13564                         continue;
13565                 }
13566                 if (flag != 'v')
13567                         unsetfunc(*ap);
13568         }
13569         return 0;
13570 }
13571
13572 static const unsigned char timescmd_str[] ALIGN1 = {
13573         ' ',  offsetof(struct tms, tms_utime),
13574         '\n', offsetof(struct tms, tms_stime),
13575         ' ',  offsetof(struct tms, tms_cutime),
13576         '\n', offsetof(struct tms, tms_cstime),
13577         0
13578 };
13579 static int FAST_FUNC
13580 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13581 {
13582         unsigned clk_tck;
13583         const unsigned char *p;
13584         struct tms buf;
13585
13586         clk_tck = bb_clk_tck();
13587
13588         times(&buf);
13589         p = timescmd_str;
13590         do {
13591                 unsigned sec, frac;
13592                 unsigned long t;
13593                 t = *(clock_t *)(((char *) &buf) + p[1]);
13594                 sec = t / clk_tck;
13595                 frac = t % clk_tck;
13596                 out1fmt("%um%u.%03us%c",
13597                         sec / 60, sec % 60,
13598                         (frac * 1000) / clk_tck,
13599                         p[0]);
13600                 p += 2;
13601         } while (*p);
13602
13603         return 0;
13604 }
13605
13606 #if ENABLE_FEATURE_SH_MATH
13607 /*
13608  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13609  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13610  *
13611  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13612  */
13613 static int FAST_FUNC
13614 letcmd(int argc UNUSED_PARAM, char **argv)
13615 {
13616         arith_t i;
13617
13618         argv++;
13619         if (!*argv)
13620                 ash_msg_and_raise_error("expression expected");
13621         do {
13622                 i = ash_arith(*argv);
13623         } while (*++argv);
13624
13625         return !i;
13626 }
13627 #endif
13628
13629 /*
13630  * The read builtin. Options:
13631  *      -r              Do not interpret '\' specially
13632  *      -s              Turn off echo (tty only)
13633  *      -n NCHARS       Read NCHARS max
13634  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13635  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13636  *      -u FD           Read from given FD instead of fd 0
13637  *      -d DELIM        End on DELIM char, not newline
13638  * This uses unbuffered input, which may be avoidable in some cases.
13639  * TODO: bash also has:
13640  *      -a ARRAY        Read into array[0],[1],etc
13641  *      -e              Use line editing (tty only)
13642  */
13643 static int FAST_FUNC
13644 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13645 {
13646         char *opt_n = NULL;
13647         char *opt_p = NULL;
13648         char *opt_t = NULL;
13649         char *opt_u = NULL;
13650         char *opt_d = NULL; /* optimized out if !BASH */
13651         int read_flags = 0;
13652         const char *r;
13653         int i;
13654
13655         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13656                 switch (i) {
13657                 case 'p':
13658                         opt_p = optionarg;
13659                         break;
13660                 case 'n':
13661                         opt_n = optionarg;
13662                         break;
13663                 case 's':
13664                         read_flags |= BUILTIN_READ_SILENT;
13665                         break;
13666                 case 't':
13667                         opt_t = optionarg;
13668                         break;
13669                 case 'r':
13670                         read_flags |= BUILTIN_READ_RAW;
13671                         break;
13672                 case 'u':
13673                         opt_u = optionarg;
13674                         break;
13675 #if BASH_READ_D
13676                 case 'd':
13677                         opt_d = optionarg;
13678                         break;
13679 #endif
13680                 default:
13681                         break;
13682                 }
13683         }
13684
13685         /* "read -s" needs to save/restore termios, can't allow ^C
13686          * to jump out of it.
13687          */
13688  again:
13689         INT_OFF;
13690         r = shell_builtin_read(setvar0,
13691                 argptr,
13692                 bltinlookup("IFS"), /* can be NULL */
13693                 read_flags,
13694                 opt_n,
13695                 opt_p,
13696                 opt_t,
13697                 opt_u,
13698                 opt_d
13699         );
13700         INT_ON;
13701
13702         if ((uintptr_t)r == 1 && errno == EINTR) {
13703                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13704                  * Correct behavior is to not exit "read"
13705                  */
13706                 if (pending_sig == 0)
13707                         goto again;
13708         }
13709
13710         if ((uintptr_t)r > 1)
13711                 ash_msg_and_raise_error(r);
13712
13713         return (uintptr_t)r;
13714 }
13715
13716 static int FAST_FUNC
13717 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13718 {
13719         static const char permuser[3] ALIGN1 = "ogu";
13720
13721         mode_t mask;
13722         int symbolic_mode = 0;
13723
13724         while (nextopt("S") != '\0') {
13725                 symbolic_mode = 1;
13726         }
13727
13728         INT_OFF;
13729         mask = umask(0);
13730         umask(mask);
13731         INT_ON;
13732
13733         if (*argptr == NULL) {
13734                 if (symbolic_mode) {
13735                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13736                         char *p = buf;
13737                         int i;
13738
13739                         i = 2;
13740                         for (;;) {
13741                                 *p++ = ',';
13742                                 *p++ = permuser[i];
13743                                 *p++ = '=';
13744                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13745                                 if (!(mask & 0400)) *p++ = 'r';
13746                                 if (!(mask & 0200)) *p++ = 'w';
13747                                 if (!(mask & 0100)) *p++ = 'x';
13748                                 mask <<= 3;
13749                                 if (--i < 0)
13750                                         break;
13751                         }
13752                         *p = '\0';
13753                         puts(buf + 1);
13754                 } else {
13755                         out1fmt("%04o\n", mask);
13756                 }
13757         } else {
13758                 char *modestr = *argptr;
13759                 /* numeric umasks are taken as-is */
13760                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13761                 if (!isdigit(modestr[0]))
13762                         mask ^= 0777;
13763                 mask = bb_parse_mode(modestr, mask);
13764                 if ((unsigned)mask > 0777) {
13765                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13766                 }
13767                 if (!isdigit(modestr[0]))
13768                         mask ^= 0777;
13769                 umask(mask);
13770         }
13771         return 0;
13772 }
13773
13774 static int FAST_FUNC
13775 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13776 {
13777         return shell_builtin_ulimit(argv);
13778 }
13779
13780 /* ============ main() and helpers */
13781
13782 /*
13783  * Called to exit the shell.
13784  */
13785 static void
13786 exitshell(void)
13787 {
13788         struct jmploc loc;
13789         char *p;
13790         int status;
13791
13792 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13793         save_history(line_input_state);
13794 #endif
13795         status = exitstatus;
13796         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13797         if (setjmp(loc.loc)) {
13798                 if (exception_type == EXEXIT)
13799                         status = exitstatus;
13800                 goto out;
13801         }
13802         exception_handler = &loc;
13803         p = trap[0];
13804         if (p) {
13805                 trap[0] = NULL;
13806                 evalskip = 0;
13807                 evalstring(p, 0);
13808                 /*free(p); - we'll exit soon */
13809         }
13810  out:
13811         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13812          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13813          */
13814         setjobctl(0);
13815         flush_stdout_stderr();
13816         _exit(status);
13817         /* NOTREACHED */
13818 }
13819
13820 /* Don't inline: conserve stack of caller from having our locals too */
13821 static NOINLINE void
13822 init(void)
13823 {
13824         /* we will never free this */
13825         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13826         basepf.linno = 1;
13827
13828         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13829         setsignal(SIGCHLD);
13830
13831         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13832          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13833          */
13834         signal(SIGHUP, SIG_DFL);
13835
13836         {
13837                 char **envp;
13838                 const char *p;
13839
13840                 initvar();
13841                 for (envp = environ; envp && *envp; envp++) {
13842 /* Used to have
13843  *                      p = endofname(*envp);
13844  *                      if (p != *envp && *p == '=') {
13845  * here to weed out badly-named variables, but this breaks
13846  * scenarios where people do want them passed to children:
13847  * import os
13848  * os.environ["test-test"]="test"
13849  * if os.fork() == 0:
13850  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13851  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13852  */
13853                         if (strchr(*envp, '=')) {
13854                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13855                         }
13856                 }
13857
13858                 setvareq((char*)defoptindvar, VTEXTFIXED);
13859
13860                 setvar0("PPID", utoa(getppid()));
13861 #if BASH_SHLVL_VAR
13862                 p = lookupvar("SHLVL");
13863                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13864 #endif
13865 #if BASH_HOSTNAME_VAR
13866                 if (!lookupvar("HOSTNAME")) {
13867                         struct utsname uts;
13868                         uname(&uts);
13869                         setvar0("HOSTNAME", uts.nodename);
13870                 }
13871 #endif
13872                 p = lookupvar("PWD");
13873                 if (p) {
13874                         struct stat st1, st2;
13875                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13876                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13877                         ) {
13878                                 p = NULL;
13879                         }
13880                 }
13881                 setpwd(p, 0);
13882         }
13883 }
13884
13885
13886 //usage:#define ash_trivial_usage
13887 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13888 //usage:#define ash_full_usage "\n\n"
13889 //usage:        "Unix shell interpreter"
13890
13891 /*
13892  * Process the shell command line arguments.
13893  */
13894 static int
13895 procargs(char **argv)
13896 {
13897         int i;
13898         const char *xminusc;
13899         char **xargv;
13900         int login_sh;
13901
13902         xargv = argv;
13903         login_sh = xargv[0] && xargv[0][0] == '-';
13904         arg0 = xargv[0];
13905         /* if (xargv[0]) - mmm, this is always true! */
13906                 xargv++;
13907         for (i = 0; i < NOPTS; i++)
13908                 optlist[i] = 2;
13909         argptr = xargv;
13910         if (options(/*cmdline:*/ 1, &login_sh)) {
13911                 /* it already printed err message */
13912                 raise_exception(EXERROR);
13913         }
13914         xargv = argptr;
13915         xminusc = minusc;
13916         if (*xargv == NULL) {
13917                 if (xminusc)
13918                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13919                 sflag = 1;
13920         }
13921         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13922                 iflag = 1;
13923         if (mflag == 2)
13924                 mflag = iflag;
13925         for (i = 0; i < NOPTS; i++)
13926                 if (optlist[i] == 2)
13927                         optlist[i] = 0;
13928 #if DEBUG == 2
13929         debug = 1;
13930 #endif
13931         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13932         if (xminusc) {
13933                 minusc = *xargv++;
13934                 if (*xargv)
13935                         goto setarg0;
13936         } else if (!sflag) {
13937                 setinputfile(*xargv, 0);
13938  setarg0:
13939                 arg0 = *xargv++;
13940                 commandname = arg0;
13941         }
13942
13943         shellparam.p = xargv;
13944 #if ENABLE_ASH_GETOPTS
13945         shellparam.optind = 1;
13946         shellparam.optoff = -1;
13947 #endif
13948         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13949         while (*xargv) {
13950                 shellparam.nparam++;
13951                 xargv++;
13952         }
13953         optschanged();
13954
13955         return login_sh;
13956 }
13957
13958 /*
13959  * Read /etc/profile, ~/.profile, $ENV.
13960  */
13961 static void
13962 read_profile(const char *name)
13963 {
13964         name = expandstr(name, DQSYNTAX);
13965         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13966                 return;
13967         cmdloop(0);
13968         popfile();
13969 }
13970
13971 /*
13972  * This routine is called when an error or an interrupt occurs in an
13973  * interactive shell and control is returned to the main command loop.
13974  * (In dash, this function is auto-generated by build machinery).
13975  */
13976 static void
13977 reset(void)
13978 {
13979         /* from eval.c: */
13980         evalskip = 0;
13981         loopnest = 0;
13982
13983         /* from expand.c: */
13984         ifsfree();
13985
13986         /* from input.c: */
13987         g_parsefile->left_in_buffer = 0;
13988         g_parsefile->left_in_line = 0;      /* clear input buffer */
13989         popallfiles();
13990
13991         /* from redir.c: */
13992         unwindredir(NULL);
13993
13994         /* from var.c: */
13995         unwindlocalvars(NULL);
13996 }
13997
13998 #if PROFILE
13999 static short profile_buf[16384];
14000 extern int etext();
14001 #endif
14002
14003 /*
14004  * Main routine.  We initialize things, parse the arguments, execute
14005  * profiles if we're a login shell, and then call cmdloop to execute
14006  * commands.  The setjmp call sets up the location to jump to when an
14007  * exception occurs.  When an exception occurs the variable "state"
14008  * is used to figure out how far we had gotten.
14009  */
14010 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14011 int ash_main(int argc UNUSED_PARAM, char **argv)
14012 {
14013         volatile smallint state;
14014         struct jmploc jmploc;
14015         struct stackmark smark;
14016         int login_sh;
14017
14018         /* Initialize global data */
14019         INIT_G_misc();
14020         INIT_G_memstack();
14021         INIT_G_var();
14022 #if ENABLE_ASH_ALIAS
14023         INIT_G_alias();
14024 #endif
14025         INIT_G_cmdtable();
14026
14027 #if PROFILE
14028         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14029 #endif
14030
14031 #if ENABLE_FEATURE_EDITING
14032         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14033 #endif
14034         state = 0;
14035         if (setjmp(jmploc.loc)) {
14036                 smallint e;
14037                 smallint s;
14038
14039                 reset();
14040
14041                 e = exception_type;
14042                 s = state;
14043                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14044                         exitshell();
14045                 }
14046                 if (e == EXINT) {
14047                         newline_and_flush(stderr);
14048                 }
14049
14050                 popstackmark(&smark);
14051                 FORCE_INT_ON; /* enable interrupts */
14052                 if (s == 1)
14053                         goto state1;
14054                 if (s == 2)
14055                         goto state2;
14056                 if (s == 3)
14057                         goto state3;
14058                 goto state4;
14059         }
14060         exception_handler = &jmploc;
14061         rootpid = getpid();
14062
14063         init();
14064         setstackmark(&smark);
14065         login_sh = procargs(argv);
14066 #if DEBUG
14067         TRACE(("Shell args: "));
14068         trace_puts_args(argv);
14069 #endif
14070
14071         if (login_sh) {
14072                 const char *hp;
14073
14074                 state = 1;
14075                 read_profile("/etc/profile");
14076  state1:
14077                 state = 2;
14078                 hp = lookupvar("HOME");
14079                 if (hp)
14080                         read_profile("$HOME/.profile");
14081         }
14082  state2:
14083         state = 3;
14084         if (
14085 #ifndef linux
14086          getuid() == geteuid() && getgid() == getegid() &&
14087 #endif
14088          iflag
14089         ) {
14090                 const char *shinit = lookupvar("ENV");
14091                 if (shinit != NULL && *shinit != '\0')
14092                         read_profile(shinit);
14093         }
14094         popstackmark(&smark);
14095  state3:
14096         state = 4;
14097         if (minusc) {
14098                 /* evalstring pushes parsefile stack.
14099                  * Ensure we don't falsely claim that 0 (stdin)
14100                  * is one of stacked source fds.
14101                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14102                 // if (!sflag) g_parsefile->pf_fd = -1;
14103                 // ^^ not necessary since now we special-case fd 0
14104                 // in save_fd_on_redirect()
14105                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14106         }
14107
14108         if (sflag || minusc == NULL) {
14109 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14110                 if (iflag) {
14111                         const char *hp = lookupvar("HISTFILE");
14112                         if (!hp) {
14113                                 hp = lookupvar("HOME");
14114                                 if (hp) {
14115                                         INT_OFF;
14116                                         hp = concat_path_file(hp, ".ash_history");
14117                                         setvar0("HISTFILE", hp);
14118                                         free((char*)hp);
14119                                         INT_ON;
14120                                         hp = lookupvar("HISTFILE");
14121                                 }
14122                         }
14123                         if (hp)
14124                                 line_input_state->hist_file = hp;
14125 # if ENABLE_FEATURE_SH_HISTFILESIZE
14126                         hp = lookupvar("HISTFILESIZE");
14127                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14128 # endif
14129                 }
14130 #endif
14131  state4: /* XXX ??? - why isn't this before the "if" statement */
14132                 cmdloop(1);
14133         }
14134 #if PROFILE
14135         monitor(0);
14136 #endif
14137 #ifdef GPROF
14138         {
14139                 extern void _mcleanup(void);
14140                 _mcleanup();
14141         }
14142 #endif
14143         TRACE(("End of main reached\n"));
14144         exitshell();
14145         /* NOTREACHED */
14146 }
14147
14148
14149 /*-
14150  * Copyright (c) 1989, 1991, 1993, 1994
14151  *      The Regents of the University of California.  All rights reserved.
14152  *
14153  * This code is derived from software contributed to Berkeley by
14154  * Kenneth Almquist.
14155  *
14156  * Redistribution and use in source and binary forms, with or without
14157  * modification, are permitted provided that the following conditions
14158  * are met:
14159  * 1. Redistributions of source code must retain the above copyright
14160  *    notice, this list of conditions and the following disclaimer.
14161  * 2. Redistributions in binary form must reproduce the above copyright
14162  *    notice, this list of conditions and the following disclaimer in the
14163  *    documentation and/or other materials provided with the distribution.
14164  * 3. Neither the name of the University nor the names of its contributors
14165  *    may be used to endorse or promote products derived from this software
14166  *    without specific prior written permission.
14167  *
14168  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14169  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14170  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14171  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14172  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14173  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14174  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14175  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14176  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14177  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14178  * SUCH DAMAGE.
14179  */