ash,hush: make ^C in interactive mode visually much closer to bash behavior
[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
19 /*
20  * The following should be set to reflect the type of system you have:
21  *      JOBS -> 1 if you have Berkeley job control, 0 otherwise.
22  *      define SYSV if you are running under System V.
23  *      define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
24  *      define DEBUG=2 to compile in and turn on debugging.
25  *
26  * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
27  * debugging info will be written to ./trace and a quit signal
28  * will generate a core dump.
29  */
30 #define DEBUG 0
31 /* Tweak debug output verbosity here */
32 #define DEBUG_TIME 0
33 #define DEBUG_PID 1
34 #define DEBUG_SIG 1
35 #define DEBUG_INTONOFF 0
36
37 #define PROFILE 0
38
39 #define JOBS ENABLE_ASH_JOB_CONTROL
40
41 #include <setjmp.h>
42 #include <fnmatch.h>
43 #include <sys/times.h>
44 #include <sys/utsname.h> /* for setting $HOSTNAME */
45
46 #include "busybox.h" /* for applet_names */
47
48 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
49 /* Bionic at least up to version 24 has no glob() */
50 # undef  ENABLE_ASH_INTERNAL_GLOB
51 # define ENABLE_ASH_INTERNAL_GLOB 1
52 #endif
53
54 #if !ENABLE_ASH_INTERNAL_GLOB
55 # include <glob.h>
56 #endif
57
58 #include "unicode.h"
59 #include "shell_common.h"
60 #if ENABLE_SH_MATH_SUPPORT
61 # include "math.h"
62 #endif
63 #if ENABLE_ASH_RANDOM_SUPPORT
64 # include "random.h"
65 #else
66 # define CLEAR_RANDOM_T(rnd) ((void)0)
67 #endif
68
69 #include "NUM_APPLETS.h"
70 #if NUM_APPLETS == 1
71 /* STANDALONE does not make sense, and won't compile */
72 # undef CONFIG_FEATURE_SH_STANDALONE
73 # undef ENABLE_FEATURE_SH_STANDALONE
74 # undef IF_FEATURE_SH_STANDALONE
75 # undef IF_NOT_FEATURE_SH_STANDALONE
76 # define ENABLE_FEATURE_SH_STANDALONE 0
77 # define IF_FEATURE_SH_STANDALONE(...)
78 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
79 #endif
80
81 #ifndef PIPE_BUF
82 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
83 #endif
84
85 #if !BB_MMU
86 # error "Do not even bother, ash will not run on NOMMU machine"
87 #endif
88
89 //config:config ASH
90 //config:       bool "ash"
91 //config:       default y
92 //config:       depends on !NOMMU
93 //config:       help
94 //config:         Tha 'ash' shell adds about 60k in the default configuration and is
95 //config:         the most complete and most pedantically correct shell included with
96 //config:         busybox. This shell is actually a derivative of the Debian 'dash'
97 //config:         shell (by Herbert Xu), which was created by porting the 'ash' shell
98 //config:         (written by Kenneth Almquist) from NetBSD.
99 //config:
100 //config:config ASH_OPTIMIZE_FOR_SIZE
101 //config:       bool "Optimize for size instead of speed"
102 //config:       default y
103 //config:       depends on ASH
104 //config:       help
105 //config:         Compile ash for reduced size at the price of speed.
106 //config:
107 //config:config ASH_INTERNAL_GLOB
108 //config:       bool "Use internal glob() implementation"
109 //config:       default n
110 //config:       depends on ASH
111 //config:       help
112 //config:         Do not use glob() function from libc, use internal implementation.
113 //config:         Use this if you are getting "glob.h: No such file or directory"
114 //config:         or similar build errors.
115 //config:
116 //config:config ASH_RANDOM_SUPPORT
117 //config:       bool "Pseudorandom generator and $RANDOM variable"
118 //config:       default y
119 //config:       depends on ASH
120 //config:       help
121 //config:         Enable pseudorandom generator and dynamic variable "$RANDOM".
122 //config:         Each read of "$RANDOM" will generate a new pseudorandom value.
123 //config:         You can reset the generator by using a specified start value.
124 //config:         After "unset RANDOM" the generator will switch off and this
125 //config:         variable will no longer have special treatment.
126 //config:
127 //config:config ASH_EXPAND_PRMT
128 //config:       bool "Expand prompt string"
129 //config:       default y
130 //config:       depends on ASH
131 //config:       help
132 //config:         "PS#" may contain volatile content, such as backquote commands.
133 //config:         This option recreates the prompt string from the environment
134 //config:         variable each time it is displayed.
135 //config:
136 //config:config ASH_BASH_COMPAT
137 //config:       bool "bash-compatible extensions"
138 //config:       default y
139 //config:       depends on ASH
140 //config:       help
141 //config:         Enable bash-compatible extensions.
142 //config:
143 //config:config ASH_IDLE_TIMEOUT
144 //config:       bool "Idle timeout variable"
145 //config:       default n
146 //config:       depends on ASH
147 //config:       help
148 //config:         Enables bash-like auto-logout after $TMOUT seconds of idle time.
149 //config:
150 //config:config ASH_JOB_CONTROL
151 //config:       bool "Job control"
152 //config:       default y
153 //config:       depends on ASH
154 //config:       help
155 //config:         Enable job control in the ash shell.
156 //config:
157 //config:config ASH_ALIAS
158 //config:       bool "Alias support"
159 //config:       default y
160 //config:       depends on ASH
161 //config:       help
162 //config:         Enable alias support in the ash shell.
163 //config:
164 //config:config ASH_GETOPTS
165 //config:       bool "Builtin getopt to parse positional parameters"
166 //config:       default y
167 //config:       depends on ASH
168 //config:       help
169 //config:         Enable support for getopts builtin in ash.
170 //config:
171 //config:config ASH_BUILTIN_ECHO
172 //config:       bool "Builtin version of 'echo'"
173 //config:       default y
174 //config:       depends on ASH
175 //config:       help
176 //config:         Enable support for echo builtin in ash.
177 //config:
178 //config:config ASH_BUILTIN_PRINTF
179 //config:       bool "Builtin version of 'printf'"
180 //config:       default y
181 //config:       depends on ASH
182 //config:       help
183 //config:         Enable support for printf builtin in ash.
184 //config:
185 //config:config ASH_BUILTIN_TEST
186 //config:       bool "Builtin version of 'test'"
187 //config:       default y
188 //config:       depends on ASH
189 //config:       help
190 //config:         Enable support for test builtin in ash.
191 //config:
192 //config:config ASH_HELP
193 //config:       bool "help builtin"
194 //config:       default y
195 //config:       depends on ASH
196 //config:       help
197 //config:         Enable help builtin in ash.
198 //config:
199 //config:config ASH_CMDCMD
200 //config:       bool "'command' command to override shell builtins"
201 //config:       default y
202 //config:       depends on ASH
203 //config:       help
204 //config:         Enable support for the ash 'command' builtin, which allows
205 //config:         you to run the specified command with the specified arguments,
206 //config:         even when there is an ash builtin command with the same name.
207 //config:
208 //config:config ASH_MAIL
209 //config:       bool "Check for new mail on interactive shells"
210 //config:       default n
211 //config:       depends on ASH
212 //config:       help
213 //config:         Enable "check for new mail" function in the ash shell.
214 //config:
215
216 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
217 //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
218 //applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash))
219
220 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
221 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
222
223
224 /* ============ Hash table sizes. Configurable. */
225
226 #define VTABSIZE 39
227 #define ATABSIZE 39
228 #define CMDTABLESIZE 31         /* should be prime */
229
230
231 /* ============ Shell options */
232
233 static const char *const optletters_optnames[] = {
234         "e"   "errexit",
235         "f"   "noglob",
236         "I"   "ignoreeof",
237         "i"   "interactive",
238         "m"   "monitor",
239         "n"   "noexec",
240         "s"   "stdin",
241         "x"   "xtrace",
242         "v"   "verbose",
243         "C"   "noclobber",
244         "a"   "allexport",
245         "b"   "notify",
246         "u"   "nounset",
247         "\0"  "vi"
248 #if ENABLE_ASH_BASH_COMPAT
249         ,"\0"  "pipefail"
250 #endif
251 #if DEBUG
252         ,"\0"  "nolog"
253         ,"\0"  "debug"
254 #endif
255 };
256
257 #define optletters(n)  optletters_optnames[n][0]
258 #define optnames(n)   (optletters_optnames[n] + 1)
259
260 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
261
262
263 /* ============ Misc data */
264
265 #define msg_illnum "Illegal number: %s"
266
267 /*
268  * We enclose jmp_buf in a structure so that we can declare pointers to
269  * jump locations.  The global variable handler contains the location to
270  * jump to when an exception occurs, and the global variable exception_type
271  * contains a code identifying the exception.  To implement nested
272  * exception handlers, the user should save the value of handler on entry
273  * to an inner scope, set handler to point to a jmploc structure for the
274  * inner scope, and restore handler on exit from the scope.
275  */
276 struct jmploc {
277         jmp_buf loc;
278 };
279
280 struct globals_misc {
281         uint8_t exitstatus;     /* exit status of last command */
282         uint8_t back_exitstatus;/* exit status of backquoted command */
283         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
284         int rootpid;            /* pid of main shell */
285         /* shell level: 0 for the main shell, 1 for its children, and so on */
286         int shlvl;
287 #define rootshell (!shlvl)
288         char *minusc;  /* argument to -c option */
289
290         char *curdir; // = nullstr;     /* current working directory */
291         char *physdir; // = nullstr;    /* physical working directory */
292
293         char *arg0; /* value of $0 */
294
295         struct jmploc *exception_handler;
296
297         volatile int suppress_int; /* counter */
298         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
299         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
300         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
301         smallint exception_type; /* kind of exception (0..5) */
302         /* exceptions */
303 #define EXINT 0         /* SIGINT received */
304 #define EXERROR 1       /* a generic error */
305 #define EXEXIT 4        /* exit the shell */
306
307         smallint isloginsh;
308         char nullstr[1];        /* zero length string */
309
310         char optlist[NOPTS];
311 #define eflag optlist[0]
312 #define fflag optlist[1]
313 #define Iflag optlist[2]
314 #define iflag optlist[3]
315 #define mflag optlist[4]
316 #define nflag optlist[5]
317 #define sflag optlist[6]
318 #define xflag optlist[7]
319 #define vflag optlist[8]
320 #define Cflag optlist[9]
321 #define aflag optlist[10]
322 #define bflag optlist[11]
323 #define uflag optlist[12]
324 #define viflag optlist[13]
325 #if ENABLE_ASH_BASH_COMPAT
326 # define pipefail optlist[14]
327 #else
328 # define pipefail 0
329 #endif
330 #if DEBUG
331 # define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT]
332 # define debug optlist[15 + ENABLE_ASH_BASH_COMPAT]
333 #endif
334
335         /* trap handler commands */
336         /*
337          * Sigmode records the current value of the signal handlers for the various
338          * modes.  A value of zero means that the current handler is not known.
339          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
340          */
341         char sigmode[NSIG - 1];
342 #define S_DFL      1            /* default signal handling (SIG_DFL) */
343 #define S_CATCH    2            /* signal is caught */
344 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
345 #define S_HARD_IGN 4            /* signal is ignored permanently */
346
347         /* indicates specified signal received */
348         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
349         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
350         char *trap[NSIG];
351         char **trap_ptr;        /* used only by "trap hack" */
352
353         /* Rarely referenced stuff */
354 #if ENABLE_ASH_RANDOM_SUPPORT
355         random_t random_gen;
356 #endif
357         pid_t backgndpid;        /* pid of last background process */
358 };
359 extern struct globals_misc *const ash_ptr_to_globals_misc;
360 #define G_misc (*ash_ptr_to_globals_misc)
361 #define exitstatus        (G_misc.exitstatus )
362 #define back_exitstatus   (G_misc.back_exitstatus )
363 #define job_warning       (G_misc.job_warning)
364 #define rootpid     (G_misc.rootpid    )
365 #define shlvl       (G_misc.shlvl      )
366 #define minusc      (G_misc.minusc     )
367 #define curdir      (G_misc.curdir     )
368 #define physdir     (G_misc.physdir    )
369 #define arg0        (G_misc.arg0       )
370 #define exception_handler (G_misc.exception_handler)
371 #define exception_type    (G_misc.exception_type   )
372 #define suppress_int      (G_misc.suppress_int     )
373 #define pending_int       (G_misc.pending_int      )
374 #define got_sigchld       (G_misc.got_sigchld      )
375 #define pending_sig       (G_misc.pending_sig      )
376 #define isloginsh   (G_misc.isloginsh  )
377 #define nullstr     (G_misc.nullstr    )
378 #define optlist     (G_misc.optlist    )
379 #define sigmode     (G_misc.sigmode    )
380 #define gotsig      (G_misc.gotsig     )
381 #define may_have_traps    (G_misc.may_have_traps   )
382 #define trap        (G_misc.trap       )
383 #define trap_ptr    (G_misc.trap_ptr   )
384 #define random_gen  (G_misc.random_gen )
385 #define backgndpid  (G_misc.backgndpid )
386 #define INIT_G_misc() do { \
387         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
388         barrier(); \
389         curdir = nullstr; \
390         physdir = nullstr; \
391         trap_ptr = trap; \
392 } while (0)
393
394
395 /* ============ DEBUG */
396 #if DEBUG
397 static void trace_printf(const char *fmt, ...);
398 static void trace_vprintf(const char *fmt, va_list va);
399 # define TRACE(param)    trace_printf param
400 # define TRACEV(param)   trace_vprintf param
401 # define close(fd) do { \
402         int dfd = (fd); \
403         if (close(dfd) < 0) \
404                 bb_error_msg("bug on %d: closing %d(0x%x)", \
405                         __LINE__, dfd, dfd); \
406 } while (0)
407 #else
408 # define TRACE(param)
409 # define TRACEV(param)
410 #endif
411
412
413 /* ============ Utility functions */
414 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
415 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
416
417 static int
418 isdigit_str9(const char *str)
419 {
420         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
421         while (--maxlen && isdigit(*str))
422                 str++;
423         return (*str == '\0');
424 }
425
426 static const char *
427 var_end(const char *var)
428 {
429         while (*var)
430                 if (*var++ == '=')
431                         break;
432         return var;
433 }
434
435
436 /* ============ Interrupts / exceptions */
437
438 static void exitshell(void) NORETURN;
439
440 /*
441  * These macros allow the user to suspend the handling of interrupt signals
442  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
443  * much more efficient and portable.  (But hacking the kernel is so much
444  * more fun than worrying about efficiency and portability. :-))
445  */
446 #if DEBUG_INTONOFF
447 # define INT_OFF do { \
448         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
449         suppress_int++; \
450         barrier(); \
451 } while (0)
452 #else
453 # define INT_OFF do { \
454         suppress_int++; \
455         barrier(); \
456 } while (0)
457 #endif
458
459 /*
460  * Called to raise an exception.  Since C doesn't include exceptions, we
461  * just do a longjmp to the exception handler.  The type of exception is
462  * stored in the global variable "exception_type".
463  */
464 static void raise_exception(int) NORETURN;
465 static void
466 raise_exception(int e)
467 {
468 #if DEBUG
469         if (exception_handler == NULL)
470                 abort();
471 #endif
472         INT_OFF;
473         exception_type = e;
474         longjmp(exception_handler->loc, 1);
475 }
476 #if DEBUG
477 #define raise_exception(e) do { \
478         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
479         raise_exception(e); \
480 } while (0)
481 #endif
482
483 /*
484  * Called when a SIGINT is received.  (If the user specifies
485  * that SIGINT is to be trapped or ignored using the trap builtin, then
486  * this routine is not called.)  Suppressint is nonzero when interrupts
487  * are held using the INT_OFF macro.  (The test for iflag is just
488  * defensive programming.)
489  */
490 static void raise_interrupt(void) NORETURN;
491 static void
492 raise_interrupt(void)
493 {
494         pending_int = 0;
495         /* Signal is not automatically unmasked after it is raised,
496          * do it ourself - unmask all signals */
497         sigprocmask_allsigs(SIG_UNBLOCK);
498         /* pending_sig = 0; - now done in signal_handler() */
499
500         if (!(rootshell && iflag)) {
501                 /* Kill ourself with SIGINT */
502                 signal(SIGINT, SIG_DFL);
503                 raise(SIGINT);
504         }
505         /* bash: ^C even on empty command line sets $? */
506         exitstatus = SIGINT + 128;
507         raise_exception(EXINT);
508         /* NOTREACHED */
509 }
510 #if DEBUG
511 #define raise_interrupt() do { \
512         TRACE(("raising interrupt on line %d\n", __LINE__)); \
513         raise_interrupt(); \
514 } while (0)
515 #endif
516
517 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
518 int_on(void)
519 {
520         barrier();
521         if (--suppress_int == 0 && pending_int) {
522                 raise_interrupt();
523         }
524 }
525 #if DEBUG_INTONOFF
526 # define INT_ON do { \
527         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
528         int_on(); \
529 } while (0)
530 #else
531 # define INT_ON int_on()
532 #endif
533 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
534 force_int_on(void)
535 {
536         barrier();
537         suppress_int = 0;
538         if (pending_int)
539                 raise_interrupt();
540 }
541 #define FORCE_INT_ON force_int_on()
542
543 #define SAVE_INT(v) ((v) = suppress_int)
544
545 #define RESTORE_INT(v) do { \
546         barrier(); \
547         suppress_int = (v); \
548         if (suppress_int == 0 && pending_int) \
549                 raise_interrupt(); \
550 } while (0)
551
552
553 /* ============ Stdout/stderr output */
554
555 static void
556 outstr(const char *p, FILE *file)
557 {
558         INT_OFF;
559         fputs(p, file);
560         INT_ON;
561 }
562
563 static void
564 flush_stdout_stderr(void)
565 {
566         INT_OFF;
567         fflush_all();
568         INT_ON;
569 }
570
571 /* Was called outcslow(c,FILE*), but c was always '\n' */
572 static void
573 newline_and_flush(FILE *dest)
574 {
575         INT_OFF;
576         putc('\n', dest);
577         fflush(dest);
578         INT_ON;
579 }
580
581 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
582 static int
583 out1fmt(const char *fmt, ...)
584 {
585         va_list ap;
586         int r;
587
588         INT_OFF;
589         va_start(ap, fmt);
590         r = vprintf(fmt, ap);
591         va_end(ap);
592         INT_ON;
593         return r;
594 }
595
596 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
597 static int
598 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
599 {
600         va_list ap;
601         int ret;
602
603         va_start(ap, fmt);
604         INT_OFF;
605         ret = vsnprintf(outbuf, length, fmt, ap);
606         va_end(ap);
607         INT_ON;
608         return ret;
609 }
610
611 static void
612 out1str(const char *p)
613 {
614         outstr(p, stdout);
615 }
616
617 static void
618 out2str(const char *p)
619 {
620         outstr(p, stderr);
621         flush_stdout_stderr();
622 }
623
624
625 /* ============ Parser structures */
626
627 /* control characters in argument strings */
628 #define CTL_FIRST CTLESC
629 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
630 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
631 #define CTLENDVAR    ((unsigned char)'\203')
632 #define CTLBACKQ     ((unsigned char)'\204')
633 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
634 #define CTLENDARI    ((unsigned char)'\207')
635 #define CTLQUOTEMARK ((unsigned char)'\210')
636 #define CTL_LAST CTLQUOTEMARK
637
638 /* variable substitution byte (follows CTLVAR) */
639 #define VSTYPE  0x0f            /* type of variable substitution */
640 #define VSNUL   0x10            /* colon--treat the empty string as unset */
641
642 /* values of VSTYPE field */
643 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
644 #define VSMINUS         0x2     /* ${var-text} */
645 #define VSPLUS          0x3     /* ${var+text} */
646 #define VSQUESTION      0x4     /* ${var?message} */
647 #define VSASSIGN        0x5     /* ${var=text} */
648 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
649 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
650 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
651 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
652 #define VSLENGTH        0xa     /* ${#var} */
653 #if ENABLE_ASH_BASH_COMPAT
654 #define VSSUBSTR        0xc     /* ${var:position:length} */
655 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
656 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
657 #endif
658
659 static const char dolatstr[] ALIGN1 = {
660         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
661 };
662 #define DOLATSTRLEN 6
663
664 #define NCMD      0
665 #define NPIPE     1
666 #define NREDIR    2
667 #define NBACKGND  3
668 #define NSUBSHELL 4
669 #define NAND      5
670 #define NOR       6
671 #define NSEMI     7
672 #define NIF       8
673 #define NWHILE    9
674 #define NUNTIL   10
675 #define NFOR     11
676 #define NCASE    12
677 #define NCLIST   13
678 #define NDEFUN   14
679 #define NARG     15
680 #define NTO      16
681 #if ENABLE_ASH_BASH_COMPAT
682 #define NTO2     17
683 #endif
684 #define NCLOBBER 18
685 #define NFROM    19
686 #define NFROMTO  20
687 #define NAPPEND  21
688 #define NTOFD    22
689 #define NFROMFD  23
690 #define NHERE    24
691 #define NXHERE   25
692 #define NNOT     26
693 #define N_NUMBER 27
694
695 union node;
696
697 struct ncmd {
698         smallint type; /* Nxxxx */
699         union node *assign;
700         union node *args;
701         union node *redirect;
702 };
703
704 struct npipe {
705         smallint type;
706         smallint pipe_backgnd;
707         struct nodelist *cmdlist;
708 };
709
710 struct nredir {
711         smallint type;
712         union node *n;
713         union node *redirect;
714 };
715
716 struct nbinary {
717         smallint type;
718         union node *ch1;
719         union node *ch2;
720 };
721
722 struct nif {
723         smallint type;
724         union node *test;
725         union node *ifpart;
726         union node *elsepart;
727 };
728
729 struct nfor {
730         smallint type;
731         union node *args;
732         union node *body;
733         char *var;
734 };
735
736 struct ncase {
737         smallint type;
738         union node *expr;
739         union node *cases;
740 };
741
742 struct nclist {
743         smallint type;
744         union node *next;
745         union node *pattern;
746         union node *body;
747 };
748
749 struct narg {
750         smallint type;
751         union node *next;
752         char *text;
753         struct nodelist *backquote;
754 };
755
756 /* nfile and ndup layout must match!
757  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
758  * that it is actually NTO2 (>&file), and change its type.
759  */
760 struct nfile {
761         smallint type;
762         union node *next;
763         int fd;
764         int _unused_dupfd;
765         union node *fname;
766         char *expfname;
767 };
768
769 struct ndup {
770         smallint type;
771         union node *next;
772         int fd;
773         int dupfd;
774         union node *vname;
775         char *_unused_expfname;
776 };
777
778 struct nhere {
779         smallint type;
780         union node *next;
781         int fd;
782         union node *doc;
783 };
784
785 struct nnot {
786         smallint type;
787         union node *com;
788 };
789
790 union node {
791         smallint type;
792         struct ncmd ncmd;
793         struct npipe npipe;
794         struct nredir nredir;
795         struct nbinary nbinary;
796         struct nif nif;
797         struct nfor nfor;
798         struct ncase ncase;
799         struct nclist nclist;
800         struct narg narg;
801         struct nfile nfile;
802         struct ndup ndup;
803         struct nhere nhere;
804         struct nnot nnot;
805 };
806
807 /*
808  * NODE_EOF is returned by parsecmd when it encounters an end of file.
809  * It must be distinct from NULL.
810  */
811 #define NODE_EOF ((union node *) -1L)
812
813 struct nodelist {
814         struct nodelist *next;
815         union node *n;
816 };
817
818 struct funcnode {
819         int count;
820         union node n;
821 };
822
823 /*
824  * Free a parse tree.
825  */
826 static void
827 freefunc(struct funcnode *f)
828 {
829         if (f && --f->count < 0)
830                 free(f);
831 }
832
833
834 /* ============ Debugging output */
835
836 #if DEBUG
837
838 static FILE *tracefile;
839
840 static void
841 trace_printf(const char *fmt, ...)
842 {
843         va_list va;
844
845         if (debug != 1)
846                 return;
847         if (DEBUG_TIME)
848                 fprintf(tracefile, "%u ", (int) time(NULL));
849         if (DEBUG_PID)
850                 fprintf(tracefile, "[%u] ", (int) getpid());
851         if (DEBUG_SIG)
852                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
853         va_start(va, fmt);
854         vfprintf(tracefile, fmt, va);
855         va_end(va);
856 }
857
858 static void
859 trace_vprintf(const char *fmt, va_list va)
860 {
861         if (debug != 1)
862                 return;
863         vfprintf(tracefile, fmt, va);
864         fprintf(tracefile, "\n");
865 }
866
867 static void
868 trace_puts(const char *s)
869 {
870         if (debug != 1)
871                 return;
872         fputs(s, tracefile);
873 }
874
875 static void
876 trace_puts_quoted(char *s)
877 {
878         char *p;
879         char c;
880
881         if (debug != 1)
882                 return;
883         putc('"', tracefile);
884         for (p = s; *p; p++) {
885                 switch ((unsigned char)*p) {
886                 case '\n': c = 'n'; goto backslash;
887                 case '\t': c = 't'; goto backslash;
888                 case '\r': c = 'r'; goto backslash;
889                 case '\"': c = '\"'; goto backslash;
890                 case '\\': c = '\\'; goto backslash;
891                 case CTLESC: c = 'e'; goto backslash;
892                 case CTLVAR: c = 'v'; goto backslash;
893                 case CTLBACKQ: c = 'q'; goto backslash;
894  backslash:
895                         putc('\\', tracefile);
896                         putc(c, tracefile);
897                         break;
898                 default:
899                         if (*p >= ' ' && *p <= '~')
900                                 putc(*p, tracefile);
901                         else {
902                                 putc('\\', tracefile);
903                                 putc((*p >> 6) & 03, tracefile);
904                                 putc((*p >> 3) & 07, tracefile);
905                                 putc(*p & 07, tracefile);
906                         }
907                         break;
908                 }
909         }
910         putc('"', tracefile);
911 }
912
913 static void
914 trace_puts_args(char **ap)
915 {
916         if (debug != 1)
917                 return;
918         if (!*ap)
919                 return;
920         while (1) {
921                 trace_puts_quoted(*ap);
922                 if (!*++ap) {
923                         putc('\n', tracefile);
924                         break;
925                 }
926                 putc(' ', tracefile);
927         }
928 }
929
930 static void
931 opentrace(void)
932 {
933         char s[100];
934 #ifdef O_APPEND
935         int flags;
936 #endif
937
938         if (debug != 1) {
939                 if (tracefile)
940                         fflush(tracefile);
941                 /* leave open because libedit might be using it */
942                 return;
943         }
944         strcpy(s, "./trace");
945         if (tracefile) {
946                 if (!freopen(s, "a", tracefile)) {
947                         fprintf(stderr, "Can't re-open %s\n", s);
948                         debug = 0;
949                         return;
950                 }
951         } else {
952                 tracefile = fopen(s, "a");
953                 if (tracefile == NULL) {
954                         fprintf(stderr, "Can't open %s\n", s);
955                         debug = 0;
956                         return;
957                 }
958         }
959 #ifdef O_APPEND
960         flags = fcntl(fileno(tracefile), F_GETFL);
961         if (flags >= 0)
962                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
963 #endif
964         setlinebuf(tracefile);
965         fputs("\nTracing started.\n", tracefile);
966 }
967
968 static void
969 indent(int amount, char *pfx, FILE *fp)
970 {
971         int i;
972
973         for (i = 0; i < amount; i++) {
974                 if (pfx && i == amount - 1)
975                         fputs(pfx, fp);
976                 putc('\t', fp);
977         }
978 }
979
980 /* little circular references here... */
981 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
982
983 static void
984 sharg(union node *arg, FILE *fp)
985 {
986         char *p;
987         struct nodelist *bqlist;
988         unsigned char subtype;
989
990         if (arg->type != NARG) {
991                 out1fmt("<node type %d>\n", arg->type);
992                 abort();
993         }
994         bqlist = arg->narg.backquote;
995         for (p = arg->narg.text; *p; p++) {
996                 switch ((unsigned char)*p) {
997                 case CTLESC:
998                         p++;
999                         putc(*p, fp);
1000                         break;
1001                 case CTLVAR:
1002                         putc('$', fp);
1003                         putc('{', fp);
1004                         subtype = *++p;
1005                         if (subtype == VSLENGTH)
1006                                 putc('#', fp);
1007
1008                         while (*p != '=') {
1009                                 putc(*p, fp);
1010                                 p++;
1011                         }
1012
1013                         if (subtype & VSNUL)
1014                                 putc(':', fp);
1015
1016                         switch (subtype & VSTYPE) {
1017                         case VSNORMAL:
1018                                 putc('}', fp);
1019                                 break;
1020                         case VSMINUS:
1021                                 putc('-', fp);
1022                                 break;
1023                         case VSPLUS:
1024                                 putc('+', fp);
1025                                 break;
1026                         case VSQUESTION:
1027                                 putc('?', fp);
1028                                 break;
1029                         case VSASSIGN:
1030                                 putc('=', fp);
1031                                 break;
1032                         case VSTRIMLEFT:
1033                                 putc('#', fp);
1034                                 break;
1035                         case VSTRIMLEFTMAX:
1036                                 putc('#', fp);
1037                                 putc('#', fp);
1038                                 break;
1039                         case VSTRIMRIGHT:
1040                                 putc('%', fp);
1041                                 break;
1042                         case VSTRIMRIGHTMAX:
1043                                 putc('%', fp);
1044                                 putc('%', fp);
1045                                 break;
1046                         case VSLENGTH:
1047                                 break;
1048                         default:
1049                                 out1fmt("<subtype %d>", subtype);
1050                         }
1051                         break;
1052                 case CTLENDVAR:
1053                         putc('}', fp);
1054                         break;
1055                 case CTLBACKQ:
1056                         putc('$', fp);
1057                         putc('(', fp);
1058                         shtree(bqlist->n, -1, NULL, fp);
1059                         putc(')', fp);
1060                         break;
1061                 default:
1062                         putc(*p, fp);
1063                         break;
1064                 }
1065         }
1066 }
1067
1068 static void
1069 shcmd(union node *cmd, FILE *fp)
1070 {
1071         union node *np;
1072         int first;
1073         const char *s;
1074         int dftfd;
1075
1076         first = 1;
1077         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1078                 if (!first)
1079                         putc(' ', fp);
1080                 sharg(np, fp);
1081                 first = 0;
1082         }
1083         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1084                 if (!first)
1085                         putc(' ', fp);
1086                 dftfd = 0;
1087                 switch (np->nfile.type) {
1088                 case NTO:      s = ">>"+1; dftfd = 1; break;
1089                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1090                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1091 #if ENABLE_ASH_BASH_COMPAT
1092                 case NTO2:
1093 #endif
1094                 case NTOFD:    s = ">&"; dftfd = 1; break;
1095                 case NFROM:    s = "<"; break;
1096                 case NFROMFD:  s = "<&"; break;
1097                 case NFROMTO:  s = "<>"; break;
1098                 default:       s = "*error*"; break;
1099                 }
1100                 if (np->nfile.fd != dftfd)
1101                         fprintf(fp, "%d", np->nfile.fd);
1102                 fputs(s, fp);
1103                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1104                         fprintf(fp, "%d", np->ndup.dupfd);
1105                 } else {
1106                         sharg(np->nfile.fname, fp);
1107                 }
1108                 first = 0;
1109         }
1110 }
1111
1112 static void
1113 shtree(union node *n, int ind, char *pfx, FILE *fp)
1114 {
1115         struct nodelist *lp;
1116         const char *s;
1117
1118         if (n == NULL)
1119                 return;
1120
1121         indent(ind, pfx, fp);
1122
1123         if (n == NODE_EOF) {
1124                 fputs("<EOF>", fp);
1125                 return;
1126         }
1127
1128         switch (n->type) {
1129         case NSEMI:
1130                 s = "; ";
1131                 goto binop;
1132         case NAND:
1133                 s = " && ";
1134                 goto binop;
1135         case NOR:
1136                 s = " || ";
1137  binop:
1138                 shtree(n->nbinary.ch1, ind, NULL, fp);
1139                 /* if (ind < 0) */
1140                         fputs(s, fp);
1141                 shtree(n->nbinary.ch2, ind, NULL, fp);
1142                 break;
1143         case NCMD:
1144                 shcmd(n, fp);
1145                 if (ind >= 0)
1146                         putc('\n', fp);
1147                 break;
1148         case NPIPE:
1149                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1150                         shtree(lp->n, 0, NULL, fp);
1151                         if (lp->next)
1152                                 fputs(" | ", fp);
1153                 }
1154                 if (n->npipe.pipe_backgnd)
1155                         fputs(" &", fp);
1156                 if (ind >= 0)
1157                         putc('\n', fp);
1158                 break;
1159         default:
1160                 fprintf(fp, "<node type %d>", n->type);
1161                 if (ind >= 0)
1162                         putc('\n', fp);
1163                 break;
1164         }
1165 }
1166
1167 static void
1168 showtree(union node *n)
1169 {
1170         trace_puts("showtree called\n");
1171         shtree(n, 1, NULL, stderr);
1172 }
1173
1174 #endif /* DEBUG */
1175
1176
1177 /* ============ Parser data */
1178
1179 /*
1180  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1181  */
1182 struct strlist {
1183         struct strlist *next;
1184         char *text;
1185 };
1186
1187 struct alias;
1188
1189 struct strpush {
1190         struct strpush *prev;   /* preceding string on stack */
1191         char *prev_string;
1192         int prev_left_in_line;
1193 #if ENABLE_ASH_ALIAS
1194         struct alias *ap;       /* if push was associated with an alias */
1195 #endif
1196         char *string;           /* remember the string since it may change */
1197
1198         /* Remember last two characters for pungetc. */
1199         int lastc[2];
1200
1201         /* Number of outstanding calls to pungetc. */
1202         int unget;
1203 };
1204
1205 struct parsefile {
1206         struct parsefile *prev; /* preceding file on stack */
1207         int linno;              /* current line */
1208         int pf_fd;              /* file descriptor (or -1 if string) */
1209         int left_in_line;       /* number of chars left in this line */
1210         int left_in_buffer;     /* number of chars left in this buffer past the line */
1211         char *next_to_pgetc;    /* next char in buffer */
1212         char *buf;              /* input buffer */
1213         struct strpush *strpush; /* for pushing strings at this level */
1214         struct strpush basestrpush; /* so pushing one is fast */
1215
1216         /* Remember last two characters for pungetc. */
1217         int lastc[2];
1218
1219         /* Number of outstanding calls to pungetc. */
1220         int unget;
1221 };
1222
1223 static struct parsefile basepf;        /* top level input file */
1224 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1225 static int startlinno;                 /* line # where last token started */
1226 static char *commandname;              /* currently executing command */
1227 static struct strlist *cmdenviron;     /* environment for builtin command */
1228
1229
1230 /* ============ Message printing */
1231
1232 static void
1233 ash_vmsg(const char *msg, va_list ap)
1234 {
1235         fprintf(stderr, "%s: ", arg0);
1236         if (commandname) {
1237                 if (strcmp(arg0, commandname))
1238                         fprintf(stderr, "%s: ", commandname);
1239                 if (!iflag || g_parsefile->pf_fd > 0)
1240                         fprintf(stderr, "line %d: ", startlinno);
1241         }
1242         vfprintf(stderr, msg, ap);
1243         newline_and_flush(stderr);
1244 }
1245
1246 /*
1247  * Exverror is called to raise the error exception.  If the second argument
1248  * is not NULL then error prints an error message using printf style
1249  * formatting.  It then raises the error exception.
1250  */
1251 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1252 static void
1253 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1254 {
1255 #if DEBUG
1256         if (msg) {
1257                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1258                 TRACEV((msg, ap));
1259         } else
1260                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1261         if (msg)
1262 #endif
1263                 ash_vmsg(msg, ap);
1264
1265         flush_stdout_stderr();
1266         raise_exception(cond);
1267         /* NOTREACHED */
1268 }
1269
1270 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1271 static void
1272 ash_msg_and_raise_error(const char *msg, ...)
1273 {
1274         va_list ap;
1275
1276         va_start(ap, msg);
1277         ash_vmsg_and_raise(EXERROR, msg, ap);
1278         /* NOTREACHED */
1279         va_end(ap);
1280 }
1281
1282 static void raise_error_syntax(const char *) NORETURN;
1283 static void
1284 raise_error_syntax(const char *msg)
1285 {
1286         ash_msg_and_raise_error("syntax error: %s", msg);
1287         /* NOTREACHED */
1288 }
1289
1290 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1291 static void
1292 ash_msg_and_raise(int cond, const char *msg, ...)
1293 {
1294         va_list ap;
1295
1296         va_start(ap, msg);
1297         ash_vmsg_and_raise(cond, msg, ap);
1298         /* NOTREACHED */
1299         va_end(ap);
1300 }
1301
1302 /*
1303  * error/warning routines for external builtins
1304  */
1305 static void
1306 ash_msg(const char *fmt, ...)
1307 {
1308         va_list ap;
1309
1310         va_start(ap, fmt);
1311         ash_vmsg(fmt, ap);
1312         va_end(ap);
1313 }
1314
1315 /*
1316  * Return a string describing an error.  The returned string may be a
1317  * pointer to a static buffer that will be overwritten on the next call.
1318  * Action describes the operation that got the error.
1319  */
1320 static const char *
1321 errmsg(int e, const char *em)
1322 {
1323         if (e == ENOENT || e == ENOTDIR) {
1324                 return em;
1325         }
1326         return strerror(e);
1327 }
1328
1329
1330 /* ============ Memory allocation */
1331
1332 #if 0
1333 /* I consider these wrappers nearly useless:
1334  * ok, they return you to nearest exception handler, but
1335  * how much memory do you leak in the process, making
1336  * memory starvation worse?
1337  */
1338 static void *
1339 ckrealloc(void * p, size_t nbytes)
1340 {
1341         p = realloc(p, nbytes);
1342         if (!p)
1343                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1344         return p;
1345 }
1346
1347 static void *
1348 ckmalloc(size_t nbytes)
1349 {
1350         return ckrealloc(NULL, nbytes);
1351 }
1352
1353 static void *
1354 ckzalloc(size_t nbytes)
1355 {
1356         return memset(ckmalloc(nbytes), 0, nbytes);
1357 }
1358
1359 static char *
1360 ckstrdup(const char *s)
1361 {
1362         char *p = strdup(s);
1363         if (!p)
1364                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1365         return p;
1366 }
1367 #else
1368 /* Using bbox equivalents. They exit if out of memory */
1369 # define ckrealloc xrealloc
1370 # define ckmalloc  xmalloc
1371 # define ckzalloc  xzalloc
1372 # define ckstrdup  xstrdup
1373 #endif
1374
1375 /*
1376  * It appears that grabstackstr() will barf with such alignments
1377  * because stalloc() will return a string allocated in a new stackblock.
1378  */
1379 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1380 enum {
1381         /* Most machines require the value returned from malloc to be aligned
1382          * in some way.  The following macro will get this right
1383          * on many machines.  */
1384         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1385         /* Minimum size of a block */
1386         MINSIZE = SHELL_ALIGN(504),
1387 };
1388
1389 struct stack_block {
1390         struct stack_block *prev;
1391         char space[MINSIZE];
1392 };
1393
1394 struct stackmark {
1395         struct stack_block *stackp;
1396         char *stacknxt;
1397         size_t stacknleft;
1398 };
1399
1400
1401 struct globals_memstack {
1402         struct stack_block *g_stackp; // = &stackbase;
1403         char *g_stacknxt; // = stackbase.space;
1404         char *sstrend; // = stackbase.space + MINSIZE;
1405         size_t g_stacknleft; // = MINSIZE;
1406         struct stack_block stackbase;
1407 };
1408 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1409 #define G_memstack (*ash_ptr_to_globals_memstack)
1410 #define g_stackp     (G_memstack.g_stackp    )
1411 #define g_stacknxt   (G_memstack.g_stacknxt  )
1412 #define sstrend      (G_memstack.sstrend     )
1413 #define g_stacknleft (G_memstack.g_stacknleft)
1414 #define stackbase    (G_memstack.stackbase   )
1415 #define INIT_G_memstack() do { \
1416         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1417         barrier(); \
1418         g_stackp = &stackbase; \
1419         g_stacknxt = stackbase.space; \
1420         g_stacknleft = MINSIZE; \
1421         sstrend = stackbase.space + MINSIZE; \
1422 } while (0)
1423
1424
1425 #define stackblock()     ((void *)g_stacknxt)
1426 #define stackblocksize() g_stacknleft
1427
1428 /*
1429  * Parse trees for commands are allocated in lifo order, so we use a stack
1430  * to make this more efficient, and also to avoid all sorts of exception
1431  * handling code to handle interrupts in the middle of a parse.
1432  *
1433  * The size 504 was chosen because the Ultrix malloc handles that size
1434  * well.
1435  */
1436 static void *
1437 stalloc(size_t nbytes)
1438 {
1439         char *p;
1440         size_t aligned;
1441
1442         aligned = SHELL_ALIGN(nbytes);
1443         if (aligned > g_stacknleft) {
1444                 size_t len;
1445                 size_t blocksize;
1446                 struct stack_block *sp;
1447
1448                 blocksize = aligned;
1449                 if (blocksize < MINSIZE)
1450                         blocksize = MINSIZE;
1451                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1452                 if (len < blocksize)
1453                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1454                 INT_OFF;
1455                 sp = ckmalloc(len);
1456                 sp->prev = g_stackp;
1457                 g_stacknxt = sp->space;
1458                 g_stacknleft = blocksize;
1459                 sstrend = g_stacknxt + blocksize;
1460                 g_stackp = sp;
1461                 INT_ON;
1462         }
1463         p = g_stacknxt;
1464         g_stacknxt += aligned;
1465         g_stacknleft -= aligned;
1466         return p;
1467 }
1468
1469 static void *
1470 stzalloc(size_t nbytes)
1471 {
1472         return memset(stalloc(nbytes), 0, nbytes);
1473 }
1474
1475 static void
1476 stunalloc(void *p)
1477 {
1478 #if DEBUG
1479         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1480                 write(STDERR_FILENO, "stunalloc\n", 10);
1481                 abort();
1482         }
1483 #endif
1484         g_stacknleft += g_stacknxt - (char *)p;
1485         g_stacknxt = p;
1486 }
1487
1488 /*
1489  * Like strdup but works with the ash stack.
1490  */
1491 static char *
1492 sstrdup(const char *p)
1493 {
1494         size_t len = strlen(p) + 1;
1495         return memcpy(stalloc(len), p, len);
1496 }
1497
1498 static inline void
1499 grabstackblock(size_t len)
1500 {
1501         stalloc(len);
1502 }
1503
1504 static void
1505 pushstackmark(struct stackmark *mark, size_t len)
1506 {
1507         mark->stackp = g_stackp;
1508         mark->stacknxt = g_stacknxt;
1509         mark->stacknleft = g_stacknleft;
1510         grabstackblock(len);
1511 }
1512
1513 static void
1514 setstackmark(struct stackmark *mark)
1515 {
1516         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1517 }
1518
1519 static void
1520 popstackmark(struct stackmark *mark)
1521 {
1522         struct stack_block *sp;
1523
1524         if (!mark->stackp)
1525                 return;
1526
1527         INT_OFF;
1528         while (g_stackp != mark->stackp) {
1529                 sp = g_stackp;
1530                 g_stackp = sp->prev;
1531                 free(sp);
1532         }
1533         g_stacknxt = mark->stacknxt;
1534         g_stacknleft = mark->stacknleft;
1535         sstrend = mark->stacknxt + mark->stacknleft;
1536         INT_ON;
1537 }
1538
1539 /*
1540  * When the parser reads in a string, it wants to stick the string on the
1541  * stack and only adjust the stack pointer when it knows how big the
1542  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1543  * of space on top of the stack and stackblocklen returns the length of
1544  * this block.  Growstackblock will grow this space by at least one byte,
1545  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1546  * part of the block that has been used.
1547  */
1548 static void
1549 growstackblock(void)
1550 {
1551         size_t newlen;
1552
1553         newlen = g_stacknleft * 2;
1554         if (newlen < g_stacknleft)
1555                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1556         if (newlen < 128)
1557                 newlen += 128;
1558
1559         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1560                 struct stack_block *sp;
1561                 struct stack_block *prevstackp;
1562                 size_t grosslen;
1563
1564                 INT_OFF;
1565                 sp = g_stackp;
1566                 prevstackp = sp->prev;
1567                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1568                 sp = ckrealloc(sp, grosslen);
1569                 sp->prev = prevstackp;
1570                 g_stackp = sp;
1571                 g_stacknxt = sp->space;
1572                 g_stacknleft = newlen;
1573                 sstrend = sp->space + newlen;
1574                 INT_ON;
1575         } else {
1576                 char *oldspace = g_stacknxt;
1577                 size_t oldlen = g_stacknleft;
1578                 char *p = stalloc(newlen);
1579
1580                 /* free the space we just allocated */
1581                 g_stacknxt = memcpy(p, oldspace, oldlen);
1582                 g_stacknleft += newlen;
1583         }
1584 }
1585
1586 /*
1587  * The following routines are somewhat easier to use than the above.
1588  * The user declares a variable of type STACKSTR, which may be declared
1589  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1590  * the user uses the macro STPUTC to add characters to the string.  In
1591  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1592  * grown as necessary.  When the user is done, she can just leave the
1593  * string there and refer to it using stackblock().  Or she can allocate
1594  * the space for it using grabstackstr().  If it is necessary to allow
1595  * someone else to use the stack temporarily and then continue to grow
1596  * the string, the user should use grabstack to allocate the space, and
1597  * then call ungrabstr(p) to return to the previous mode of operation.
1598  *
1599  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1600  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1601  * is space for at least one character.
1602  */
1603 static void *
1604 growstackstr(void)
1605 {
1606         size_t len = stackblocksize();
1607         growstackblock();
1608         return (char *)stackblock() + len;
1609 }
1610
1611 /*
1612  * Called from CHECKSTRSPACE.
1613  */
1614 static char *
1615 makestrspace(size_t newlen, char *p)
1616 {
1617         size_t len = p - g_stacknxt;
1618         size_t size;
1619
1620         for (;;) {
1621                 size_t nleft;
1622
1623                 size = stackblocksize();
1624                 nleft = size - len;
1625                 if (nleft >= newlen)
1626                         break;
1627                 growstackblock();
1628         }
1629         return (char *)stackblock() + len;
1630 }
1631
1632 static char *
1633 stack_nputstr(const char *s, size_t n, char *p)
1634 {
1635         p = makestrspace(n, p);
1636         p = (char *)memcpy(p, s, n) + n;
1637         return p;
1638 }
1639
1640 static char *
1641 stack_putstr(const char *s, char *p)
1642 {
1643         return stack_nputstr(s, strlen(s), p);
1644 }
1645
1646 static char *
1647 _STPUTC(int c, char *p)
1648 {
1649         if (p == sstrend)
1650                 p = growstackstr();
1651         *p++ = c;
1652         return p;
1653 }
1654
1655 #define STARTSTACKSTR(p)        ((p) = stackblock())
1656 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1657 #define CHECKSTRSPACE(n, p) do { \
1658         char *q = (p); \
1659         size_t l = (n); \
1660         size_t m = sstrend - q; \
1661         if (l > m) \
1662                 (p) = makestrspace(l, q); \
1663 } while (0)
1664 #define USTPUTC(c, p)           (*(p)++ = (c))
1665 #define STACKSTRNUL(p) do { \
1666         if ((p) == sstrend) \
1667                 (p) = growstackstr(); \
1668         *(p) = '\0'; \
1669 } while (0)
1670 #define STUNPUTC(p)             (--(p))
1671 #define STTOPC(p)               ((p)[-1])
1672 #define STADJUST(amount, p)     ((p) += (amount))
1673
1674 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1675 #define ungrabstackstr(s, p)    stunalloc(s)
1676 #define stackstrend()           ((void *)sstrend)
1677
1678
1679 /* ============ String helpers */
1680
1681 /*
1682  * prefix -- see if pfx is a prefix of string.
1683  */
1684 static char *
1685 prefix(const char *string, const char *pfx)
1686 {
1687         while (*pfx) {
1688                 if (*pfx++ != *string++)
1689                         return NULL;
1690         }
1691         return (char *) string;
1692 }
1693
1694 /*
1695  * Check for a valid number.  This should be elsewhere.
1696  */
1697 static int
1698 is_number(const char *p)
1699 {
1700         do {
1701                 if (!isdigit(*p))
1702                         return 0;
1703         } while (*++p != '\0');
1704         return 1;
1705 }
1706
1707 /*
1708  * Convert a string of digits to an integer, printing an error message on
1709  * failure.
1710  */
1711 static int
1712 number(const char *s)
1713 {
1714         if (!is_number(s))
1715                 ash_msg_and_raise_error(msg_illnum, s);
1716         return atoi(s);
1717 }
1718
1719 /*
1720  * Produce a possibly single quoted string suitable as input to the shell.
1721  * The return string is allocated on the stack.
1722  */
1723 static char *
1724 single_quote(const char *s)
1725 {
1726         char *p;
1727
1728         STARTSTACKSTR(p);
1729
1730         do {
1731                 char *q;
1732                 size_t len;
1733
1734                 len = strchrnul(s, '\'') - s;
1735
1736                 q = p = makestrspace(len + 3, p);
1737
1738                 *q++ = '\'';
1739                 q = (char *)memcpy(q, s, len) + len;
1740                 *q++ = '\'';
1741                 s += len;
1742
1743                 STADJUST(q - p, p);
1744
1745                 if (*s != '\'')
1746                         break;
1747                 len = 0;
1748                 do len++; while (*++s == '\'');
1749
1750                 q = p = makestrspace(len + 3, p);
1751
1752                 *q++ = '"';
1753                 q = (char *)memcpy(q, s - len, len) + len;
1754                 *q++ = '"';
1755
1756                 STADJUST(q - p, p);
1757         } while (*s);
1758
1759         USTPUTC('\0', p);
1760
1761         return stackblock();
1762 }
1763
1764
1765 /* ============ nextopt */
1766
1767 static char **argptr;                  /* argument list for builtin commands */
1768 static char *optionarg;                /* set by nextopt (like getopt) */
1769 static char *optptr;                   /* used by nextopt */
1770
1771 /*
1772  * XXX - should get rid of. Have all builtins use getopt(3).
1773  * The library getopt must have the BSD extension static variable
1774  * "optreset", otherwise it can't be used within the shell safely.
1775  *
1776  * Standard option processing (a la getopt) for builtin routines.
1777  * The only argument that is passed to nextopt is the option string;
1778  * the other arguments are unnecessary. It returns the character,
1779  * or '\0' on end of input.
1780  */
1781 static int
1782 nextopt(const char *optstring)
1783 {
1784         char *p;
1785         const char *q;
1786         char c;
1787
1788         p = optptr;
1789         if (p == NULL || *p == '\0') {
1790                 /* We ate entire "-param", take next one */
1791                 p = *argptr;
1792                 if (p == NULL)
1793                         return '\0';
1794                 if (*p != '-')
1795                         return '\0';
1796                 if (*++p == '\0') /* just "-" ? */
1797                         return '\0';
1798                 argptr++;
1799                 if (LONE_DASH(p)) /* "--" ? */
1800                         return '\0';
1801                 /* p => next "-param" */
1802         }
1803         /* p => some option char in the middle of a "-param" */
1804         c = *p++;
1805         for (q = optstring; *q != c;) {
1806                 if (*q == '\0')
1807                         ash_msg_and_raise_error("illegal option -%c", c);
1808                 if (*++q == ':')
1809                         q++;
1810         }
1811         if (*++q == ':') {
1812                 if (*p == '\0') {
1813                         p = *argptr++;
1814                         if (p == NULL)
1815                                 ash_msg_and_raise_error("no arg for -%c option", c);
1816                 }
1817                 optionarg = p;
1818                 p = NULL;
1819         }
1820         optptr = p;
1821         return c;
1822 }
1823
1824
1825 /* ============ Shell variables */
1826
1827 /*
1828  * The parsefile structure pointed to by the global variable parsefile
1829  * contains information about the current file being read.
1830  */
1831 struct shparam {
1832         int nparam;             /* # of positional parameters (without $0) */
1833 #if ENABLE_ASH_GETOPTS
1834         int optind;             /* next parameter to be processed by getopts */
1835         int optoff;             /* used by getopts */
1836 #endif
1837         unsigned char malloced; /* if parameter list dynamically allocated */
1838         char **p;               /* parameter list */
1839 };
1840
1841 /*
1842  * Free the list of positional parameters.
1843  */
1844 static void
1845 freeparam(volatile struct shparam *param)
1846 {
1847         if (param->malloced) {
1848                 char **ap, **ap1;
1849                 ap = ap1 = param->p;
1850                 while (*ap)
1851                         free(*ap++);
1852                 free(ap1);
1853         }
1854 }
1855
1856 #if ENABLE_ASH_GETOPTS
1857 static void FAST_FUNC getoptsreset(const char *value);
1858 #endif
1859
1860 struct var {
1861         struct var *next;               /* next entry in hash list */
1862         int flags;                      /* flags are defined above */
1863         const char *var_text;           /* name=value */
1864         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1865                                         /* the variable gets set/unset */
1866 };
1867
1868 struct localvar {
1869         struct localvar *next;          /* next local variable in list */
1870         struct var *vp;                 /* the variable that was made local */
1871         int flags;                      /* saved flags */
1872         const char *text;               /* saved text */
1873 };
1874
1875 /* flags */
1876 #define VEXPORT         0x01    /* variable is exported */
1877 #define VREADONLY       0x02    /* variable cannot be modified */
1878 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1879 #define VTEXTFIXED      0x08    /* text is statically allocated */
1880 #define VSTACK          0x10    /* text is allocated on the stack */
1881 #define VUNSET          0x20    /* the variable is not set */
1882 #define VNOFUNC         0x40    /* don't call the callback function */
1883 #define VNOSET          0x80    /* do not set variable - just readonly test */
1884 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1885 #if ENABLE_ASH_RANDOM_SUPPORT
1886 # define VDYNAMIC       0x200   /* dynamic variable */
1887 #else
1888 # define VDYNAMIC       0
1889 #endif
1890
1891
1892 /* Need to be before varinit_data[] */
1893 #if ENABLE_LOCALE_SUPPORT
1894 static void FAST_FUNC
1895 change_lc_all(const char *value)
1896 {
1897         if (value && *value != '\0')
1898                 setlocale(LC_ALL, value);
1899 }
1900 static void FAST_FUNC
1901 change_lc_ctype(const char *value)
1902 {
1903         if (value && *value != '\0')
1904                 setlocale(LC_CTYPE, value);
1905 }
1906 #endif
1907 #if ENABLE_ASH_MAIL
1908 static void chkmail(void);
1909 static void changemail(const char *var_value) FAST_FUNC;
1910 #else
1911 # define chkmail()  ((void)0)
1912 #endif
1913 static void changepath(const char *) FAST_FUNC;
1914 #if ENABLE_ASH_RANDOM_SUPPORT
1915 static void change_random(const char *) FAST_FUNC;
1916 #endif
1917
1918 static const struct {
1919         int flags;
1920         const char *var_text;
1921         void (*var_func)(const char *) FAST_FUNC;
1922 } varinit_data[] = {
1923         /*
1924          * Note: VEXPORT would not work correctly here for NOFORK applets:
1925          * some environment strings may be constant.
1926          */
1927         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1928 #if ENABLE_ASH_MAIL
1929         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1930         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1931 #endif
1932         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1933         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1934         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1935         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1936 #if ENABLE_ASH_GETOPTS
1937         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
1938 #endif
1939 #if ENABLE_ASH_RANDOM_SUPPORT
1940         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
1941 #endif
1942 #if ENABLE_LOCALE_SUPPORT
1943         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
1944         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
1945 #endif
1946 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1947         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
1948 #endif
1949 };
1950
1951 struct redirtab;
1952
1953 struct globals_var {
1954         struct shparam shellparam;      /* $@ current positional parameters */
1955         struct redirtab *redirlist;
1956         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1957         struct var *vartab[VTABSIZE];
1958         struct var varinit[ARRAY_SIZE(varinit_data)];
1959 };
1960 extern struct globals_var *const ash_ptr_to_globals_var;
1961 #define G_var (*ash_ptr_to_globals_var)
1962 #define shellparam    (G_var.shellparam   )
1963 //#define redirlist     (G_var.redirlist    )
1964 #define preverrout_fd (G_var.preverrout_fd)
1965 #define vartab        (G_var.vartab       )
1966 #define varinit       (G_var.varinit      )
1967 #define INIT_G_var() do { \
1968         unsigned i; \
1969         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1970         barrier(); \
1971         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1972                 varinit[i].flags    = varinit_data[i].flags; \
1973                 varinit[i].var_text = varinit_data[i].var_text; \
1974                 varinit[i].var_func = varinit_data[i].var_func; \
1975         } \
1976 } while (0)
1977
1978 #define vifs      varinit[0]
1979 #if ENABLE_ASH_MAIL
1980 # define vmail    (&vifs)[1]
1981 # define vmpath   (&vmail)[1]
1982 # define vpath    (&vmpath)[1]
1983 #else
1984 # define vpath    (&vifs)[1]
1985 #endif
1986 #define vps1      (&vpath)[1]
1987 #define vps2      (&vps1)[1]
1988 #define vps4      (&vps2)[1]
1989 #if ENABLE_ASH_GETOPTS
1990 # define voptind  (&vps4)[1]
1991 # if ENABLE_ASH_RANDOM_SUPPORT
1992 #  define vrandom (&voptind)[1]
1993 # endif
1994 #else
1995 # if ENABLE_ASH_RANDOM_SUPPORT
1996 #  define vrandom (&vps4)[1]
1997 # endif
1998 #endif
1999
2000 /*
2001  * The following macros access the values of the above variables.
2002  * They have to skip over the name.  They return the null string
2003  * for unset variables.
2004  */
2005 #define ifsval()        (vifs.var_text + 4)
2006 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2007 #if ENABLE_ASH_MAIL
2008 # define mailval()      (vmail.var_text + 5)
2009 # define mpathval()     (vmpath.var_text + 9)
2010 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2011 #endif
2012 #define pathval()       (vpath.var_text + 5)
2013 #define ps1val()        (vps1.var_text + 4)
2014 #define ps2val()        (vps2.var_text + 4)
2015 #define ps4val()        (vps4.var_text + 4)
2016 #if ENABLE_ASH_GETOPTS
2017 # define optindval()    (voptind.var_text + 7)
2018 #endif
2019
2020 #if ENABLE_ASH_GETOPTS
2021 static void FAST_FUNC
2022 getoptsreset(const char *value)
2023 {
2024         shellparam.optind = number(value) ?: 1;
2025         shellparam.optoff = -1;
2026 }
2027 #endif
2028
2029 /*
2030  * Compares two strings up to the first = or '\0'.  The first
2031  * string must be terminated by '='; the second may be terminated by
2032  * either '=' or '\0'.
2033  */
2034 static int
2035 varcmp(const char *p, const char *q)
2036 {
2037         int c, d;
2038
2039         while ((c = *p) == (d = *q)) {
2040                 if (c == '\0' || c == '=')
2041                         goto out;
2042                 p++;
2043                 q++;
2044         }
2045         if (c == '=')
2046                 c = '\0';
2047         if (d == '=')
2048                 d = '\0';
2049  out:
2050         return c - d;
2051 }
2052
2053 /*
2054  * Find the appropriate entry in the hash table from the name.
2055  */
2056 static struct var **
2057 hashvar(const char *p)
2058 {
2059         unsigned hashval;
2060
2061         hashval = ((unsigned char) *p) << 4;
2062         while (*p && *p != '=')
2063                 hashval += (unsigned char) *p++;
2064         return &vartab[hashval % VTABSIZE];
2065 }
2066
2067 static int
2068 vpcmp(const void *a, const void *b)
2069 {
2070         return varcmp(*(const char **)a, *(const char **)b);
2071 }
2072
2073 /*
2074  * This routine initializes the builtin variables.
2075  */
2076 static void
2077 initvar(void)
2078 {
2079         struct var *vp;
2080         struct var *end;
2081         struct var **vpp;
2082
2083         /*
2084          * PS1 depends on uid
2085          */
2086 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2087         vps1.var_text = "PS1=\\w \\$ ";
2088 #else
2089         if (!geteuid())
2090                 vps1.var_text = "PS1=# ";
2091 #endif
2092         vp = varinit;
2093         end = vp + ARRAY_SIZE(varinit);
2094         do {
2095                 vpp = hashvar(vp->var_text);
2096                 vp->next = *vpp;
2097                 *vpp = vp;
2098         } while (++vp < end);
2099 }
2100
2101 static struct var **
2102 findvar(struct var **vpp, const char *name)
2103 {
2104         for (; *vpp; vpp = &(*vpp)->next) {
2105                 if (varcmp((*vpp)->var_text, name) == 0) {
2106                         break;
2107                 }
2108         }
2109         return vpp;
2110 }
2111
2112 /*
2113  * Find the value of a variable.  Returns NULL if not set.
2114  */
2115 static const char* FAST_FUNC
2116 lookupvar(const char *name)
2117 {
2118         struct var *v;
2119
2120         v = *findvar(hashvar(name), name);
2121         if (v) {
2122 #if ENABLE_ASH_RANDOM_SUPPORT
2123         /*
2124          * Dynamic variables are implemented roughly the same way they are
2125          * in bash. Namely, they're "special" so long as they aren't unset.
2126          * As soon as they're unset, they're no longer dynamic, and dynamic
2127          * lookup will no longer happen at that point. -- PFM.
2128          */
2129                 if (v->flags & VDYNAMIC)
2130                         v->var_func(NULL);
2131 #endif
2132                 if (!(v->flags & VUNSET))
2133                         return var_end(v->var_text);
2134         }
2135         return NULL;
2136 }
2137
2138 static void
2139 reinit_unicode_for_ash(void)
2140 {
2141         /* Unicode support should be activated even if LANG is set
2142          * _during_ shell execution, not only if it was set when
2143          * shell was started. Therefore, re-check LANG every time:
2144          */
2145         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2146          || ENABLE_UNICODE_USING_LOCALE
2147         ) {
2148                 const char *s = lookupvar("LC_ALL");
2149                 if (!s) s = lookupvar("LC_CTYPE");
2150                 if (!s) s = lookupvar("LANG");
2151                 reinit_unicode(s);
2152         }
2153 }
2154
2155 /*
2156  * Search the environment of a builtin command.
2157  */
2158 static const char *
2159 bltinlookup(const char *name)
2160 {
2161         struct strlist *sp;
2162
2163         for (sp = cmdenviron; sp; sp = sp->next) {
2164                 if (varcmp(sp->text, name) == 0)
2165                         return var_end(sp->text);
2166         }
2167         return lookupvar(name);
2168 }
2169
2170 /*
2171  * Same as setvar except that the variable and value are passed in
2172  * the first argument as name=value.  Since the first argument will
2173  * be actually stored in the table, it should not be a string that
2174  * will go away.
2175  * Called with interrupts off.
2176  */
2177 static void
2178 setvareq(char *s, int flags)
2179 {
2180         struct var *vp, **vpp;
2181
2182         vpp = hashvar(s);
2183         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2184         vp = *findvar(vpp, s);
2185         if (vp) {
2186                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2187                         const char *n;
2188
2189                         if (flags & VNOSAVE)
2190                                 free(s);
2191                         n = vp->var_text;
2192                         exitstatus = 1;
2193                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2194                 }
2195
2196                 if (flags & VNOSET)
2197                         return;
2198
2199                 if (vp->var_func && !(flags & VNOFUNC))
2200                         vp->var_func(var_end(s));
2201
2202                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2203                         free((char*)vp->var_text);
2204
2205                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2206         } else {
2207                 /* variable s is not found */
2208                 if (flags & VNOSET)
2209                         return;
2210                 vp = ckzalloc(sizeof(*vp));
2211                 vp->next = *vpp;
2212                 /*vp->func = NULL; - ckzalloc did it */
2213                 *vpp = vp;
2214         }
2215         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2216                 s = ckstrdup(s);
2217         vp->var_text = s;
2218         vp->flags = flags;
2219 }
2220
2221 /*
2222  * Set the value of a variable.  The flags argument is ored with the
2223  * flags of the variable.  If val is NULL, the variable is unset.
2224  */
2225 static void
2226 setvar(const char *name, const char *val, int flags)
2227 {
2228         const char *q;
2229         char *p;
2230         char *nameeq;
2231         size_t namelen;
2232         size_t vallen;
2233
2234         q = endofname(name);
2235         p = strchrnul(q, '=');
2236         namelen = p - name;
2237         if (!namelen || p != q)
2238                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2239         vallen = 0;
2240         if (val == NULL) {
2241                 flags |= VUNSET;
2242         } else {
2243                 vallen = strlen(val);
2244         }
2245
2246         INT_OFF;
2247         nameeq = ckmalloc(namelen + vallen + 2);
2248         p = memcpy(nameeq, name, namelen) + namelen;
2249         if (val) {
2250                 *p++ = '=';
2251                 p = memcpy(p, val, vallen) + vallen;
2252         }
2253         *p = '\0';
2254         setvareq(nameeq, flags | VNOSAVE);
2255         INT_ON;
2256 }
2257
2258 static void FAST_FUNC
2259 setvar0(const char *name, const char *val)
2260 {
2261         setvar(name, val, 0);
2262 }
2263
2264 /*
2265  * Unset the specified variable.
2266  */
2267 static int
2268 unsetvar(const char *s)
2269 {
2270         struct var **vpp;
2271         struct var *vp;
2272         int retval;
2273
2274         vpp = findvar(hashvar(s), s);
2275         vp = *vpp;
2276         retval = 2;
2277         if (vp) {
2278                 int flags = vp->flags;
2279
2280                 retval = 1;
2281                 if (flags & VREADONLY)
2282                         goto out;
2283 #if ENABLE_ASH_RANDOM_SUPPORT
2284                 vp->flags &= ~VDYNAMIC;
2285 #endif
2286                 if (flags & VUNSET)
2287                         goto ok;
2288                 if ((flags & VSTRFIXED) == 0) {
2289                         INT_OFF;
2290                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2291                                 free((char*)vp->var_text);
2292                         *vpp = vp->next;
2293                         free(vp);
2294                         INT_ON;
2295                 } else {
2296                         setvar0(s, NULL);
2297                         vp->flags &= ~VEXPORT;
2298                 }
2299  ok:
2300                 retval = 0;
2301         }
2302  out:
2303         return retval;
2304 }
2305
2306 /*
2307  * Process a linked list of variable assignments.
2308  */
2309 static void
2310 listsetvar(struct strlist *list_set_var, int flags)
2311 {
2312         struct strlist *lp = list_set_var;
2313
2314         if (!lp)
2315                 return;
2316         INT_OFF;
2317         do {
2318                 setvareq(lp->text, flags);
2319                 lp = lp->next;
2320         } while (lp);
2321         INT_ON;
2322 }
2323
2324 /*
2325  * Generate a list of variables satisfying the given conditions.
2326  */
2327 static char **
2328 listvars(int on, int off, char ***end)
2329 {
2330         struct var **vpp;
2331         struct var *vp;
2332         char **ep;
2333         int mask;
2334
2335         STARTSTACKSTR(ep);
2336         vpp = vartab;
2337         mask = on | off;
2338         do {
2339                 for (vp = *vpp; vp; vp = vp->next) {
2340                         if ((vp->flags & mask) == on) {
2341                                 if (ep == stackstrend())
2342                                         ep = growstackstr();
2343                                 *ep++ = (char*)vp->var_text;
2344                         }
2345                 }
2346         } while (++vpp < vartab + VTABSIZE);
2347         if (ep == stackstrend())
2348                 ep = growstackstr();
2349         if (end)
2350                 *end = ep;
2351         *ep++ = NULL;
2352         return grabstackstr(ep);
2353 }
2354
2355
2356 /* ============ Path search helper
2357  *
2358  * The variable path (passed by reference) should be set to the start
2359  * of the path before the first call; path_advance will update
2360  * this value as it proceeds.  Successive calls to path_advance will return
2361  * the possible path expansions in sequence.  If an option (indicated by
2362  * a percent sign) appears in the path entry then the global variable
2363  * pathopt will be set to point to it; otherwise pathopt will be set to
2364  * NULL.
2365  */
2366 static const char *pathopt;     /* set by path_advance */
2367
2368 static char *
2369 path_advance(const char **path, const char *name)
2370 {
2371         const char *p;
2372         char *q;
2373         const char *start;
2374         size_t len;
2375
2376         if (*path == NULL)
2377                 return NULL;
2378         start = *path;
2379         for (p = start; *p && *p != ':' && *p != '%'; p++)
2380                 continue;
2381         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2382         while (stackblocksize() < len)
2383                 growstackblock();
2384         q = stackblock();
2385         if (p != start) {
2386                 memcpy(q, start, p - start);
2387                 q += p - start;
2388                 *q++ = '/';
2389         }
2390         strcpy(q, name);
2391         pathopt = NULL;
2392         if (*p == '%') {
2393                 pathopt = ++p;
2394                 while (*p && *p != ':')
2395                         p++;
2396         }
2397         if (*p == ':')
2398                 *path = p + 1;
2399         else
2400                 *path = NULL;
2401         return stalloc(len);
2402 }
2403
2404
2405 /* ============ Prompt */
2406
2407 static smallint doprompt;                   /* if set, prompt the user */
2408 static smallint needprompt;                 /* true if interactive and at start of line */
2409
2410 #if ENABLE_FEATURE_EDITING
2411 static line_input_t *line_input_state;
2412 static const char *cmdedit_prompt;
2413 static void
2414 putprompt(const char *s)
2415 {
2416         if (ENABLE_ASH_EXPAND_PRMT) {
2417                 free((char*)cmdedit_prompt);
2418                 cmdedit_prompt = ckstrdup(s);
2419                 return;
2420         }
2421         cmdedit_prompt = s;
2422 }
2423 #else
2424 static void
2425 putprompt(const char *s)
2426 {
2427         out2str(s);
2428 }
2429 #endif
2430
2431 #if ENABLE_ASH_EXPAND_PRMT
2432 /* expandstr() needs parsing machinery, so it is far away ahead... */
2433 static const char *expandstr(const char *ps);
2434 #else
2435 #define expandstr(s) s
2436 #endif
2437
2438 static void
2439 setprompt_if(smallint do_set, int whichprompt)
2440 {
2441         const char *prompt;
2442         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2443
2444         if (!do_set)
2445                 return;
2446
2447         needprompt = 0;
2448
2449         switch (whichprompt) {
2450         case 1:
2451                 prompt = ps1val();
2452                 break;
2453         case 2:
2454                 prompt = ps2val();
2455                 break;
2456         default:                        /* 0 */
2457                 prompt = nullstr;
2458         }
2459 #if ENABLE_ASH_EXPAND_PRMT
2460         pushstackmark(&smark, stackblocksize());
2461 #endif
2462         putprompt(expandstr(prompt));
2463 #if ENABLE_ASH_EXPAND_PRMT
2464         popstackmark(&smark);
2465 #endif
2466 }
2467
2468
2469 /* ============ The cd and pwd commands */
2470
2471 #define CD_PHYSICAL 1
2472 #define CD_PRINT 2
2473
2474 static int
2475 cdopt(void)
2476 {
2477         int flags = 0;
2478         int i, j;
2479
2480         j = 'L';
2481         while ((i = nextopt("LP")) != '\0') {
2482                 if (i != j) {
2483                         flags ^= CD_PHYSICAL;
2484                         j = i;
2485                 }
2486         }
2487
2488         return flags;
2489 }
2490
2491 /*
2492  * Update curdir (the name of the current directory) in response to a
2493  * cd command.
2494  */
2495 static const char *
2496 updatepwd(const char *dir)
2497 {
2498         char *new;
2499         char *p;
2500         char *cdcomppath;
2501         const char *lim;
2502
2503         cdcomppath = sstrdup(dir);
2504         STARTSTACKSTR(new);
2505         if (*dir != '/') {
2506                 if (curdir == nullstr)
2507                         return 0;
2508                 new = stack_putstr(curdir, new);
2509         }
2510         new = makestrspace(strlen(dir) + 2, new);
2511         lim = (char *)stackblock() + 1;
2512         if (*dir != '/') {
2513                 if (new[-1] != '/')
2514                         USTPUTC('/', new);
2515                 if (new > lim && *lim == '/')
2516                         lim++;
2517         } else {
2518                 USTPUTC('/', new);
2519                 cdcomppath++;
2520                 if (dir[1] == '/' && dir[2] != '/') {
2521                         USTPUTC('/', new);
2522                         cdcomppath++;
2523                         lim++;
2524                 }
2525         }
2526         p = strtok(cdcomppath, "/");
2527         while (p) {
2528                 switch (*p) {
2529                 case '.':
2530                         if (p[1] == '.' && p[2] == '\0') {
2531                                 while (new > lim) {
2532                                         STUNPUTC(new);
2533                                         if (new[-1] == '/')
2534                                                 break;
2535                                 }
2536                                 break;
2537                         }
2538                         if (p[1] == '\0')
2539                                 break;
2540                         /* fall through */
2541                 default:
2542                         new = stack_putstr(p, new);
2543                         USTPUTC('/', new);
2544                 }
2545                 p = strtok(NULL, "/");
2546         }
2547         if (new > lim)
2548                 STUNPUTC(new);
2549         *new = 0;
2550         return stackblock();
2551 }
2552
2553 /*
2554  * Find out what the current directory is. If we already know the current
2555  * directory, this routine returns immediately.
2556  */
2557 static char *
2558 getpwd(void)
2559 {
2560         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2561         return dir ? dir : nullstr;
2562 }
2563
2564 static void
2565 setpwd(const char *val, int setold)
2566 {
2567         char *oldcur, *dir;
2568
2569         oldcur = dir = curdir;
2570
2571         if (setold) {
2572                 setvar("OLDPWD", oldcur, VEXPORT);
2573         }
2574         INT_OFF;
2575         if (physdir != nullstr) {
2576                 if (physdir != oldcur)
2577                         free(physdir);
2578                 physdir = nullstr;
2579         }
2580         if (oldcur == val || !val) {
2581                 char *s = getpwd();
2582                 physdir = s;
2583                 if (!val)
2584                         dir = s;
2585         } else
2586                 dir = ckstrdup(val);
2587         if (oldcur != dir && oldcur != nullstr) {
2588                 free(oldcur);
2589         }
2590         curdir = dir;
2591         INT_ON;
2592         setvar("PWD", dir, VEXPORT);
2593 }
2594
2595 static void hashcd(void);
2596
2597 /*
2598  * Actually do the chdir.  We also call hashcd to let other routines
2599  * know that the current directory has changed.
2600  */
2601 static int
2602 docd(const char *dest, int flags)
2603 {
2604         const char *dir = NULL;
2605         int err;
2606
2607         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2608
2609         INT_OFF;
2610         if (!(flags & CD_PHYSICAL)) {
2611                 dir = updatepwd(dest);
2612                 if (dir)
2613                         dest = dir;
2614         }
2615         err = chdir(dest);
2616         if (err)
2617                 goto out;
2618         setpwd(dir, 1);
2619         hashcd();
2620  out:
2621         INT_ON;
2622         return err;
2623 }
2624
2625 static int FAST_FUNC
2626 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2627 {
2628         const char *dest;
2629         const char *path;
2630         const char *p;
2631         char c;
2632         struct stat statb;
2633         int flags;
2634
2635         flags = cdopt();
2636         dest = *argptr;
2637         if (!dest)
2638                 dest = bltinlookup("HOME");
2639         else if (LONE_DASH(dest)) {
2640                 dest = bltinlookup("OLDPWD");
2641                 flags |= CD_PRINT;
2642         }
2643         if (!dest)
2644                 dest = nullstr;
2645         if (*dest == '/')
2646                 goto step6;
2647         if (*dest == '.') {
2648                 c = dest[1];
2649  dotdot:
2650                 switch (c) {
2651                 case '\0':
2652                 case '/':
2653                         goto step6;
2654                 case '.':
2655                         c = dest[2];
2656                         if (c != '.')
2657                                 goto dotdot;
2658                 }
2659         }
2660         if (!*dest)
2661                 dest = ".";
2662         path = bltinlookup("CDPATH");
2663         while (path) {
2664                 c = *path;
2665                 p = path_advance(&path, dest);
2666                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2667                         if (c && c != ':')
2668                                 flags |= CD_PRINT;
2669  docd:
2670                         if (!docd(p, flags))
2671                                 goto out;
2672                         goto err;
2673                 }
2674         }
2675
2676  step6:
2677         p = dest;
2678         goto docd;
2679
2680  err:
2681         ash_msg_and_raise_error("can't cd to %s", dest);
2682         /* NOTREACHED */
2683  out:
2684         if (flags & CD_PRINT)
2685                 out1fmt("%s\n", curdir);
2686         return 0;
2687 }
2688
2689 static int FAST_FUNC
2690 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2691 {
2692         int flags;
2693         const char *dir = curdir;
2694
2695         flags = cdopt();
2696         if (flags) {
2697                 if (physdir == nullstr)
2698                         setpwd(dir, 0);
2699                 dir = physdir;
2700         }
2701         out1fmt("%s\n", dir);
2702         return 0;
2703 }
2704
2705
2706 /* ============ ... */
2707
2708
2709 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2710
2711 /* Syntax classes */
2712 #define CWORD     0             /* character is nothing special */
2713 #define CNL       1             /* newline character */
2714 #define CBACK     2             /* a backslash character */
2715 #define CSQUOTE   3             /* single quote */
2716 #define CDQUOTE   4             /* double quote */
2717 #define CENDQUOTE 5             /* a terminating quote */
2718 #define CBQUOTE   6             /* backwards single quote */
2719 #define CVAR      7             /* a dollar sign */
2720 #define CENDVAR   8             /* a '}' character */
2721 #define CLP       9             /* a left paren in arithmetic */
2722 #define CRP      10             /* a right paren in arithmetic */
2723 #define CENDFILE 11             /* end of file */
2724 #define CCTL     12             /* like CWORD, except it must be escaped */
2725 #define CSPCL    13             /* these terminate a word */
2726 #define CIGN     14             /* character should be ignored */
2727
2728 #define PEOF     256
2729 #if ENABLE_ASH_ALIAS
2730 # define PEOA    257
2731 #endif
2732
2733 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2734
2735 #if ENABLE_SH_MATH_SUPPORT
2736 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2737 #else
2738 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2739 #endif
2740 static const uint16_t S_I_T[] ALIGN2 = {
2741 #if ENABLE_ASH_ALIAS
2742         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2743 #endif
2744         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2745         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2746         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2747         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2748         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2749         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2750         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2751         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2752         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2753         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2754         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2755 #if !USE_SIT_FUNCTION
2756         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2757         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2758         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2759 #endif
2760 #undef SIT_ITEM
2761 };
2762 /* Constants below must match table above */
2763 enum {
2764 #if ENABLE_ASH_ALIAS
2765         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2766 #endif
2767         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2768         CNL_CNL_CNL_CNL                    , /*  2 */
2769         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2770         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2771         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2772         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2773         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2774         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2775         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2776         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2777         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2778         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2779         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2780         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2781 };
2782
2783 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2784  * caller must ensure proper cast on it if c is *char_ptr!
2785  */
2786 /* Values for syntax param */
2787 #define BASESYNTAX 0    /* not in quotes */
2788 #define DQSYNTAX   1    /* in double quotes */
2789 #define SQSYNTAX   2    /* in single quotes */
2790 #define ARISYNTAX  3    /* in arithmetic */
2791 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2792
2793 #if USE_SIT_FUNCTION
2794
2795 static int
2796 SIT(int c, int syntax)
2797 {
2798         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2799         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2800         /*
2801          * This causes '/' to be prepended with CTLESC in dquoted string,
2802          * making "./file"* treated incorrectly because we feed
2803          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2804          * The "homegrown" glob implementation is okay with that,
2805          * but glibc one isn't. With '/' always treated as CWORD,
2806          * both work fine.
2807          */
2808 # if ENABLE_ASH_ALIAS
2809         static const uint8_t syntax_index_table[] ALIGN1 = {
2810                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2811                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2812                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2813                 11, 3                           /* "}~" */
2814         };
2815 # else
2816         static const uint8_t syntax_index_table[] ALIGN1 = {
2817                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2818                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2819                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2820                 10, 2                           /* "}~" */
2821         };
2822 # endif
2823         const char *s;
2824         int indx;
2825
2826         if (c == PEOF)
2827                 return CENDFILE;
2828 # if ENABLE_ASH_ALIAS
2829         if (c == PEOA)
2830                 indx = 0;
2831         else
2832 # endif
2833         {
2834                 /* Cast is purely for paranoia here,
2835                  * just in case someone passed signed char to us */
2836                 if ((unsigned char)c >= CTL_FIRST
2837                  && (unsigned char)c <= CTL_LAST
2838                 ) {
2839                         return CCTL;
2840                 }
2841                 s = strchrnul(spec_symbls, c);
2842                 if (*s == '\0')
2843                         return CWORD;
2844                 indx = syntax_index_table[s - spec_symbls];
2845         }
2846         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2847 }
2848
2849 #else   /* !USE_SIT_FUNCTION */
2850
2851 static const uint8_t syntax_index_table[] ALIGN1 = {
2852         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2853         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2854         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2855         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2856         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2857         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2858         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2859         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2860         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2861         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2862         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2863         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2864         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2865         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2866         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2867         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2868         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2869         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2870         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2871         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2872         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2873         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2874         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2875         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2876         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2877         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2878         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2879         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2880         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2881         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2882         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2883         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2884         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2885         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2886         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2887         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2888         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2889         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2890         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2891         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2892         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2893         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2894         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2895         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2896         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2897         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2898         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2899         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2900 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2901         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2902         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2903         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2904         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2905         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2906         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2907         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2908         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2909         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2910         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2911         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2912         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2913         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2914         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2915         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2916         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2917         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2918         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2919         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2920         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2921         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2922         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2923         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2924         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2925         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2926         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2927         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2928         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2929         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2930         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2931         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2935         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2936         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2938         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2939         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2940         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2941         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2942         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2943         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2946         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2947         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2948         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2951         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2954         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2955         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2956         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2957         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2958         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2959         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2960         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2961         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2962         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2963         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
2964         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
2965         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
2966         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
2967         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
2968         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
2969         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
2970         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
2971         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
2972         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
2973         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
2974         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
2975         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
2976         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
2977         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
2978         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
2979         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2980         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
2981         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
2982         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2983         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
2984         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
2985         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
2986         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
2987         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
2988         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
2989         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
2990         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2991         /* 137      */ CWORD_CWORD_CWORD_CWORD,
2992         /* 138      */ CWORD_CWORD_CWORD_CWORD,
2993         /* 139      */ CWORD_CWORD_CWORD_CWORD,
2994         /* 140      */ CWORD_CWORD_CWORD_CWORD,
2995         /* 141      */ CWORD_CWORD_CWORD_CWORD,
2996         /* 142      */ CWORD_CWORD_CWORD_CWORD,
2997         /* 143      */ CWORD_CWORD_CWORD_CWORD,
2998         /* 144      */ CWORD_CWORD_CWORD_CWORD,
2999         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3000         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3001         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3002         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3003         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3004         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3005         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3006         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3007         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3008         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3009         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3010         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3011         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3012         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3013         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3014         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3015         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3016         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3017         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3018         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3019         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3020         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3021         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3022         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3023         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3024         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3025         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3026         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3027         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3110         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3111 # if ENABLE_ASH_ALIAS
3112         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3113 # endif
3114 };
3115
3116 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3117
3118 #endif  /* !USE_SIT_FUNCTION */
3119
3120
3121 /* ============ Alias handling */
3122
3123 #if ENABLE_ASH_ALIAS
3124
3125 #define ALIASINUSE 1
3126 #define ALIASDEAD  2
3127
3128 struct alias {
3129         struct alias *next;
3130         char *name;
3131         char *val;
3132         int flag;
3133 };
3134
3135
3136 static struct alias **atab; // [ATABSIZE];
3137 #define INIT_G_alias() do { \
3138         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3139 } while (0)
3140
3141
3142 static struct alias **
3143 __lookupalias(const char *name)
3144 {
3145         unsigned int hashval;
3146         struct alias **app;
3147         const char *p;
3148         unsigned int ch;
3149
3150         p = name;
3151
3152         ch = (unsigned char)*p;
3153         hashval = ch << 4;
3154         while (ch) {
3155                 hashval += ch;
3156                 ch = (unsigned char)*++p;
3157         }
3158         app = &atab[hashval % ATABSIZE];
3159
3160         for (; *app; app = &(*app)->next) {
3161                 if (strcmp(name, (*app)->name) == 0) {
3162                         break;
3163                 }
3164         }
3165
3166         return app;
3167 }
3168
3169 static struct alias *
3170 lookupalias(const char *name, int check)
3171 {
3172         struct alias *ap = *__lookupalias(name);
3173
3174         if (check && ap && (ap->flag & ALIASINUSE))
3175                 return NULL;
3176         return ap;
3177 }
3178
3179 static struct alias *
3180 freealias(struct alias *ap)
3181 {
3182         struct alias *next;
3183
3184         if (ap->flag & ALIASINUSE) {
3185                 ap->flag |= ALIASDEAD;
3186                 return ap;
3187         }
3188
3189         next = ap->next;
3190         free(ap->name);
3191         free(ap->val);
3192         free(ap);
3193         return next;
3194 }
3195
3196 static void
3197 setalias(const char *name, const char *val)
3198 {
3199         struct alias *ap, **app;
3200
3201         app = __lookupalias(name);
3202         ap = *app;
3203         INT_OFF;
3204         if (ap) {
3205                 if (!(ap->flag & ALIASINUSE)) {
3206                         free(ap->val);
3207                 }
3208                 ap->val = ckstrdup(val);
3209                 ap->flag &= ~ALIASDEAD;
3210         } else {
3211                 /* not found */
3212                 ap = ckzalloc(sizeof(struct alias));
3213                 ap->name = ckstrdup(name);
3214                 ap->val = ckstrdup(val);
3215                 /*ap->flag = 0; - ckzalloc did it */
3216                 /*ap->next = NULL;*/
3217                 *app = ap;
3218         }
3219         INT_ON;
3220 }
3221
3222 static int
3223 unalias(const char *name)
3224 {
3225         struct alias **app;
3226
3227         app = __lookupalias(name);
3228
3229         if (*app) {
3230                 INT_OFF;
3231                 *app = freealias(*app);
3232                 INT_ON;
3233                 return 0;
3234         }
3235
3236         return 1;
3237 }
3238
3239 static void
3240 rmaliases(void)
3241 {
3242         struct alias *ap, **app;
3243         int i;
3244
3245         INT_OFF;
3246         for (i = 0; i < ATABSIZE; i++) {
3247                 app = &atab[i];
3248                 for (ap = *app; ap; ap = *app) {
3249                         *app = freealias(*app);
3250                         if (ap == *app) {
3251                                 app = &ap->next;
3252                         }
3253                 }
3254         }
3255         INT_ON;
3256 }
3257
3258 static void
3259 printalias(const struct alias *ap)
3260 {
3261         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3262 }
3263
3264 /*
3265  * TODO - sort output
3266  */
3267 static int FAST_FUNC
3268 aliascmd(int argc UNUSED_PARAM, char **argv)
3269 {
3270         char *n, *v;
3271         int ret = 0;
3272         struct alias *ap;
3273
3274         if (!argv[1]) {
3275                 int i;
3276
3277                 for (i = 0; i < ATABSIZE; i++) {
3278                         for (ap = atab[i]; ap; ap = ap->next) {
3279                                 printalias(ap);
3280                         }
3281                 }
3282                 return 0;
3283         }
3284         while ((n = *++argv) != NULL) {
3285                 v = strchr(n+1, '=');
3286                 if (v == NULL) { /* n+1: funny ksh stuff */
3287                         ap = *__lookupalias(n);
3288                         if (ap == NULL) {
3289                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3290                                 ret = 1;
3291                         } else
3292                                 printalias(ap);
3293                 } else {
3294                         *v++ = '\0';
3295                         setalias(n, v);
3296                 }
3297         }
3298
3299         return ret;
3300 }
3301
3302 static int FAST_FUNC
3303 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3304 {
3305         int i;
3306
3307         while ((i = nextopt("a")) != '\0') {
3308                 if (i == 'a') {
3309                         rmaliases();
3310                         return 0;
3311                 }
3312         }
3313         for (i = 0; *argptr; argptr++) {
3314                 if (unalias(*argptr)) {
3315                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3316                         i = 1;
3317                 }
3318         }
3319
3320         return i;
3321 }
3322
3323 #endif /* ASH_ALIAS */
3324
3325
3326 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3327 #define FORK_FG    0
3328 #define FORK_BG    1
3329 #define FORK_NOJOB 2
3330
3331 /* mode flags for showjob(s) */
3332 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3333 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3334 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3335 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3336
3337 /*
3338  * A job structure contains information about a job.  A job is either a
3339  * single process or a set of processes contained in a pipeline.  In the
3340  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3341  * array of pids.
3342  */
3343 struct procstat {
3344         pid_t   ps_pid;         /* process id */
3345         int     ps_status;      /* last process status from wait() */
3346         char    *ps_cmd;        /* text of command being run */
3347 };
3348
3349 struct job {
3350         struct procstat ps0;    /* status of process */
3351         struct procstat *ps;    /* status or processes when more than one */
3352 #if JOBS
3353         int stopstatus;         /* status of a stopped job */
3354 #endif
3355         uint32_t
3356                 nprocs: 16,     /* number of processes */
3357                 state: 8,
3358 #define JOBRUNNING      0       /* at least one proc running */
3359 #define JOBSTOPPED      1       /* all procs are stopped */
3360 #define JOBDONE         2       /* all procs are completed */
3361 #if JOBS
3362                 sigint: 1,      /* job was killed by SIGINT */
3363                 jobctl: 1,      /* job running under job control */
3364 #endif
3365                 waited: 1,      /* true if this entry has been waited for */
3366                 used: 1,        /* true if this entry is in used */
3367                 changed: 1;     /* true if status has changed */
3368         struct job *prev_job;   /* previous job */
3369 };
3370
3371 static struct job *makejob(/*union node *,*/ int);
3372 static int forkshell(struct job *, union node *, int);
3373 static int waitforjob(struct job *);
3374
3375 #if !JOBS
3376 enum { doing_jobctl = 0 };
3377 #define setjobctl(on) do {} while (0)
3378 #else
3379 static smallint doing_jobctl; //references:8
3380 static void setjobctl(int);
3381 #endif
3382
3383 /*
3384  * Ignore a signal.
3385  */
3386 static void
3387 ignoresig(int signo)
3388 {
3389         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3390         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3391                 /* No, need to do it */
3392                 signal(signo, SIG_IGN);
3393         }
3394         sigmode[signo - 1] = S_HARD_IGN;
3395 }
3396
3397 /*
3398  * Only one usage site - in setsignal()
3399  */
3400 static void
3401 signal_handler(int signo)
3402 {
3403         if (signo == SIGCHLD) {
3404                 got_sigchld = 1;
3405                 if (!trap[SIGCHLD])
3406                         return;
3407         }
3408
3409         gotsig[signo - 1] = 1;
3410         pending_sig = signo;
3411
3412         if (signo == SIGINT && !trap[SIGINT]) {
3413                 if (!suppress_int) {
3414                         pending_sig = 0;
3415                         raise_interrupt(); /* does not return */
3416                 }
3417                 pending_int = 1;
3418         }
3419 }
3420
3421 /*
3422  * Set the signal handler for the specified signal.  The routine figures
3423  * out what it should be set to.
3424  */
3425 static void
3426 setsignal(int signo)
3427 {
3428         char *t;
3429         char cur_act, new_act;
3430         struct sigaction act;
3431
3432         t = trap[signo];
3433         new_act = S_DFL;
3434         if (t != NULL) { /* trap for this sig is set */
3435                 new_act = S_CATCH;
3436                 if (t[0] == '\0') /* trap is "": ignore this sig */
3437                         new_act = S_IGN;
3438         }
3439
3440         if (rootshell && new_act == S_DFL) {
3441                 switch (signo) {
3442                 case SIGINT:
3443                         if (iflag || minusc || sflag == 0)
3444                                 new_act = S_CATCH;
3445                         break;
3446                 case SIGQUIT:
3447 #if DEBUG
3448                         if (debug)
3449                                 break;
3450 #endif
3451                         /* man bash:
3452                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3453                          * commands run by bash have signal handlers
3454                          * set to the values inherited by the shell
3455                          * from its parent". */
3456                         new_act = S_IGN;
3457                         break;
3458                 case SIGTERM:
3459                         if (iflag)
3460                                 new_act = S_IGN;
3461                         break;
3462 #if JOBS
3463                 case SIGTSTP:
3464                 case SIGTTOU:
3465                         if (mflag)
3466                                 new_act = S_IGN;
3467                         break;
3468 #endif
3469                 }
3470         }
3471 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3472 //whereas we have to restore it to what shell got on entry
3473 //from the parent. See comment above
3474
3475         if (signo == SIGCHLD)
3476                 new_act = S_CATCH;
3477
3478         t = &sigmode[signo - 1];
3479         cur_act = *t;
3480         if (cur_act == 0) {
3481                 /* current setting is not yet known */
3482                 if (sigaction(signo, NULL, &act)) {
3483                         /* pretend it worked; maybe we should give a warning,
3484                          * but other shells don't. We don't alter sigmode,
3485                          * so we retry every time.
3486                          * btw, in Linux it never fails. --vda */
3487                         return;
3488                 }
3489                 if (act.sa_handler == SIG_IGN) {
3490                         cur_act = S_HARD_IGN;
3491                         if (mflag
3492                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3493                         ) {
3494                                 cur_act = S_IGN;   /* don't hard ignore these */
3495                         }
3496                 }
3497         }
3498         if (cur_act == S_HARD_IGN || cur_act == new_act)
3499                 return;
3500
3501         act.sa_handler = SIG_DFL;
3502         switch (new_act) {
3503         case S_CATCH:
3504                 act.sa_handler = signal_handler;
3505                 break;
3506         case S_IGN:
3507                 act.sa_handler = SIG_IGN;
3508                 break;
3509         }
3510
3511         /* flags and mask matter only if !DFL and !IGN, but we do it
3512          * for all cases for more deterministic behavior:
3513          */
3514         act.sa_flags = 0;
3515         sigfillset(&act.sa_mask);
3516
3517         sigaction_set(signo, &act);
3518
3519         *t = new_act;
3520 }
3521
3522 /* mode flags for set_curjob */
3523 #define CUR_DELETE 2
3524 #define CUR_RUNNING 1
3525 #define CUR_STOPPED 0
3526
3527 #if JOBS
3528 /* pgrp of shell on invocation */
3529 static int initialpgrp; //references:2
3530 static int ttyfd = -1; //5
3531 #endif
3532 /* array of jobs */
3533 static struct job *jobtab; //5
3534 /* size of array */
3535 static unsigned njobs; //4
3536 /* current job */
3537 static struct job *curjob; //lots
3538 /* number of presumed living untracked jobs */
3539 static int jobless; //4
3540
3541 static void
3542 set_curjob(struct job *jp, unsigned mode)
3543 {
3544         struct job *jp1;
3545         struct job **jpp, **curp;
3546
3547         /* first remove from list */
3548         jpp = curp = &curjob;
3549         while (1) {
3550                 jp1 = *jpp;
3551                 if (jp1 == jp)
3552                         break;
3553                 jpp = &jp1->prev_job;
3554         }
3555         *jpp = jp1->prev_job;
3556
3557         /* Then re-insert in correct position */
3558         jpp = curp;
3559         switch (mode) {
3560         default:
3561 #if DEBUG
3562                 abort();
3563 #endif
3564         case CUR_DELETE:
3565                 /* job being deleted */
3566                 break;
3567         case CUR_RUNNING:
3568                 /* newly created job or backgrounded job,
3569                  * put after all stopped jobs.
3570                  */
3571                 while (1) {
3572                         jp1 = *jpp;
3573 #if JOBS
3574                         if (!jp1 || jp1->state != JOBSTOPPED)
3575 #endif
3576                                 break;
3577                         jpp = &jp1->prev_job;
3578                 }
3579                 /* FALLTHROUGH */
3580 #if JOBS
3581         case CUR_STOPPED:
3582 #endif
3583                 /* newly stopped job - becomes curjob */
3584                 jp->prev_job = *jpp;
3585                 *jpp = jp;
3586                 break;
3587         }
3588 }
3589
3590 #if JOBS || DEBUG
3591 static int
3592 jobno(const struct job *jp)
3593 {
3594         return jp - jobtab + 1;
3595 }
3596 #endif
3597
3598 /*
3599  * Convert a job name to a job structure.
3600  */
3601 #if !JOBS
3602 #define getjob(name, getctl) getjob(name)
3603 #endif
3604 static struct job *
3605 getjob(const char *name, int getctl)
3606 {
3607         struct job *jp;
3608         struct job *found;
3609         const char *err_msg = "%s: no such job";
3610         unsigned num;
3611         int c;
3612         const char *p;
3613         char *(*match)(const char *, const char *);
3614
3615         jp = curjob;
3616         p = name;
3617         if (!p)
3618                 goto currentjob;
3619
3620         if (*p != '%')
3621                 goto err;
3622
3623         c = *++p;
3624         if (!c)
3625                 goto currentjob;
3626
3627         if (!p[1]) {
3628                 if (c == '+' || c == '%') {
3629  currentjob:
3630                         err_msg = "No current job";
3631                         goto check;
3632                 }
3633                 if (c == '-') {
3634                         if (jp)
3635                                 jp = jp->prev_job;
3636                         err_msg = "No previous job";
3637  check:
3638                         if (!jp)
3639                                 goto err;
3640                         goto gotit;
3641                 }
3642         }
3643
3644         if (is_number(p)) {
3645                 num = atoi(p);
3646                 if (num > 0 && num <= njobs) {
3647                         jp = jobtab + num - 1;
3648                         if (jp->used)
3649                                 goto gotit;
3650                         goto err;
3651                 }
3652         }
3653
3654         match = prefix;
3655         if (*p == '?') {
3656                 match = strstr;
3657                 p++;
3658         }
3659
3660         found = NULL;
3661         while (jp) {
3662                 if (match(jp->ps[0].ps_cmd, p)) {
3663                         if (found)
3664                                 goto err;
3665                         found = jp;
3666                         err_msg = "%s: ambiguous";
3667                 }
3668                 jp = jp->prev_job;
3669         }
3670         if (!found)
3671                 goto err;
3672         jp = found;
3673
3674  gotit:
3675 #if JOBS
3676         err_msg = "job %s not created under job control";
3677         if (getctl && jp->jobctl == 0)
3678                 goto err;
3679 #endif
3680         return jp;
3681  err:
3682         ash_msg_and_raise_error(err_msg, name);
3683 }
3684
3685 /*
3686  * Mark a job structure as unused.
3687  */
3688 static void
3689 freejob(struct job *jp)
3690 {
3691         struct procstat *ps;
3692         int i;
3693
3694         INT_OFF;
3695         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3696                 if (ps->ps_cmd != nullstr)
3697                         free(ps->ps_cmd);
3698         }
3699         if (jp->ps != &jp->ps0)
3700                 free(jp->ps);
3701         jp->used = 0;
3702         set_curjob(jp, CUR_DELETE);
3703         INT_ON;
3704 }
3705
3706 #if JOBS
3707 static void
3708 xtcsetpgrp(int fd, pid_t pgrp)
3709 {
3710         if (tcsetpgrp(fd, pgrp))
3711                 ash_msg_and_raise_error("can't set tty process group (%m)");
3712 }
3713
3714 /*
3715  * Turn job control on and off.
3716  *
3717  * Note:  This code assumes that the third arg to ioctl is a character
3718  * pointer, which is true on Berkeley systems but not System V.  Since
3719  * System V doesn't have job control yet, this isn't a problem now.
3720  *
3721  * Called with interrupts off.
3722  */
3723 static void
3724 setjobctl(int on)
3725 {
3726         int fd;
3727         int pgrp;
3728
3729         if (on == doing_jobctl || rootshell == 0)
3730                 return;
3731         if (on) {
3732                 int ofd;
3733                 ofd = fd = open(_PATH_TTY, O_RDWR);
3734                 if (fd < 0) {
3735         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3736          * That sometimes helps to acquire controlling tty.
3737          * Obviously, a workaround for bugs when someone
3738          * failed to provide a controlling tty to bash! :) */
3739                         fd = 2;
3740                         while (!isatty(fd))
3741                                 if (--fd < 0)
3742                                         goto out;
3743                 }
3744                 /* fd is a tty at this point */
3745                 fd = fcntl(fd, F_DUPFD, 10);
3746                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, dont */
3747                         close(ofd);
3748                 if (fd < 0)
3749                         goto out; /* F_DUPFD failed */
3750                 close_on_exec_on(fd);
3751                 while (1) { /* while we are in the background */
3752                         pgrp = tcgetpgrp(fd);
3753                         if (pgrp < 0) {
3754  out:
3755                                 ash_msg("can't access tty; job control turned off");
3756                                 mflag = on = 0;
3757                                 goto close;
3758                         }
3759                         if (pgrp == getpgrp())
3760                                 break;
3761                         killpg(0, SIGTTIN);
3762                 }
3763                 initialpgrp = pgrp;
3764
3765                 setsignal(SIGTSTP);
3766                 setsignal(SIGTTOU);
3767                 setsignal(SIGTTIN);
3768                 pgrp = rootpid;
3769                 setpgid(0, pgrp);
3770                 xtcsetpgrp(fd, pgrp);
3771         } else {
3772                 /* turning job control off */
3773                 fd = ttyfd;
3774                 pgrp = initialpgrp;
3775                 /* was xtcsetpgrp, but this can make exiting ash
3776                  * loop forever if pty is already deleted */
3777                 tcsetpgrp(fd, pgrp);
3778                 setpgid(0, pgrp);
3779                 setsignal(SIGTSTP);
3780                 setsignal(SIGTTOU);
3781                 setsignal(SIGTTIN);
3782  close:
3783                 if (fd >= 0)
3784                         close(fd);
3785                 fd = -1;
3786         }
3787         ttyfd = fd;
3788         doing_jobctl = on;
3789 }
3790
3791 static int FAST_FUNC
3792 killcmd(int argc, char **argv)
3793 {
3794         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3795                 int i = 1;
3796                 do {
3797                         if (argv[i][0] == '%') {
3798                                 /*
3799                                  * "kill %N" - job kill
3800                                  * Converting to pgrp / pid kill
3801                                  */
3802                                 struct job *jp;
3803                                 char *dst;
3804                                 int j, n;
3805
3806                                 jp = getjob(argv[i], 0);
3807                                 /*
3808                                  * In jobs started under job control, we signal
3809                                  * entire process group by kill -PGRP_ID.
3810                                  * This happens, f.e., in interactive shell.
3811                                  *
3812                                  * Otherwise, we signal each child via
3813                                  * kill PID1 PID2 PID3.
3814                                  * Testcases:
3815                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3816                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3817                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3818                                  */
3819                                 n = jp->nprocs; /* can't be 0 (I hope) */
3820                                 if (jp->jobctl)
3821                                         n = 1;
3822                                 dst = alloca(n * sizeof(int)*4);
3823                                 argv[i] = dst;
3824                                 for (j = 0; j < n; j++) {
3825                                         struct procstat *ps = &jp->ps[j];
3826                                         /* Skip non-running and not-stopped members
3827                                          * (i.e. dead members) of the job
3828                                          */
3829                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3830                                                 continue;
3831                                         /*
3832                                          * kill_main has matching code to expect
3833                                          * leading space. Needed to not confuse
3834                                          * negative pids with "kill -SIGNAL_NO" syntax
3835                                          */
3836                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3837                                 }
3838                                 *dst = '\0';
3839                         }
3840                 } while (argv[++i]);
3841         }
3842         return kill_main(argc, argv);
3843 }
3844
3845 static void
3846 showpipe(struct job *jp /*, FILE *out*/)
3847 {
3848         struct procstat *ps;
3849         struct procstat *psend;
3850
3851         psend = jp->ps + jp->nprocs;
3852         for (ps = jp->ps + 1; ps < psend; ps++)
3853                 printf(" | %s", ps->ps_cmd);
3854         newline_and_flush(stdout);
3855         flush_stdout_stderr();
3856 }
3857
3858
3859 static int
3860 restartjob(struct job *jp, int mode)
3861 {
3862         struct procstat *ps;
3863         int i;
3864         int status;
3865         pid_t pgid;
3866
3867         INT_OFF;
3868         if (jp->state == JOBDONE)
3869                 goto out;
3870         jp->state = JOBRUNNING;
3871         pgid = jp->ps[0].ps_pid;
3872         if (mode == FORK_FG)
3873                 xtcsetpgrp(ttyfd, pgid);
3874         killpg(pgid, SIGCONT);
3875         ps = jp->ps;
3876         i = jp->nprocs;
3877         do {
3878                 if (WIFSTOPPED(ps->ps_status)) {
3879                         ps->ps_status = -1;
3880                 }
3881                 ps++;
3882         } while (--i);
3883  out:
3884         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3885         INT_ON;
3886         return status;
3887 }
3888
3889 static int FAST_FUNC
3890 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3891 {
3892         struct job *jp;
3893         int mode;
3894         int retval;
3895
3896         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3897         nextopt(nullstr);
3898         argv = argptr;
3899         do {
3900                 jp = getjob(*argv, 1);
3901                 if (mode == FORK_BG) {
3902                         set_curjob(jp, CUR_RUNNING);
3903                         printf("[%d] ", jobno(jp));
3904                 }
3905                 out1str(jp->ps[0].ps_cmd);
3906                 showpipe(jp /*, stdout*/);
3907                 retval = restartjob(jp, mode);
3908         } while (*argv && *++argv);
3909         return retval;
3910 }
3911 #endif
3912
3913 static int
3914 sprint_status48(char *s, int status, int sigonly)
3915 {
3916         int col;
3917         int st;
3918
3919         col = 0;
3920         if (!WIFEXITED(status)) {
3921                 if (JOBS && WIFSTOPPED(status))
3922                         st = WSTOPSIG(status);
3923                 else
3924                         st = WTERMSIG(status);
3925                 if (sigonly) {
3926                         if (st == SIGINT || st == SIGPIPE)
3927                                 goto out;
3928                         if (JOBS && WIFSTOPPED(status))
3929                                 goto out;
3930                 }
3931                 st &= 0x7f;
3932 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
3933                 col = fmtstr(s, 32, strsignal(st));
3934                 if (WCOREDUMP(status)) {
3935                         strcpy(s + col, " (core dumped)");
3936                         col += sizeof(" (core dumped)")-1;
3937                 }
3938         } else if (!sigonly) {
3939                 st = WEXITSTATUS(status);
3940                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
3941         }
3942  out:
3943         return col;
3944 }
3945
3946 static int
3947 wait_block_or_sig(int *status)
3948 {
3949         int pid;
3950
3951         do {
3952                 sigset_t mask;
3953
3954                 /* Poll all children for changes in their state */
3955                 got_sigchld = 0;
3956                 /* if job control is active, accept stopped processes too */
3957                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
3958                 if (pid != 0)
3959                         break; /* Error (e.g. EINTR, ECHILD) or pid */
3960
3961                 /* Children exist, but none are ready. Sleep until interesting signal */
3962 #if 1
3963                 sigfillset(&mask);
3964                 sigprocmask(SIG_SETMASK, &mask, &mask);
3965                 while (!got_sigchld && !pending_sig)
3966                         sigsuspend(&mask);
3967                 sigprocmask(SIG_SETMASK, &mask, NULL);
3968 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
3969                 while (!got_sigchld && !pending_sig)
3970                         pause();
3971 #endif
3972
3973                 /* If it was SIGCHLD, poll children again */
3974         } while (got_sigchld);
3975
3976         return pid;
3977 }
3978
3979 #define DOWAIT_NONBLOCK 0
3980 #define DOWAIT_BLOCK    1
3981 #define DOWAIT_BLOCK_OR_SIG 2
3982
3983 static int
3984 dowait(int block, struct job *job)
3985 {
3986         int pid;
3987         int status;
3988         struct job *jp;
3989         struct job *thisjob = NULL;
3990
3991         TRACE(("dowait(0x%x) called\n", block));
3992
3993         /* It's wrong to call waitpid() outside of INT_OFF region:
3994          * signal can arrive just after syscall return and handler can
3995          * longjmp away, losing stop/exit notification processing.
3996          * Thus, for "jobs" builtin, and for waiting for a fg job,
3997          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
3998          *
3999          * However, for "wait" builtin it is wrong to simply call waitpid()
4000          * in INT_OFF region: "wait" needs to wait for any running job
4001          * to change state, but should exit on any trap too.
4002          * In INT_OFF region, a signal just before syscall entry can set
4003          * pending_sig variables, but we can't check them, and we would
4004          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4005          *
4006          * Because of this, we run inside INT_OFF, but use a special routine
4007          * which combines waitpid() and sigsuspend().
4008          * This is the reason why we need to have a handler for SIGCHLD:
4009          * SIG_DFL handler does not wake sigsuspend().
4010          */
4011         INT_OFF;
4012         if (block == DOWAIT_BLOCK_OR_SIG) {
4013                 pid = wait_block_or_sig(&status);
4014         } else {
4015                 int wait_flags = 0;
4016                 if (block == DOWAIT_NONBLOCK)
4017                         wait_flags = WNOHANG;
4018                 /* if job control is active, accept stopped processes too */
4019                 if (doing_jobctl)
4020                         wait_flags |= WUNTRACED;
4021                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4022                 pid = waitpid(-1, &status, wait_flags);
4023         }
4024         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4025                                 pid, status, errno, strerror(errno)));
4026         if (pid <= 0)
4027                 goto out;
4028
4029         thisjob = NULL;
4030         for (jp = curjob; jp; jp = jp->prev_job) {
4031                 int jobstate;
4032                 struct procstat *ps;
4033                 struct procstat *psend;
4034                 if (jp->state == JOBDONE)
4035                         continue;
4036                 jobstate = JOBDONE;
4037                 ps = jp->ps;
4038                 psend = ps + jp->nprocs;
4039                 do {
4040                         if (ps->ps_pid == pid) {
4041                                 TRACE(("Job %d: changing status of proc %d "
4042                                         "from 0x%x to 0x%x\n",
4043                                         jobno(jp), pid, ps->ps_status, status));
4044                                 ps->ps_status = status;
4045                                 thisjob = jp;
4046                         }
4047                         if (ps->ps_status == -1)
4048                                 jobstate = JOBRUNNING;
4049 #if JOBS
4050                         if (jobstate == JOBRUNNING)
4051                                 continue;
4052                         if (WIFSTOPPED(ps->ps_status)) {
4053                                 jp->stopstatus = ps->ps_status;
4054                                 jobstate = JOBSTOPPED;
4055                         }
4056 #endif
4057                 } while (++ps < psend);
4058                 if (!thisjob)
4059                         continue;
4060
4061                 /* Found the job where one of its processes changed its state.
4062                  * Is there at least one live and running process in this job? */
4063                 if (jobstate != JOBRUNNING) {
4064                         /* No. All live processes in the job are stopped
4065                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4066                          */
4067                         thisjob->changed = 1;
4068                         if (thisjob->state != jobstate) {
4069                                 TRACE(("Job %d: changing state from %d to %d\n",
4070                                         jobno(thisjob), thisjob->state, jobstate));
4071                                 thisjob->state = jobstate;
4072 #if JOBS
4073                                 if (jobstate == JOBSTOPPED)
4074                                         set_curjob(thisjob, CUR_STOPPED);
4075 #endif
4076                         }
4077                 }
4078                 goto out;
4079         }
4080         /* The process wasn't found in job list */
4081         if (JOBS && !WIFSTOPPED(status))
4082                 jobless--;
4083  out:
4084         INT_ON;
4085
4086         if (thisjob && thisjob == job) {
4087                 char s[48 + 1];
4088                 int len;
4089
4090                 len = sprint_status48(s, status, 1);
4091                 if (len) {
4092                         s[len] = '\n';
4093                         s[len + 1] = '\0';
4094                         out2str(s);
4095                 }
4096         }
4097         return pid;
4098 }
4099
4100 #if JOBS
4101 static void
4102 showjob(struct job *jp, int mode)
4103 {
4104         struct procstat *ps;
4105         struct procstat *psend;
4106         int col;
4107         int indent_col;
4108         char s[16 + 16 + 48];
4109         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4110
4111         ps = jp->ps;
4112
4113         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4114                 /* just output process (group) id of pipeline */
4115                 fprintf(out, "%d\n", ps->ps_pid);
4116                 return;
4117         }
4118
4119         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4120         indent_col = col;
4121
4122         if (jp == curjob)
4123                 s[col - 3] = '+';
4124         else if (curjob && jp == curjob->prev_job)
4125                 s[col - 3] = '-';
4126
4127         if (mode & SHOW_PIDS)
4128                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4129
4130         psend = ps + jp->nprocs;
4131
4132         if (jp->state == JOBRUNNING) {
4133                 strcpy(s + col, "Running");
4134                 col += sizeof("Running") - 1;
4135         } else {
4136                 int status = psend[-1].ps_status;
4137                 if (jp->state == JOBSTOPPED)
4138                         status = jp->stopstatus;
4139                 col += sprint_status48(s + col, status, 0);
4140         }
4141         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4142
4143         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4144          * or prints several "PID             | <cmdN>" lines,
4145          * depending on SHOW_PIDS bit.
4146          * We do not print status of individual processes
4147          * between PID and <cmdN>. bash does it, but not very well:
4148          * first line shows overall job status, not process status,
4149          * making it impossible to know 1st process status.
4150          */
4151         goto start;
4152         do {
4153                 /* for each process */
4154                 s[0] = '\0';
4155                 col = 33;
4156                 if (mode & SHOW_PIDS)
4157                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4158  start:
4159                 fprintf(out, "%s%*c%s%s",
4160                                 s,
4161                                 33 - col >= 0 ? 33 - col : 0, ' ',
4162                                 ps == jp->ps ? "" : "| ",
4163                                 ps->ps_cmd
4164                 );
4165         } while (++ps != psend);
4166         newline_and_flush(out);
4167
4168         jp->changed = 0;
4169
4170         if (jp->state == JOBDONE) {
4171                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4172                 freejob(jp);
4173         }
4174 }
4175
4176 /*
4177  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4178  * statuses have changed since the last call to showjobs.
4179  */
4180 static void
4181 showjobs(int mode)
4182 {
4183         struct job *jp;
4184
4185         TRACE(("showjobs(0x%x) called\n", mode));
4186
4187         /* Handle all finished jobs */
4188         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4189                 continue;
4190
4191         for (jp = curjob; jp; jp = jp->prev_job) {
4192                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4193                         showjob(jp, mode);
4194                 }
4195         }
4196 }
4197
4198 static int FAST_FUNC
4199 jobscmd(int argc UNUSED_PARAM, char **argv)
4200 {
4201         int mode, m;
4202
4203         mode = 0;
4204         while ((m = nextopt("lp")) != '\0') {
4205                 if (m == 'l')
4206                         mode |= SHOW_PIDS;
4207                 else
4208                         mode |= SHOW_ONLY_PGID;
4209         }
4210
4211         argv = argptr;
4212         if (*argv) {
4213                 do
4214                         showjob(getjob(*argv, 0), mode);
4215                 while (*++argv);
4216         } else {
4217                 showjobs(mode);
4218         }
4219
4220         return 0;
4221 }
4222 #endif /* JOBS */
4223
4224 /* Called only on finished or stopped jobs (no members are running) */
4225 static int
4226 getstatus(struct job *job)
4227 {
4228         int status;
4229         int retval;
4230         struct procstat *ps;
4231
4232         /* Fetch last member's status */
4233         ps = job->ps + job->nprocs - 1;
4234         status = ps->ps_status;
4235         if (pipefail) {
4236                 /* "set -o pipefail" mode: use last _nonzero_ status */
4237                 while (status == 0 && --ps >= job->ps)
4238                         status = ps->ps_status;
4239         }
4240
4241         retval = WEXITSTATUS(status);
4242         if (!WIFEXITED(status)) {
4243 #if JOBS
4244                 retval = WSTOPSIG(status);
4245                 if (!WIFSTOPPED(status))
4246 #endif
4247                 {
4248                         /* XXX: limits number of signals */
4249                         retval = WTERMSIG(status);
4250 #if JOBS
4251                         if (retval == SIGINT)
4252                                 job->sigint = 1;
4253 #endif
4254                 }
4255                 retval += 128;
4256         }
4257         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4258                 jobno(job), job->nprocs, status, retval));
4259         return retval;
4260 }
4261
4262 static int FAST_FUNC
4263 waitcmd(int argc UNUSED_PARAM, char **argv)
4264 {
4265         struct job *job;
4266         int retval;
4267         struct job *jp;
4268
4269         nextopt(nullstr);
4270         retval = 0;
4271
4272         argv = argptr;
4273         if (!*argv) {
4274                 /* wait for all jobs */
4275                 for (;;) {
4276                         jp = curjob;
4277                         while (1) {
4278                                 if (!jp) /* no running procs */
4279                                         goto ret;
4280                                 if (jp->state == JOBRUNNING)
4281                                         break;
4282                                 jp->waited = 1;
4283                                 jp = jp->prev_job;
4284                         }
4285         /* man bash:
4286          * "When bash is waiting for an asynchronous command via
4287          * the wait builtin, the reception of a signal for which a trap
4288          * has been set will cause the wait builtin to return immediately
4289          * with an exit status greater than 128, immediately after which
4290          * the trap is executed."
4291          */
4292                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4293         /* if child sends us a signal *and immediately exits*,
4294          * dowait() returns pid > 0. Check this case,
4295          * not "if (dowait() < 0)"!
4296          */
4297                         if (pending_sig)
4298                                 goto sigout;
4299                 }
4300         }
4301
4302         retval = 127;
4303         do {
4304                 if (**argv != '%') {
4305                         pid_t pid = number(*argv);
4306                         job = curjob;
4307                         while (1) {
4308                                 if (!job)
4309                                         goto repeat;
4310                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4311                                         break;
4312                                 job = job->prev_job;
4313                         }
4314                 } else {
4315                         job = getjob(*argv, 0);
4316                 }
4317                 /* loop until process terminated or stopped */
4318                 while (job->state == JOBRUNNING) {
4319                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4320                         if (pending_sig)
4321                                 goto sigout;
4322                 }
4323                 job->waited = 1;
4324                 retval = getstatus(job);
4325  repeat: ;
4326         } while (*++argv);
4327
4328  ret:
4329         return retval;
4330  sigout:
4331         retval = 128 + pending_sig;
4332         return retval;
4333 }
4334
4335 static struct job *
4336 growjobtab(void)
4337 {
4338         size_t len;
4339         ptrdiff_t offset;
4340         struct job *jp, *jq;
4341
4342         len = njobs * sizeof(*jp);
4343         jq = jobtab;
4344         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4345
4346         offset = (char *)jp - (char *)jq;
4347         if (offset) {
4348                 /* Relocate pointers */
4349                 size_t l = len;
4350
4351                 jq = (struct job *)((char *)jq + l);
4352                 while (l) {
4353                         l -= sizeof(*jp);
4354                         jq--;
4355 #define joff(p) ((struct job *)((char *)(p) + l))
4356 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4357                         if (joff(jp)->ps == &jq->ps0)
4358                                 jmove(joff(jp)->ps);
4359                         if (joff(jp)->prev_job)
4360                                 jmove(joff(jp)->prev_job);
4361                 }
4362                 if (curjob)
4363                         jmove(curjob);
4364 #undef joff
4365 #undef jmove
4366         }
4367
4368         njobs += 4;
4369         jobtab = jp;
4370         jp = (struct job *)((char *)jp + len);
4371         jq = jp + 3;
4372         do {
4373                 jq->used = 0;
4374         } while (--jq >= jp);
4375         return jp;
4376 }
4377
4378 /*
4379  * Return a new job structure.
4380  * Called with interrupts off.
4381  */
4382 static struct job *
4383 makejob(/*union node *node,*/ int nprocs)
4384 {
4385         int i;
4386         struct job *jp;
4387
4388         for (i = njobs, jp = jobtab; ; jp++) {
4389                 if (--i < 0) {
4390                         jp = growjobtab();
4391                         break;
4392                 }
4393                 if (jp->used == 0)
4394                         break;
4395                 if (jp->state != JOBDONE || !jp->waited)
4396                         continue;
4397 #if JOBS
4398                 if (doing_jobctl)
4399                         continue;
4400 #endif
4401                 freejob(jp);
4402                 break;
4403         }
4404         memset(jp, 0, sizeof(*jp));
4405 #if JOBS
4406         /* jp->jobctl is a bitfield.
4407          * "jp->jobctl |= jobctl" likely to give awful code */
4408         if (doing_jobctl)
4409                 jp->jobctl = 1;
4410 #endif
4411         jp->prev_job = curjob;
4412         curjob = jp;
4413         jp->used = 1;
4414         jp->ps = &jp->ps0;
4415         if (nprocs > 1) {
4416                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4417         }
4418         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4419                                 jobno(jp)));
4420         return jp;
4421 }
4422
4423 #if JOBS
4424 /*
4425  * Return a string identifying a command (to be printed by the
4426  * jobs command).
4427  */
4428 static char *cmdnextc;
4429
4430 static void
4431 cmdputs(const char *s)
4432 {
4433         static const char vstype[VSTYPE + 1][3] = {
4434                 "", "}", "-", "+", "?", "=",
4435                 "%", "%%", "#", "##"
4436                 IF_ASH_BASH_COMPAT(, ":", "/", "//")
4437         };
4438
4439         const char *p, *str;
4440         char cc[2];
4441         char *nextc;
4442         unsigned char c;
4443         unsigned char subtype = 0;
4444         int quoted = 0;
4445
4446         cc[1] = '\0';
4447         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4448         p = s;
4449         while ((c = *p++) != '\0') {
4450                 str = NULL;
4451                 switch (c) {
4452                 case CTLESC:
4453                         c = *p++;
4454                         break;
4455                 case CTLVAR:
4456                         subtype = *p++;
4457                         if ((subtype & VSTYPE) == VSLENGTH)
4458                                 str = "${#";
4459                         else
4460                                 str = "${";
4461                         goto dostr;
4462                 case CTLENDVAR:
4463                         str = "\"}" + !(quoted & 1);
4464                         quoted >>= 1;
4465                         subtype = 0;
4466                         goto dostr;
4467                 case CTLBACKQ:
4468                         str = "$(...)";
4469                         goto dostr;
4470 #if ENABLE_SH_MATH_SUPPORT
4471                 case CTLARI:
4472                         str = "$((";
4473                         goto dostr;
4474                 case CTLENDARI:
4475                         str = "))";
4476                         goto dostr;
4477 #endif
4478                 case CTLQUOTEMARK:
4479                         quoted ^= 1;
4480                         c = '"';
4481                         break;
4482                 case '=':
4483                         if (subtype == 0)
4484                                 break;
4485                         if ((subtype & VSTYPE) != VSNORMAL)
4486                                 quoted <<= 1;
4487                         str = vstype[subtype & VSTYPE];
4488                         if (subtype & VSNUL)
4489                                 c = ':';
4490                         else
4491                                 goto checkstr;
4492                         break;
4493                 case '\'':
4494                 case '\\':
4495                 case '"':
4496                 case '$':
4497                         /* These can only happen inside quotes */
4498                         cc[0] = c;
4499                         str = cc;
4500                         c = '\\';
4501                         break;
4502                 default:
4503                         break;
4504                 }
4505                 USTPUTC(c, nextc);
4506  checkstr:
4507                 if (!str)
4508                         continue;
4509  dostr:
4510                 while ((c = *str++) != '\0') {
4511                         USTPUTC(c, nextc);
4512                 }
4513         } /* while *p++ not NUL */
4514
4515         if (quoted & 1) {
4516                 USTPUTC('"', nextc);
4517         }
4518         *nextc = 0;
4519         cmdnextc = nextc;
4520 }
4521
4522 /* cmdtxt() and cmdlist() call each other */
4523 static void cmdtxt(union node *n);
4524
4525 static void
4526 cmdlist(union node *np, int sep)
4527 {
4528         for (; np; np = np->narg.next) {
4529                 if (!sep)
4530                         cmdputs(" ");
4531                 cmdtxt(np);
4532                 if (sep && np->narg.next)
4533                         cmdputs(" ");
4534         }
4535 }
4536
4537 static void
4538 cmdtxt(union node *n)
4539 {
4540         union node *np;
4541         struct nodelist *lp;
4542         const char *p;
4543
4544         if (!n)
4545                 return;
4546         switch (n->type) {
4547         default:
4548 #if DEBUG
4549                 abort();
4550 #endif
4551         case NPIPE:
4552                 lp = n->npipe.cmdlist;
4553                 for (;;) {
4554                         cmdtxt(lp->n);
4555                         lp = lp->next;
4556                         if (!lp)
4557                                 break;
4558                         cmdputs(" | ");
4559                 }
4560                 break;
4561         case NSEMI:
4562                 p = "; ";
4563                 goto binop;
4564         case NAND:
4565                 p = " && ";
4566                 goto binop;
4567         case NOR:
4568                 p = " || ";
4569  binop:
4570                 cmdtxt(n->nbinary.ch1);
4571                 cmdputs(p);
4572                 n = n->nbinary.ch2;
4573                 goto donode;
4574         case NREDIR:
4575         case NBACKGND:
4576                 n = n->nredir.n;
4577                 goto donode;
4578         case NNOT:
4579                 cmdputs("!");
4580                 n = n->nnot.com;
4581  donode:
4582                 cmdtxt(n);
4583                 break;
4584         case NIF:
4585                 cmdputs("if ");
4586                 cmdtxt(n->nif.test);
4587                 cmdputs("; then ");
4588                 if (n->nif.elsepart) {
4589                         cmdtxt(n->nif.ifpart);
4590                         cmdputs("; else ");
4591                         n = n->nif.elsepart;
4592                 } else {
4593                         n = n->nif.ifpart;
4594                 }
4595                 p = "; fi";
4596                 goto dotail;
4597         case NSUBSHELL:
4598                 cmdputs("(");
4599                 n = n->nredir.n;
4600                 p = ")";
4601                 goto dotail;
4602         case NWHILE:
4603                 p = "while ";
4604                 goto until;
4605         case NUNTIL:
4606                 p = "until ";
4607  until:
4608                 cmdputs(p);
4609                 cmdtxt(n->nbinary.ch1);
4610                 n = n->nbinary.ch2;
4611                 p = "; done";
4612  dodo:
4613                 cmdputs("; do ");
4614  dotail:
4615                 cmdtxt(n);
4616                 goto dotail2;
4617         case NFOR:
4618                 cmdputs("for ");
4619                 cmdputs(n->nfor.var);
4620                 cmdputs(" in ");
4621                 cmdlist(n->nfor.args, 1);
4622                 n = n->nfor.body;
4623                 p = "; done";
4624                 goto dodo;
4625         case NDEFUN:
4626                 cmdputs(n->narg.text);
4627                 p = "() { ... }";
4628                 goto dotail2;
4629         case NCMD:
4630                 cmdlist(n->ncmd.args, 1);
4631                 cmdlist(n->ncmd.redirect, 0);
4632                 break;
4633         case NARG:
4634                 p = n->narg.text;
4635  dotail2:
4636                 cmdputs(p);
4637                 break;
4638         case NHERE:
4639         case NXHERE:
4640                 p = "<<...";
4641                 goto dotail2;
4642         case NCASE:
4643                 cmdputs("case ");
4644                 cmdputs(n->ncase.expr->narg.text);
4645                 cmdputs(" in ");
4646                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4647                         cmdtxt(np->nclist.pattern);
4648                         cmdputs(") ");
4649                         cmdtxt(np->nclist.body);
4650                         cmdputs(";; ");
4651                 }
4652                 p = "esac";
4653                 goto dotail2;
4654         case NTO:
4655                 p = ">";
4656                 goto redir;
4657         case NCLOBBER:
4658                 p = ">|";
4659                 goto redir;
4660         case NAPPEND:
4661                 p = ">>";
4662                 goto redir;
4663 #if ENABLE_ASH_BASH_COMPAT
4664         case NTO2:
4665 #endif
4666         case NTOFD:
4667                 p = ">&";
4668                 goto redir;
4669         case NFROM:
4670                 p = "<";
4671                 goto redir;
4672         case NFROMFD:
4673                 p = "<&";
4674                 goto redir;
4675         case NFROMTO:
4676                 p = "<>";
4677  redir:
4678                 cmdputs(utoa(n->nfile.fd));
4679                 cmdputs(p);
4680                 if (n->type == NTOFD || n->type == NFROMFD) {
4681                         cmdputs(utoa(n->ndup.dupfd));
4682                         break;
4683                 }
4684                 n = n->nfile.fname;
4685                 goto donode;
4686         }
4687 }
4688
4689 static char *
4690 commandtext(union node *n)
4691 {
4692         char *name;
4693
4694         STARTSTACKSTR(cmdnextc);
4695         cmdtxt(n);
4696         name = stackblock();
4697         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4698         return ckstrdup(name);
4699 }
4700 #endif /* JOBS */
4701
4702 /*
4703  * Fork off a subshell.  If we are doing job control, give the subshell its
4704  * own process group.  Jp is a job structure that the job is to be added to.
4705  * N is the command that will be evaluated by the child.  Both jp and n may
4706  * be NULL.  The mode parameter can be one of the following:
4707  *      FORK_FG - Fork off a foreground process.
4708  *      FORK_BG - Fork off a background process.
4709  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4710  *                   process group even if job control is on.
4711  *
4712  * When job control is turned off, background processes have their standard
4713  * input redirected to /dev/null (except for the second and later processes
4714  * in a pipeline).
4715  *
4716  * Called with interrupts off.
4717  */
4718 /*
4719  * Clear traps on a fork.
4720  */
4721 static void
4722 clear_traps(void)
4723 {
4724         char **tp;
4725
4726         INT_OFF;
4727         for (tp = trap; tp < &trap[NSIG]; tp++) {
4728                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4729                         if (trap_ptr == trap)
4730                                 free(*tp);
4731                         /* else: it "belongs" to trap_ptr vector, don't free */
4732                         *tp = NULL;
4733                         if ((tp - trap) != 0)
4734                                 setsignal(tp - trap);
4735                 }
4736         }
4737         may_have_traps = 0;
4738         INT_ON;
4739 }
4740
4741 /* Lives far away from here, needed for forkchild */
4742 static void closescript(void);
4743
4744 /* Called after fork(), in child */
4745 /* jp and n are NULL when called by openhere() for heredoc support */
4746 static NOINLINE void
4747 forkchild(struct job *jp, union node *n, int mode)
4748 {
4749         int oldlvl;
4750
4751         TRACE(("Child shell %d\n", getpid()));
4752         oldlvl = shlvl;
4753         shlvl++;
4754
4755         /* man bash: "Non-builtin commands run by bash have signal handlers
4756          * set to the values inherited by the shell from its parent".
4757          * Do we do it correctly? */
4758
4759         closescript();
4760
4761         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4762          && n && n->type == NCMD        /* is it single cmd? */
4763         /* && n->ncmd.args->type == NARG - always true? */
4764          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4765          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4766         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4767         ) {
4768                 TRACE(("Trap hack\n"));
4769                 /* Awful hack for `trap` or $(trap).
4770                  *
4771                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4772                  * contains an example where "trap" is executed in a subshell:
4773                  *
4774                  * save_traps=$(trap)
4775                  * ...
4776                  * eval "$save_traps"
4777                  *
4778                  * Standard does not say that "trap" in subshell shall print
4779                  * parent shell's traps. It only says that its output
4780                  * must have suitable form, but then, in the above example
4781                  * (which is not supposed to be normative), it implies that.
4782                  *
4783                  * bash (and probably other shell) does implement it
4784                  * (traps are reset to defaults, but "trap" still shows them),
4785                  * but as a result, "trap" logic is hopelessly messed up:
4786                  *
4787                  * # trap
4788                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4789                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4790                  * # true | trap   <--- trap is in subshell - no output (ditto)
4791                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4792                  * trap -- 'echo Ho' SIGWINCH
4793                  * # echo `(trap)`         <--- in subshell in subshell - output
4794                  * trap -- 'echo Ho' SIGWINCH
4795                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4796                  * trap -- 'echo Ho' SIGWINCH
4797                  *
4798                  * The rules when to forget and when to not forget traps
4799                  * get really complex and nonsensical.
4800                  *
4801                  * Our solution: ONLY bare $(trap) or `trap` is special.
4802                  */
4803                 /* Save trap handler strings for trap builtin to print */
4804                 trap_ptr = xmemdup(trap, sizeof(trap));
4805                 /* Fall through into clearing traps */
4806         }
4807         clear_traps();
4808 #if JOBS
4809         /* do job control only in root shell */
4810         doing_jobctl = 0;
4811         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4812                 pid_t pgrp;
4813
4814                 if (jp->nprocs == 0)
4815                         pgrp = getpid();
4816                 else
4817                         pgrp = jp->ps[0].ps_pid;
4818                 /* this can fail because we are doing it in the parent also */
4819                 setpgid(0, pgrp);
4820                 if (mode == FORK_FG)
4821                         xtcsetpgrp(ttyfd, pgrp);
4822                 setsignal(SIGTSTP);
4823                 setsignal(SIGTTOU);
4824         } else
4825 #endif
4826         if (mode == FORK_BG) {
4827                 /* man bash: "When job control is not in effect,
4828                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4829                 ignoresig(SIGINT);
4830                 ignoresig(SIGQUIT);
4831                 if (jp->nprocs == 0) {
4832                         close(0);
4833                         if (open(bb_dev_null, O_RDONLY) != 0)
4834                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4835                 }
4836         }
4837         if (oldlvl == 0) {
4838                 if (iflag) { /* why if iflag only? */
4839                         setsignal(SIGINT);
4840                         setsignal(SIGTERM);
4841                 }
4842                 /* man bash:
4843                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4844                  * commands run by bash have signal handlers
4845                  * set to the values inherited by the shell
4846                  * from its parent".
4847                  * Take care of the second rule: */
4848                 setsignal(SIGQUIT);
4849         }
4850 #if JOBS
4851         if (n && n->type == NCMD
4852          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4853         ) {
4854                 TRACE(("Job hack\n"));
4855                 /* "jobs": we do not want to clear job list for it,
4856                  * instead we remove only _its_ own_ job from job list.
4857                  * This makes "jobs .... | cat" more useful.
4858                  */
4859                 freejob(curjob);
4860                 return;
4861         }
4862 #endif
4863         for (jp = curjob; jp; jp = jp->prev_job)
4864                 freejob(jp);
4865         jobless = 0;
4866 }
4867
4868 /* Called after fork(), in parent */
4869 #if !JOBS
4870 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4871 #endif
4872 static void
4873 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4874 {
4875         TRACE(("In parent shell: child = %d\n", pid));
4876         if (!jp) {
4877                 /* jp is NULL when called by openhere() for heredoc support */
4878                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4879                         continue;
4880                 jobless++;
4881                 return;
4882         }
4883 #if JOBS
4884         if (mode != FORK_NOJOB && jp->jobctl) {
4885                 int pgrp;
4886
4887                 if (jp->nprocs == 0)
4888                         pgrp = pid;
4889                 else
4890                         pgrp = jp->ps[0].ps_pid;
4891                 /* This can fail because we are doing it in the child also */
4892                 setpgid(pid, pgrp);
4893         }
4894 #endif
4895         if (mode == FORK_BG) {
4896                 backgndpid = pid;               /* set $! */
4897                 set_curjob(jp, CUR_RUNNING);
4898         }
4899         if (jp) {
4900                 struct procstat *ps = &jp->ps[jp->nprocs++];
4901                 ps->ps_pid = pid;
4902                 ps->ps_status = -1;
4903                 ps->ps_cmd = nullstr;
4904 #if JOBS
4905                 if (doing_jobctl && n)
4906                         ps->ps_cmd = commandtext(n);
4907 #endif
4908         }
4909 }
4910
4911 /* jp and n are NULL when called by openhere() for heredoc support */
4912 static int
4913 forkshell(struct job *jp, union node *n, int mode)
4914 {
4915         int pid;
4916
4917         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4918         pid = fork();
4919         if (pid < 0) {
4920                 TRACE(("Fork failed, errno=%d", errno));
4921                 if (jp)
4922                         freejob(jp);
4923                 ash_msg_and_raise_error("can't fork");
4924         }
4925         if (pid == 0) {
4926                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
4927                 forkchild(jp, n, mode);
4928         } else {
4929                 forkparent(jp, n, mode, pid);
4930         }
4931         return pid;
4932 }
4933
4934 /*
4935  * Wait for job to finish.
4936  *
4937  * Under job control we have the problem that while a child process
4938  * is running interrupts generated by the user are sent to the child
4939  * but not to the shell.  This means that an infinite loop started by
4940  * an interactive user may be hard to kill.  With job control turned off,
4941  * an interactive user may place an interactive program inside a loop.
4942  * If the interactive program catches interrupts, the user doesn't want
4943  * these interrupts to also abort the loop.  The approach we take here
4944  * is to have the shell ignore interrupt signals while waiting for a
4945  * foreground process to terminate, and then send itself an interrupt
4946  * signal if the child process was terminated by an interrupt signal.
4947  * Unfortunately, some programs want to do a bit of cleanup and then
4948  * exit on interrupt; unless these processes terminate themselves by
4949  * sending a signal to themselves (instead of calling exit) they will
4950  * confuse this approach.
4951  *
4952  * Called with interrupts off.
4953  */
4954 static int
4955 waitforjob(struct job *jp)
4956 {
4957         int st;
4958
4959         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4960
4961         INT_OFF;
4962         while (jp->state == JOBRUNNING) {
4963                 /* In non-interactive shells, we _can_ get
4964                  * a keyboard signal here and be EINTRed,
4965                  * but we just loop back, waiting for command to complete.
4966                  *
4967                  * man bash:
4968                  * "If bash is waiting for a command to complete and receives
4969                  * a signal for which a trap has been set, the trap
4970                  * will not be executed until the command completes."
4971                  *
4972                  * Reality is that even if trap is not set, bash
4973                  * will not act on the signal until command completes.
4974                  * Try this. sleep5intoff.c:
4975                  * #include <signal.h>
4976                  * #include <unistd.h>
4977                  * int main() {
4978                  *         sigset_t set;
4979                  *         sigemptyset(&set);
4980                  *         sigaddset(&set, SIGINT);
4981                  *         sigaddset(&set, SIGQUIT);
4982                  *         sigprocmask(SIG_BLOCK, &set, NULL);
4983                  *         sleep(5);
4984                  *         return 0;
4985                  * }
4986                  * $ bash -c './sleep5intoff; echo hi'
4987                  * ^C^C^C^C <--- pressing ^C once a second
4988                  * $ _
4989                  * $ bash -c './sleep5intoff; echo hi'
4990                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4991                  * $ _
4992                  */
4993                 dowait(DOWAIT_BLOCK, jp);
4994         }
4995         INT_ON;
4996
4997         st = getstatus(jp);
4998 #if JOBS
4999         if (jp->jobctl) {
5000                 xtcsetpgrp(ttyfd, rootpid);
5001                 /*
5002                  * This is truly gross.
5003                  * If we're doing job control, then we did a TIOCSPGRP which
5004                  * caused us (the shell) to no longer be in the controlling
5005                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5006                  * intuit from the subprocess exit status whether a SIGINT
5007                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5008                  */
5009                 if (jp->sigint) /* TODO: do the same with all signals */
5010                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5011         }
5012         if (jp->state == JOBDONE)
5013 #endif
5014                 freejob(jp);
5015         return st;
5016 }
5017
5018 /*
5019  * return 1 if there are stopped jobs, otherwise 0
5020  */
5021 static int
5022 stoppedjobs(void)
5023 {
5024         struct job *jp;
5025         int retval;
5026
5027         retval = 0;
5028         if (job_warning)
5029                 goto out;
5030         jp = curjob;
5031         if (jp && jp->state == JOBSTOPPED) {
5032                 out2str("You have stopped jobs.\n");
5033                 job_warning = 2;
5034                 retval++;
5035         }
5036  out:
5037         return retval;
5038 }
5039
5040
5041 /*
5042  * Code for dealing with input/output redirection.
5043  */
5044
5045 #undef EMPTY
5046 #undef CLOSED
5047 #define EMPTY -2                /* marks an unused slot in redirtab */
5048 #define CLOSED -3               /* marks a slot of previously-closed fd */
5049
5050 /*
5051  * Open a file in noclobber mode.
5052  * The code was copied from bash.
5053  */
5054 static int
5055 noclobberopen(const char *fname)
5056 {
5057         int r, fd;
5058         struct stat finfo, finfo2;
5059
5060         /*
5061          * If the file exists and is a regular file, return an error
5062          * immediately.
5063          */
5064         r = stat(fname, &finfo);
5065         if (r == 0 && S_ISREG(finfo.st_mode)) {
5066                 errno = EEXIST;
5067                 return -1;
5068         }
5069
5070         /*
5071          * If the file was not present (r != 0), make sure we open it
5072          * exclusively so that if it is created before we open it, our open
5073          * will fail.  Make sure that we do not truncate an existing file.
5074          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5075          * file was not a regular file, we leave O_EXCL off.
5076          */
5077         if (r != 0)
5078                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5079         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5080
5081         /* If the open failed, return the file descriptor right away. */
5082         if (fd < 0)
5083                 return fd;
5084
5085         /*
5086          * OK, the open succeeded, but the file may have been changed from a
5087          * non-regular file to a regular file between the stat and the open.
5088          * We are assuming that the O_EXCL open handles the case where FILENAME
5089          * did not exist and is symlinked to an existing file between the stat
5090          * and open.
5091          */
5092
5093         /*
5094          * If we can open it and fstat the file descriptor, and neither check
5095          * revealed that it was a regular file, and the file has not been
5096          * replaced, return the file descriptor.
5097          */
5098         if (fstat(fd, &finfo2) == 0
5099          && !S_ISREG(finfo2.st_mode)
5100          && finfo.st_dev == finfo2.st_dev
5101          && finfo.st_ino == finfo2.st_ino
5102         ) {
5103                 return fd;
5104         }
5105
5106         /* The file has been replaced.  badness. */
5107         close(fd);
5108         errno = EEXIST;
5109         return -1;
5110 }
5111
5112 /*
5113  * Handle here documents.  Normally we fork off a process to write the
5114  * data to a pipe.  If the document is short, we can stuff the data in
5115  * the pipe without forking.
5116  */
5117 /* openhere needs this forward reference */
5118 static void expandhere(union node *arg, int fd);
5119 static int
5120 openhere(union node *redir)
5121 {
5122         int pip[2];
5123         size_t len = 0;
5124
5125         if (pipe(pip) < 0)
5126                 ash_msg_and_raise_error("pipe call failed");
5127         if (redir->type == NHERE) {
5128                 len = strlen(redir->nhere.doc->narg.text);
5129                 if (len <= PIPE_BUF) {
5130                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5131                         goto out;
5132                 }
5133         }
5134         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5135                 /* child */
5136                 close(pip[0]);
5137                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5138                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5139                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5140                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5141                 signal(SIGPIPE, SIG_DFL);
5142                 if (redir->type == NHERE)
5143                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5144                 else /* NXHERE */
5145                         expandhere(redir->nhere.doc, pip[1]);
5146                 _exit(EXIT_SUCCESS);
5147         }
5148  out:
5149         close(pip[1]);
5150         return pip[0];
5151 }
5152
5153 static int
5154 openredirect(union node *redir)
5155 {
5156         char *fname;
5157         int f;
5158
5159         switch (redir->nfile.type) {
5160 /* Can't happen, our single caller does this itself */
5161 //      case NTOFD:
5162 //      case NFROMFD:
5163 //              return -1;
5164         case NHERE:
5165         case NXHERE:
5166                 return openhere(redir);
5167         }
5168
5169         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5170          * allocated space. Do it only when we know it is safe.
5171          */
5172         fname = redir->nfile.expfname;
5173
5174         switch (redir->nfile.type) {
5175         default:
5176 #if DEBUG
5177                 abort();
5178 #endif
5179         case NFROM:
5180                 f = open(fname, O_RDONLY);
5181                 if (f < 0)
5182                         goto eopen;
5183                 break;
5184         case NFROMTO:
5185                 f = open(fname, O_RDWR|O_CREAT, 0666);
5186                 if (f < 0)
5187                         goto ecreate;
5188                 break;
5189         case NTO:
5190 #if ENABLE_ASH_BASH_COMPAT
5191         case NTO2:
5192 #endif
5193                 /* Take care of noclobber mode. */
5194                 if (Cflag) {
5195                         f = noclobberopen(fname);
5196                         if (f < 0)
5197                                 goto ecreate;
5198                         break;
5199                 }
5200                 /* FALLTHROUGH */
5201         case NCLOBBER:
5202                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5203                 if (f < 0)
5204                         goto ecreate;
5205                 break;
5206         case NAPPEND:
5207                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5208                 if (f < 0)
5209                         goto ecreate;
5210                 break;
5211         }
5212
5213         return f;
5214  ecreate:
5215         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5216  eopen:
5217         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5218 }
5219
5220 /*
5221  * Copy a file descriptor to be >= 10. Throws exception on error.
5222  */
5223 static int
5224 savefd(int from)
5225 {
5226         int newfd;
5227         int err;
5228
5229         newfd = fcntl(from, F_DUPFD, 10);
5230         err = newfd < 0 ? errno : 0;
5231         if (err != EBADF) {
5232                 if (err)
5233                         ash_msg_and_raise_error("%d: %m", from);
5234                 close(from);
5235                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5236         }
5237
5238         return newfd;
5239 }
5240 static int
5241 dup2_or_raise(int from, int to)
5242 {
5243         int newfd;
5244
5245         newfd = (from != to) ? dup2(from, to) : to;
5246         if (newfd < 0) {
5247                 /* Happens when source fd is not open: try "echo >&99" */
5248                 ash_msg_and_raise_error("%d: %m", from);
5249         }
5250         return newfd;
5251 }
5252
5253 /* Struct def and variable are moved down to the first usage site */
5254 struct two_fd_t {
5255         int orig, copy;
5256 };
5257 struct redirtab {
5258         struct redirtab *next;
5259         int pair_count;
5260         struct two_fd_t two_fd[];
5261 };
5262 #define redirlist (G_var.redirlist)
5263 enum {
5264         COPYFD_RESTORE = (int)~(INT_MAX),
5265 };
5266
5267 static int
5268 need_to_remember(struct redirtab *rp, int fd)
5269 {
5270         int i;
5271
5272         if (!rp) /* remembering was not requested */
5273                 return 0;
5274
5275         for (i = 0; i < rp->pair_count; i++) {
5276                 if (rp->two_fd[i].orig == fd) {
5277                         /* already remembered */
5278                         return 0;
5279                 }
5280         }
5281         return 1;
5282 }
5283
5284 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5285 static int
5286 is_hidden_fd(struct redirtab *rp, int fd)
5287 {
5288         int i;
5289         struct parsefile *pf;
5290
5291         if (fd == -1)
5292                 return 0;
5293         /* Check open scripts' fds */
5294         pf = g_parsefile;
5295         while (pf) {
5296                 /* We skip pf_fd == 0 case because of the following case:
5297                  * $ ash  # running ash interactively
5298                  * $ . ./script.sh
5299                  * and in script.sh: "exec 9>&0".
5300                  * Even though top-level pf_fd _is_ 0,
5301                  * it's still ok to use it: "read" builtin uses it,
5302                  * why should we cripple "exec" builtin?
5303                  */
5304                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5305                         return 1;
5306                 }
5307                 pf = pf->prev;
5308         }
5309
5310         if (!rp)
5311                 return 0;
5312         /* Check saved fds of redirects */
5313         fd |= COPYFD_RESTORE;
5314         for (i = 0; i < rp->pair_count; i++) {
5315                 if (rp->two_fd[i].copy == fd) {
5316                         return 1;
5317                 }
5318         }
5319         return 0;
5320 }
5321
5322 /*
5323  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5324  * old file descriptors are stashed away so that the redirection can be
5325  * undone by calling popredir.
5326  */
5327 /* flags passed to redirect */
5328 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5329 #define REDIR_SAVEFD2 03        /* set preverrout */
5330 static void
5331 redirect(union node *redir, int flags)
5332 {
5333         struct redirtab *sv;
5334         int sv_pos;
5335         int i;
5336         int fd;
5337         int newfd;
5338         int copied_fd2 = -1;
5339
5340         if (!redir) {
5341                 return;
5342         }
5343
5344         sv = NULL;
5345         sv_pos = 0;
5346         INT_OFF;
5347         if (flags & REDIR_PUSH) {
5348                 union node *tmp = redir;
5349                 do {
5350                         sv_pos++;
5351 #if ENABLE_ASH_BASH_COMPAT
5352                         if (tmp->nfile.type == NTO2)
5353                                 sv_pos++;
5354 #endif
5355                         tmp = tmp->nfile.next;
5356                 } while (tmp);
5357                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5358                 sv->next = redirlist;
5359                 sv->pair_count = sv_pos;
5360                 redirlist = sv;
5361                 while (sv_pos > 0) {
5362                         sv_pos--;
5363                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5364                 }
5365         }
5366
5367         do {
5368                 int right_fd = -1;
5369                 fd = redir->nfile.fd;
5370                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5371                         right_fd = redir->ndup.dupfd;
5372                         //bb_error_msg("doing %d > %d", fd, right_fd);
5373                         /* redirect from/to same file descriptor? */
5374                         if (right_fd == fd)
5375                                 continue;
5376                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5377                         if (is_hidden_fd(sv, right_fd)) {
5378                                 errno = EBADF; /* as if it is closed */
5379                                 ash_msg_and_raise_error("%d: %m", right_fd);
5380                         }
5381                         newfd = -1;
5382                 } else {
5383                         newfd = openredirect(redir); /* always >= 0 */
5384                         if (fd == newfd) {
5385                                 /* Descriptor wasn't open before redirect.
5386                                  * Mark it for close in the future */
5387                                 if (need_to_remember(sv, fd)) {
5388                                         goto remember_to_close;
5389                                 }
5390                                 continue;
5391                         }
5392                 }
5393 #if ENABLE_ASH_BASH_COMPAT
5394  redirect_more:
5395 #endif
5396                 if (need_to_remember(sv, fd)) {
5397                         /* Copy old descriptor */
5398                         /* Careful to not accidentally "save"
5399                          * to the same fd as right side fd in N>&M */
5400                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5401                         i = fcntl(fd, F_DUPFD, minfd);
5402 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5403  * are closed in popredir() in the child, preventing them from leaking
5404  * into child. (popredir() also cleans up the mess in case of failures)
5405  */
5406                         if (i == -1) {
5407                                 i = errno;
5408                                 if (i != EBADF) {
5409                                         /* Strange error (e.g. "too many files" EMFILE?) */
5410                                         if (newfd >= 0)
5411                                                 close(newfd);
5412                                         errno = i;
5413                                         ash_msg_and_raise_error("%d: %m", fd);
5414                                         /* NOTREACHED */
5415                                 }
5416                                 /* EBADF: it is not open - good, remember to close it */
5417  remember_to_close:
5418                                 i = CLOSED;
5419                         } else { /* fd is open, save its copy */
5420                                 /* "exec fd>&-" should not close fds
5421                                  * which point to script file(s).
5422                                  * Force them to be restored afterwards */
5423                                 if (is_hidden_fd(sv, fd))
5424                                         i |= COPYFD_RESTORE;
5425                         }
5426                         if (fd == 2)
5427                                 copied_fd2 = i;
5428                         sv->two_fd[sv_pos].orig = fd;
5429                         sv->two_fd[sv_pos].copy = i;
5430                         sv_pos++;
5431                 }
5432                 if (newfd < 0) {
5433                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5434                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5435                                 /* Don't want to trigger debugging */
5436                                 if (fd != -1)
5437                                         close(fd);
5438                         } else {
5439                                 dup2_or_raise(redir->ndup.dupfd, fd);
5440                         }
5441                 } else if (fd != newfd) { /* move newfd to fd */
5442                         dup2_or_raise(newfd, fd);
5443 #if ENABLE_ASH_BASH_COMPAT
5444                         if (!(redir->nfile.type == NTO2 && fd == 2))
5445 #endif
5446                                 close(newfd);
5447                 }
5448 #if ENABLE_ASH_BASH_COMPAT
5449                 if (redir->nfile.type == NTO2 && fd == 1) {
5450                         /* We already redirected it to fd 1, now copy it to 2 */
5451                         newfd = 1;
5452                         fd = 2;
5453                         goto redirect_more;
5454                 }
5455 #endif
5456         } while ((redir = redir->nfile.next) != NULL);
5457
5458         INT_ON;
5459         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5460                 preverrout_fd = copied_fd2;
5461 }
5462
5463 /*
5464  * Undo the effects of the last redirection.
5465  */
5466 static void
5467 popredir(int drop, int restore)
5468 {
5469         struct redirtab *rp;
5470         int i;
5471
5472         if (redirlist == NULL)
5473                 return;
5474         INT_OFF;
5475         rp = redirlist;
5476         for (i = 0; i < rp->pair_count; i++) {
5477                 int fd = rp->two_fd[i].orig;
5478                 int copy = rp->two_fd[i].copy;
5479                 if (copy == CLOSED) {
5480                         if (!drop)
5481                                 close(fd);
5482                         continue;
5483                 }
5484                 if (copy != EMPTY) {
5485                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5486                                 copy &= ~COPYFD_RESTORE;
5487                                 /*close(fd);*/
5488                                 dup2_or_raise(copy, fd);
5489                         }
5490                         close(copy & ~COPYFD_RESTORE);
5491                 }
5492         }
5493         redirlist = rp->next;
5494         free(rp);
5495         INT_ON;
5496 }
5497
5498 /*
5499  * Undo all redirections.  Called on error or interrupt.
5500  */
5501
5502 static int
5503 redirectsafe(union node *redir, int flags)
5504 {
5505         int err;
5506         volatile int saveint;
5507         struct jmploc *volatile savehandler = exception_handler;
5508         struct jmploc jmploc;
5509
5510         SAVE_INT(saveint);
5511         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5512         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5513         if (!err) {
5514                 exception_handler = &jmploc;
5515                 redirect(redir, flags);
5516         }
5517         exception_handler = savehandler;
5518         if (err && exception_type != EXERROR)
5519                 longjmp(exception_handler->loc, 1);
5520         RESTORE_INT(saveint);
5521         return err;
5522 }
5523
5524
5525 /* ============ Routines to expand arguments to commands
5526  *
5527  * We have to deal with backquotes, shell variables, and file metacharacters.
5528  */
5529
5530 #if ENABLE_SH_MATH_SUPPORT
5531 static arith_t
5532 ash_arith(const char *s)
5533 {
5534         arith_state_t math_state;
5535         arith_t result;
5536
5537         math_state.lookupvar = lookupvar;
5538         math_state.setvar    = setvar0;
5539         //math_state.endofname = endofname;
5540
5541         INT_OFF;
5542         result = arith(&math_state, s);
5543         if (math_state.errmsg)
5544                 ash_msg_and_raise_error(math_state.errmsg);
5545         INT_ON;
5546
5547         return result;
5548 }
5549 #endif
5550
5551 /*
5552  * expandarg flags
5553  */
5554 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5555 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5556 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5557 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5558 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5559  * POSIX says for this case:
5560  *  Pathname expansion shall not be performed on the word by a
5561  *  non-interactive shell; an interactive shell may perform it, but shall
5562  *  do so only when the expansion would result in one word.
5563  * Currently, our code complies to the above rule by never globbing
5564  * redirection filenames.
5565  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5566  * (this means that on a typical Linux distro, bash almost always
5567  * performs globbing, and thus diverges from what we do).
5568  */
5569 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5570 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5571 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5572 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5573 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5574 /*
5575  * rmescape() flags
5576  */
5577 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5578 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5579 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5580 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5581 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5582
5583 /* Add CTLESC when necessary. */
5584 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5585 /* Do not skip NUL characters. */
5586 #define QUOTES_KEEPNUL EXP_TILDE
5587
5588 /*
5589  * Structure specifying which parts of the string should be searched
5590  * for IFS characters.
5591  */
5592 struct ifsregion {
5593         struct ifsregion *next; /* next region in list */
5594         int begoff;             /* offset of start of region */
5595         int endoff;             /* offset of end of region */
5596         int nulonly;            /* search for nul bytes only */
5597 };
5598
5599 struct arglist {
5600         struct strlist *list;
5601         struct strlist **lastp;
5602 };
5603
5604 /* output of current string */
5605 static char *expdest;
5606 /* list of back quote expressions */
5607 static struct nodelist *argbackq;
5608 /* first struct in list of ifs regions */
5609 static struct ifsregion ifsfirst;
5610 /* last struct in list */
5611 static struct ifsregion *ifslastp;
5612 /* holds expanded arg list */
5613 static struct arglist exparg;
5614
5615 /*
5616  * Our own itoa().
5617  */
5618 #if !ENABLE_SH_MATH_SUPPORT
5619 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5620 typedef long arith_t;
5621 # define ARITH_FMT "%ld"
5622 #endif
5623 static int
5624 cvtnum(arith_t num)
5625 {
5626         int len;
5627
5628         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5629         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5630         STADJUST(len, expdest);
5631         return len;
5632 }
5633
5634 /*
5635  * Break the argument string into pieces based upon IFS and add the
5636  * strings to the argument list.  The regions of the string to be
5637  * searched for IFS characters have been stored by recordregion.
5638  */
5639 static void
5640 ifsbreakup(char *string, struct arglist *arglist)
5641 {
5642         struct ifsregion *ifsp;
5643         struct strlist *sp;
5644         char *start;
5645         char *p;
5646         char *q;
5647         const char *ifs, *realifs;
5648         int ifsspc;
5649         int nulonly;
5650
5651         start = string;
5652         if (ifslastp != NULL) {
5653                 ifsspc = 0;
5654                 nulonly = 0;
5655                 realifs = ifsset() ? ifsval() : defifs;
5656                 ifsp = &ifsfirst;
5657                 do {
5658                         p = string + ifsp->begoff;
5659                         nulonly = ifsp->nulonly;
5660                         ifs = nulonly ? nullstr : realifs;
5661                         ifsspc = 0;
5662                         while (p < string + ifsp->endoff) {
5663                                 q = p;
5664                                 if ((unsigned char)*p == CTLESC)
5665                                         p++;
5666                                 if (!strchr(ifs, *p)) {
5667                                         p++;
5668                                         continue;
5669                                 }
5670                                 if (!nulonly)
5671                                         ifsspc = (strchr(defifs, *p) != NULL);
5672                                 /* Ignore IFS whitespace at start */
5673                                 if (q == start && ifsspc) {
5674                                         p++;
5675                                         start = p;
5676                                         continue;
5677                                 }
5678                                 *q = '\0';
5679                                 sp = stzalloc(sizeof(*sp));
5680                                 sp->text = start;
5681                                 *arglist->lastp = sp;
5682                                 arglist->lastp = &sp->next;
5683                                 p++;
5684                                 if (!nulonly) {
5685                                         for (;;) {
5686                                                 if (p >= string + ifsp->endoff) {
5687                                                         break;
5688                                                 }
5689                                                 q = p;
5690                                                 if ((unsigned char)*p == CTLESC)
5691                                                         p++;
5692                                                 if (strchr(ifs, *p) == NULL) {
5693                                                         p = q;
5694                                                         break;
5695                                                 }
5696                                                 if (strchr(defifs, *p) == NULL) {
5697                                                         if (ifsspc) {
5698                                                                 p++;
5699                                                                 ifsspc = 0;
5700                                                         } else {
5701                                                                 p = q;
5702                                                                 break;
5703                                                         }
5704                                                 } else
5705                                                         p++;
5706                                         }
5707                                 }
5708                                 start = p;
5709                         } /* while */
5710                         ifsp = ifsp->next;
5711                 } while (ifsp != NULL);
5712                 if (nulonly)
5713                         goto add;
5714         }
5715
5716         if (!*start)
5717                 return;
5718
5719  add:
5720         sp = stzalloc(sizeof(*sp));
5721         sp->text = start;
5722         *arglist->lastp = sp;
5723         arglist->lastp = &sp->next;
5724 }
5725
5726 static void
5727 ifsfree(void)
5728 {
5729         struct ifsregion *p = ifsfirst.next;
5730
5731         if (!p)
5732                 goto out;
5733
5734         INT_OFF;
5735         do {
5736                 struct ifsregion *ifsp;
5737                 ifsp = p->next;
5738                 free(p);
5739                 p = ifsp;
5740         } while (p);
5741         ifsfirst.next = NULL;
5742         INT_ON;
5743  out:
5744         ifslastp = NULL;
5745 }
5746
5747 static size_t
5748 esclen(const char *start, const char *p)
5749 {
5750         size_t esc = 0;
5751
5752         while (p > start && (unsigned char)*--p == CTLESC) {
5753                 esc++;
5754         }
5755         return esc;
5756 }
5757
5758 /*
5759  * Remove any CTLESC characters from a string.
5760  */
5761 static char *
5762 rmescapes(char *str, int flag)
5763 {
5764         static const char qchars[] ALIGN1 = {
5765                 IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' };
5766
5767         char *p, *q, *r;
5768         unsigned inquotes;
5769         unsigned protect_against_glob;
5770         unsigned globbing;
5771         IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;)
5772
5773         p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash));
5774         if (!p)
5775                 return str;
5776
5777         q = p;
5778         r = str;
5779         if (flag & RMESCAPE_ALLOC) {
5780                 size_t len = p - str;
5781                 size_t fulllen = len + strlen(p) + 1;
5782
5783                 if (flag & RMESCAPE_GROW) {
5784                         int strloc = str - (char *)stackblock();
5785                         r = makestrspace(fulllen, expdest);
5786                         /* p and str may be invalidated by makestrspace */
5787                         str = (char *)stackblock() + strloc;
5788                         p = str + len;
5789                 } else if (flag & RMESCAPE_HEAP) {
5790                         r = ckmalloc(fulllen);
5791                 } else {
5792                         r = stalloc(fulllen);
5793                 }
5794                 q = r;
5795                 if (len > 0) {
5796                         q = (char *)memcpy(q, str, len) + len;
5797                 }
5798         }
5799
5800         inquotes = 0;
5801         globbing = flag & RMESCAPE_GLOB;
5802         protect_against_glob = globbing;
5803         while (*p) {
5804                 if ((unsigned char)*p == CTLQUOTEMARK) {
5805 // Note: both inquotes and protect_against_glob only affect whether
5806                         inquotes = ~inquotes;
5807                         p++;
5808                         protect_against_glob = globbing;
5809                         continue;
5810                 }
5811                 if ((unsigned char)*p == CTLESC) {
5812                         p++;
5813 #if DEBUG
5814                         if (*p == '\0')
5815                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5816 #endif
5817                         if (protect_against_glob) {
5818                                 *q++ = '\\';
5819                         }
5820                 } else if (*p == '\\' && !inquotes) {
5821                         /* naked back slash */
5822                         protect_against_glob = 0;
5823                         goto copy;
5824                 }
5825 #if ENABLE_ASH_BASH_COMPAT
5826                 else if (*p == '/' && slash) {
5827                         /* stop handling globbing and mark location of slash */
5828                         globbing = slash = 0;
5829                         *p = CTLESC;
5830                 }
5831 #endif
5832                 protect_against_glob = globbing;
5833  copy:
5834                 *q++ = *p++;
5835         }
5836         *q = '\0';
5837         if (flag & RMESCAPE_GROW) {
5838                 expdest = r;
5839                 STADJUST(q - r + 1, expdest);
5840         }
5841         return r;
5842 }
5843 #define pmatch(a, b) !fnmatch((a), (b), 0)
5844
5845 /*
5846  * Prepare a pattern for a expmeta (internal glob(3)) call.
5847  *
5848  * Returns an stalloced string.
5849  */
5850 static char *
5851 preglob(const char *pattern, int flag)
5852 {
5853         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5854 }
5855
5856 /*
5857  * Put a string on the stack.
5858  */
5859 static void
5860 memtodest(const char *p, size_t len, int syntax, int quotes)
5861 {
5862         char *q;
5863
5864         if (!len)
5865                 return;
5866
5867         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5868
5869         do {
5870                 unsigned char c = *p++;
5871                 if (c) {
5872                         int n = SIT(c, syntax);
5873                         if ((quotes & QUOTES_ESC)
5874                          && ((n == CCTL)
5875                             ||  (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5876                                 && n == CBACK)
5877                                 )
5878                         ) {
5879                                 USTPUTC(CTLESC, q);
5880                         }
5881                 } else if (!(quotes & QUOTES_KEEPNUL))
5882                         continue;
5883                 USTPUTC(c, q);
5884         } while (--len);
5885
5886         expdest = q;
5887 }
5888
5889 static size_t
5890 strtodest(const char *p, int syntax, int quotes)
5891 {
5892         size_t len = strlen(p);
5893         memtodest(p, len, syntax, quotes);
5894         return len;
5895 }
5896
5897 /*
5898  * Record the fact that we have to scan this region of the
5899  * string for IFS characters.
5900  */
5901 static void
5902 recordregion(int start, int end, int nulonly)
5903 {
5904         struct ifsregion *ifsp;
5905
5906         if (ifslastp == NULL) {
5907                 ifsp = &ifsfirst;
5908         } else {
5909                 INT_OFF;
5910                 ifsp = ckzalloc(sizeof(*ifsp));
5911                 /*ifsp->next = NULL; - ckzalloc did it */
5912                 ifslastp->next = ifsp;
5913                 INT_ON;
5914         }
5915         ifslastp = ifsp;
5916         ifslastp->begoff = start;
5917         ifslastp->endoff = end;
5918         ifslastp->nulonly = nulonly;
5919 }
5920
5921 static void
5922 removerecordregions(int endoff)
5923 {
5924         if (ifslastp == NULL)
5925                 return;
5926
5927         if (ifsfirst.endoff > endoff) {
5928                 while (ifsfirst.next) {
5929                         struct ifsregion *ifsp;
5930                         INT_OFF;
5931                         ifsp = ifsfirst.next->next;
5932                         free(ifsfirst.next);
5933                         ifsfirst.next = ifsp;
5934                         INT_ON;
5935                 }
5936                 if (ifsfirst.begoff > endoff) {
5937                         ifslastp = NULL;
5938                 } else {
5939                         ifslastp = &ifsfirst;
5940                         ifsfirst.endoff = endoff;
5941                 }
5942                 return;
5943         }
5944
5945         ifslastp = &ifsfirst;
5946         while (ifslastp->next && ifslastp->next->begoff < endoff)
5947                 ifslastp = ifslastp->next;
5948         while (ifslastp->next) {
5949                 struct ifsregion *ifsp;
5950                 INT_OFF;
5951                 ifsp = ifslastp->next->next;
5952                 free(ifslastp->next);
5953                 ifslastp->next = ifsp;
5954                 INT_ON;
5955         }
5956         if (ifslastp->endoff > endoff)
5957                 ifslastp->endoff = endoff;
5958 }
5959
5960 static char *
5961 exptilde(char *startp, char *p, int flags)
5962 {
5963         unsigned char c;
5964         char *name;
5965         struct passwd *pw;
5966         const char *home;
5967         int quotes = flags & QUOTES_ESC;
5968
5969         name = p + 1;
5970
5971         while ((c = *++p) != '\0') {
5972                 switch (c) {
5973                 case CTLESC:
5974                         return startp;
5975                 case CTLQUOTEMARK:
5976                         return startp;
5977                 case ':':
5978                         if (flags & EXP_VARTILDE)
5979                                 goto done;
5980                         break;
5981                 case '/':
5982                 case CTLENDVAR:
5983                         goto done;
5984                 }
5985         }
5986  done:
5987         *p = '\0';
5988         if (*name == '\0') {
5989                 home = lookupvar("HOME");
5990         } else {
5991                 pw = getpwnam(name);
5992                 if (pw == NULL)
5993                         goto lose;
5994                 home = pw->pw_dir;
5995         }
5996         if (!home || !*home)
5997                 goto lose;
5998         *p = c;
5999         strtodest(home, SQSYNTAX, quotes);
6000         return p;
6001  lose:
6002         *p = c;
6003         return startp;
6004 }
6005
6006 /*
6007  * Execute a command inside back quotes.  If it's a builtin command, we
6008  * want to save its output in a block obtained from malloc.  Otherwise
6009  * we fork off a subprocess and get the output of the command via a pipe.
6010  * Should be called with interrupts off.
6011  */
6012 struct backcmd {                /* result of evalbackcmd */
6013         int fd;                 /* file descriptor to read from */
6014         int nleft;              /* number of chars in buffer */
6015         char *buf;              /* buffer */
6016         struct job *jp;         /* job structure for command */
6017 };
6018
6019 /* These forward decls are needed to use "eval" code for backticks handling: */
6020 #define EV_EXIT 01              /* exit after evaluating tree */
6021 static int evaltree(union node *, int);
6022
6023 static void FAST_FUNC
6024 evalbackcmd(union node *n, struct backcmd *result)
6025 {
6026         int pip[2];
6027         struct job *jp;
6028
6029         result->fd = -1;
6030         result->buf = NULL;
6031         result->nleft = 0;
6032         result->jp = NULL;
6033         if (n == NULL) {
6034                 goto out;
6035         }
6036
6037         if (pipe(pip) < 0)
6038                 ash_msg_and_raise_error("pipe call failed");
6039         jp = makejob(/*n,*/ 1);
6040         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6041                 /* child */
6042                 FORCE_INT_ON;
6043                 close(pip[0]);
6044                 if (pip[1] != 1) {
6045                         /*close(1);*/
6046                         dup2_or_raise(pip[1], 1);
6047                         close(pip[1]);
6048                 }
6049 /* TODO: eflag clearing makes the following not abort:
6050  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6051  * which is what bash does (unless it is in POSIX mode).
6052  * dash deleted "eflag = 0" line in the commit
6053  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6054  *  [EVAL] Don't clear eflag in evalbackcmd
6055  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6056  */
6057                 eflag = 0;
6058                 ifsfree();
6059                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6060                 /* NOTREACHED */
6061         }
6062         /* parent */
6063         close(pip[1]);
6064         result->fd = pip[0];
6065         result->jp = jp;
6066
6067  out:
6068         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6069                 result->fd, result->buf, result->nleft, result->jp));
6070 }
6071
6072 /*
6073  * Expand stuff in backwards quotes.
6074  */
6075 static void
6076 expbackq(union node *cmd, int flag)
6077 {
6078         struct backcmd in;
6079         int i;
6080         char buf[128];
6081         char *p;
6082         char *dest;
6083         int startloc;
6084         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6085         struct stackmark smark;
6086
6087         INT_OFF;
6088         startloc = expdest - (char *)stackblock();
6089         pushstackmark(&smark, startloc);
6090         evalbackcmd(cmd, &in);
6091         popstackmark(&smark);
6092
6093         p = in.buf;
6094         i = in.nleft;
6095         if (i == 0)
6096                 goto read;
6097         for (;;) {
6098                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6099  read:
6100                 if (in.fd < 0)
6101                         break;
6102                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6103                 TRACE(("expbackq: read returns %d\n", i));
6104                 if (i <= 0)
6105                         break;
6106                 p = buf;
6107         }
6108
6109         free(in.buf);
6110         if (in.fd >= 0) {
6111                 close(in.fd);
6112                 back_exitstatus = waitforjob(in.jp);
6113         }
6114         INT_ON;
6115
6116         /* Eat all trailing newlines */
6117         dest = expdest;
6118         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6119                 STUNPUTC(dest);
6120         expdest = dest;
6121
6122         if (!(flag & EXP_QUOTED))
6123                 recordregion(startloc, dest - (char *)stackblock(), 0);
6124         TRACE(("evalbackq: size:%d:'%.*s'\n",
6125                 (int)((dest - (char *)stackblock()) - startloc),
6126                 (int)((dest - (char *)stackblock()) - startloc),
6127                 stackblock() + startloc));
6128 }
6129
6130 #if ENABLE_SH_MATH_SUPPORT
6131 /*
6132  * Expand arithmetic expression.  Backup to start of expression,
6133  * evaluate, place result in (backed up) result, adjust string position.
6134  */
6135 static void
6136 expari(int flag)
6137 {
6138         char *p, *start;
6139         int begoff;
6140         int len;
6141
6142         /* ifsfree(); */
6143
6144         /*
6145          * This routine is slightly over-complicated for
6146          * efficiency.  Next we scan backwards looking for the
6147          * start of arithmetic.
6148          */
6149         start = stackblock();
6150         p = expdest - 1;
6151         *p = '\0';
6152         p--;
6153         while (1) {
6154                 int esc;
6155
6156                 while ((unsigned char)*p != CTLARI) {
6157                         p--;
6158 #if DEBUG
6159                         if (p < start) {
6160                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6161                         }
6162 #endif
6163                 }
6164
6165                 esc = esclen(start, p);
6166                 if (!(esc % 2)) {
6167                         break;
6168                 }
6169
6170                 p -= esc + 1;
6171         }
6172
6173         begoff = p - start;
6174
6175         removerecordregions(begoff);
6176
6177         expdest = p;
6178
6179         if (flag & QUOTES_ESC)
6180                 rmescapes(p + 1, 0);
6181
6182         len = cvtnum(ash_arith(p + 1));
6183
6184         if (!(flag & EXP_QUOTED))
6185                 recordregion(begoff, begoff + len, 0);
6186 }
6187 #endif
6188
6189 /* argstr needs it */
6190 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6191
6192 /*
6193  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6194  * characters to allow for further processing.  Otherwise treat
6195  * $@ like $* since no splitting will be performed.
6196  *
6197  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6198  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
6199  * for correct expansion of "B=$A" word.
6200  */
6201 static void
6202 argstr(char *p, int flags, struct strlist *var_str_list)
6203 {
6204         static const char spclchars[] ALIGN1 = {
6205                 '=',
6206                 ':',
6207                 CTLQUOTEMARK,
6208                 CTLENDVAR,
6209                 CTLESC,
6210                 CTLVAR,
6211                 CTLBACKQ,
6212 #if ENABLE_SH_MATH_SUPPORT
6213                 CTLENDARI,
6214 #endif
6215                 '\0'
6216         };
6217         const char *reject = spclchars;
6218         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6219         int inquotes;
6220         size_t length;
6221         int startloc;
6222
6223         if (!(flags & EXP_VARTILDE)) {
6224                 reject += 2;
6225         } else if (flags & EXP_VARTILDE2) {
6226                 reject++;
6227         }
6228         inquotes = 0;
6229         length = 0;
6230         if (flags & EXP_TILDE) {
6231                 char *q;
6232
6233                 flags &= ~EXP_TILDE;
6234  tilde:
6235                 q = p;
6236                 if (*q == '~')
6237                         p = exptilde(p, q, flags);
6238         }
6239  start:
6240         startloc = expdest - (char *)stackblock();
6241         for (;;) {
6242                 unsigned char c;
6243
6244                 length += strcspn(p + length, reject);
6245                 c = p[length];
6246                 if (c) {
6247                         if (!(c & 0x80)
6248                         IF_SH_MATH_SUPPORT(|| c == CTLENDARI)
6249                         ) {
6250                                 /* c == '=' || c == ':' || c == CTLENDARI */
6251                                 length++;
6252                         }
6253                 }
6254                 if (length > 0) {
6255                         int newloc;
6256                         expdest = stack_nputstr(p, length, expdest);
6257                         newloc = expdest - (char *)stackblock();
6258                         if (breakall && !inquotes && newloc > startloc) {
6259                                 recordregion(startloc, newloc, 0);
6260                         }
6261                         startloc = newloc;
6262                 }
6263                 p += length + 1;
6264                 length = 0;
6265
6266                 switch (c) {
6267                 case '\0':
6268                         goto breakloop;
6269                 case '=':
6270                         if (flags & EXP_VARTILDE2) {
6271                                 p--;
6272                                 continue;
6273                         }
6274                         flags |= EXP_VARTILDE2;
6275                         reject++;
6276                         /* fall through */
6277                 case ':':
6278                         /*
6279                          * sort of a hack - expand tildes in variable
6280                          * assignments (after the first '=' and after ':'s).
6281                          */
6282                         if (*--p == '~') {
6283                                 goto tilde;
6284                         }
6285                         continue;
6286                 }
6287
6288                 switch (c) {
6289                 case CTLENDVAR: /* ??? */
6290                         goto breakloop;
6291                 case CTLQUOTEMARK:
6292                         inquotes ^= EXP_QUOTED;
6293                         /* "$@" syntax adherence hack */
6294                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6295                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6296                                 goto start;
6297                         }
6298  addquote:
6299                         if (flags & QUOTES_ESC) {
6300                                 p--;
6301                                 length++;
6302                                 startloc++;
6303                         }
6304                         break;
6305                 case CTLESC:
6306                         startloc++;
6307                         length++;
6308
6309                         /*
6310                          * Quoted parameter expansion pattern: remove quote
6311                          * unless inside inner quotes or we have a literal
6312                          * backslash.
6313                          */
6314                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6315                             EXP_QPAT && *p != '\\')
6316                                 break;
6317
6318                         goto addquote;
6319                 case CTLVAR:
6320                         TRACE(("argstr: evalvar('%s')\n", p));
6321                         p = evalvar(p, flags | inquotes, var_str_list);
6322                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6323                         goto start;
6324                 case CTLBACKQ:
6325                         expbackq(argbackq->n, flags | inquotes);
6326                         argbackq = argbackq->next;
6327                         goto start;
6328 #if ENABLE_SH_MATH_SUPPORT
6329                 case CTLENDARI:
6330                         p--;
6331                         expari(flags | inquotes);
6332                         goto start;
6333 #endif
6334                 }
6335         }
6336  breakloop: ;
6337 }
6338
6339 static char *
6340 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6341                 char *pattern, int quotes, int zero)
6342 {
6343         char *loc, *loc2;
6344         char c;
6345
6346         loc = startp;
6347         loc2 = rmesc;
6348         do {
6349                 int match;
6350                 const char *s = loc2;
6351
6352                 c = *loc2;
6353                 if (zero) {
6354                         *loc2 = '\0';
6355                         s = rmesc;
6356                 }
6357                 match = pmatch(pattern, s);
6358
6359                 *loc2 = c;
6360                 if (match)
6361                         return loc;
6362                 if (quotes && (unsigned char)*loc == CTLESC)
6363                         loc++;
6364                 loc++;
6365                 loc2++;
6366         } while (c);
6367         return NULL;
6368 }
6369
6370 static char *
6371 scanright(char *startp, char *rmesc, char *rmescend,
6372                 char *pattern, int quotes, int match_at_start)
6373 {
6374 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6375         int try2optimize = match_at_start;
6376 #endif
6377         int esc = 0;
6378         char *loc;
6379         char *loc2;
6380
6381         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6382          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6383          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6384          * Logic:
6385          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6386          * and on each iteration they go back two/one char until they reach the beginning.
6387          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6388          */
6389         /* TODO: document in what other circumstances we are called. */
6390
6391         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6392                 int match;
6393                 char c = *loc2;
6394                 const char *s = loc2;
6395                 if (match_at_start) {
6396                         *loc2 = '\0';
6397                         s = rmesc;
6398                 }
6399                 match = pmatch(pattern, s);
6400                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6401                 *loc2 = c;
6402                 if (match)
6403                         return loc;
6404 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6405                 if (try2optimize) {
6406                         /* Maybe we can optimize this:
6407                          * if pattern ends with unescaped *, we can avoid checking
6408                          * shorter strings: if "foo*" doesnt match "raw_value_of_v",
6409                          * it wont match truncated "raw_value_of_" strings too.
6410                          */
6411                         unsigned plen = strlen(pattern);
6412                         /* Does it end with "*"? */
6413                         if (plen != 0 && pattern[--plen] == '*') {
6414                                 /* "xxxx*" is not escaped */
6415                                 /* "xxx\*" is escaped */
6416                                 /* "xx\\*" is not escaped */
6417                                 /* "x\\\*" is escaped */
6418                                 int slashes = 0;
6419                                 while (plen != 0 && pattern[--plen] == '\\')
6420                                         slashes++;
6421                                 if (!(slashes & 1))
6422                                         break; /* ends with unescaped "*" */
6423                         }
6424                         try2optimize = 0;
6425                 }
6426 #endif
6427                 loc--;
6428                 if (quotes) {
6429                         if (--esc < 0) {
6430                                 esc = esclen(startp, loc);
6431                         }
6432                         if (esc % 2) {
6433                                 esc--;
6434                                 loc--;
6435                         }
6436                 }
6437         }
6438         return NULL;
6439 }
6440
6441 static void varunset(const char *, const char *, const char *, int) NORETURN;
6442 static void
6443 varunset(const char *end, const char *var, const char *umsg, int varflags)
6444 {
6445         const char *msg;
6446         const char *tail;
6447
6448         tail = nullstr;
6449         msg = "parameter not set";
6450         if (umsg) {
6451                 if ((unsigned char)*end == CTLENDVAR) {
6452                         if (varflags & VSNUL)
6453                                 tail = " or null";
6454                 } else {
6455                         msg = umsg;
6456                 }
6457         }
6458         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6459 }
6460
6461 static const char *
6462 subevalvar(char *p, char *varname, int strloc, int subtype,
6463                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6464 {
6465         struct nodelist *saveargbackq = argbackq;
6466         int quotes = flag & QUOTES_ESC;
6467         char *startp;
6468         char *loc;
6469         char *rmesc, *rmescend;
6470         char *str;
6471         IF_ASH_BASH_COMPAT(char *repl = NULL;)
6472         IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
6473         int amount, resetloc;
6474         IF_ASH_BASH_COMPAT(int workloc;)
6475         int zero;
6476         char *(*scan)(char*, char*, char*, char*, int, int);
6477
6478         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6479         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6480
6481         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6482                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6483                         var_str_list);
6484         STPUTC('\0', expdest);
6485         argbackq = saveargbackq;
6486         startp = (char *)stackblock() + startloc;
6487
6488         switch (subtype) {
6489         case VSASSIGN:
6490                 setvar0(varname, startp);
6491                 amount = startp - expdest;
6492                 STADJUST(amount, expdest);
6493                 return startp;
6494
6495         case VSQUESTION:
6496                 varunset(p, varname, startp, varflags);
6497                 /* NOTREACHED */
6498
6499 #if ENABLE_ASH_BASH_COMPAT
6500         case VSSUBSTR:
6501 //TODO: support more general format ${v:EXPR:EXPR},
6502 // where EXPR follows $(()) rules
6503                 loc = str = stackblock() + strloc;
6504                 /* Read POS in ${var:POS:LEN} */
6505                 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6506                 len = str - startp - 1;
6507
6508                 /* *loc != '\0', guaranteed by parser */
6509                 if (quotes) {
6510                         char *ptr;
6511
6512                         /* Adjust the length by the number of escapes */
6513                         for (ptr = startp; ptr < (str - 1); ptr++) {
6514                                 if ((unsigned char)*ptr == CTLESC) {
6515                                         len--;
6516                                         ptr++;
6517                                 }
6518                         }
6519                 }
6520                 orig_len = len;
6521
6522                 if (*loc++ == ':') {
6523                         /* ${var::LEN} */
6524                         len = number(loc);
6525                 } else {
6526                         /* Skip POS in ${var:POS:LEN} */
6527                         len = orig_len;
6528                         while (*loc && *loc != ':') {
6529                                 /* TODO?
6530                                  * bash complains on: var=qwe; echo ${var:1a:123}
6531                                 if (!isdigit(*loc))
6532                                         ash_msg_and_raise_error(msg_illnum, str);
6533                                  */
6534                                 loc++;
6535                         }
6536                         if (*loc++ == ':') {
6537                                 len = number(loc);
6538                         }
6539                 }
6540                 if (pos < 0) {
6541                         /* ${VAR:$((-n)):l} starts n chars from the end */
6542                         pos = orig_len + pos;
6543                 }
6544                 if ((unsigned)pos >= orig_len) {
6545                         /* apart from obvious ${VAR:999999:l},
6546                          * covers ${VAR:$((-9999999)):l} - result is ""
6547                          * (bash-compat)
6548                          */
6549                         pos = 0;
6550                         len = 0;
6551                 }
6552                 if (len > (orig_len - pos))
6553                         len = orig_len - pos;
6554
6555                 for (str = startp; pos; str++, pos--) {
6556                         if (quotes && (unsigned char)*str == CTLESC)
6557                                 str++;
6558                 }
6559                 for (loc = startp; len; len--) {
6560                         if (quotes && (unsigned char)*str == CTLESC)
6561                                 *loc++ = *str++;
6562                         *loc++ = *str++;
6563                 }
6564                 *loc = '\0';
6565                 amount = loc - expdest;
6566                 STADJUST(amount, expdest);
6567                 return loc;
6568 #endif
6569         }
6570
6571         resetloc = expdest - (char *)stackblock();
6572
6573         /* We'll comeback here if we grow the stack while handling
6574          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6575          * stack will need rebasing, and we'll need to remove our work
6576          * areas each time
6577          */
6578  IF_ASH_BASH_COMPAT(restart:)
6579
6580         amount = expdest - ((char *)stackblock() + resetloc);
6581         STADJUST(-amount, expdest);
6582         startp = (char *)stackblock() + startloc;
6583
6584         rmesc = startp;
6585         rmescend = (char *)stackblock() + strloc;
6586         if (quotes) {
6587                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6588                 if (rmesc != startp) {
6589                         rmescend = expdest;
6590                         startp = (char *)stackblock() + startloc;
6591                 }
6592         }
6593         rmescend--;
6594         str = (char *)stackblock() + strloc;
6595         /*
6596          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6597          * The result is a_\_z_c (not a\_\_z_c)!
6598          *
6599          * The search pattern and replace string treat backslashes differently!
6600          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6601          * and string.  It's only used on the first call.
6602          */
6603         preglob(str, IF_ASH_BASH_COMPAT(
6604                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6605                         RMESCAPE_SLASH :) 0);
6606
6607 #if ENABLE_ASH_BASH_COMPAT
6608         workloc = expdest - (char *)stackblock();
6609         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6610                 char *idx, *end;
6611
6612                 if (!repl) {
6613                         repl = strchr(str, CTLESC);
6614                         if (repl)
6615                                 *repl++ = '\0';
6616                         else
6617                                 repl = nullstr;
6618                 }
6619                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6620
6621                 /* If there's no pattern to match, return the expansion unmolested */
6622                 if (str[0] == '\0')
6623                         return NULL;
6624
6625                 len = 0;
6626                 idx = startp;
6627                 end = str - 1;
6628                 while (idx < end) {
6629  try_to_match:
6630                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6631                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6632                         if (!loc) {
6633                                 /* No match, advance */
6634                                 char *restart_detect = stackblock();
6635  skip_matching:
6636                                 STPUTC(*idx, expdest);
6637                                 if (quotes && (unsigned char)*idx == CTLESC) {
6638                                         idx++;
6639                                         len++;
6640                                         STPUTC(*idx, expdest);
6641                                 }
6642                                 if (stackblock() != restart_detect)
6643                                         goto restart;
6644                                 idx++;
6645                                 len++;
6646                                 rmesc++;
6647                                 /* continue; - prone to quadratic behavior, smarter code: */
6648                                 if (idx >= end)
6649                                         break;
6650                                 if (str[0] == '*') {
6651                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6652                                          * it would never match "ong_string" etc, no point in trying.
6653                                          */
6654                                         goto skip_matching;
6655                                 }
6656                                 goto try_to_match;
6657                         }
6658
6659                         if (subtype == VSREPLACEALL) {
6660                                 while (idx < loc) {
6661                                         if (quotes && (unsigned char)*idx == CTLESC)
6662                                                 idx++;
6663                                         idx++;
6664                                         rmesc++;
6665                                 }
6666                         } else {
6667                                 idx = loc;
6668                         }
6669
6670                         //bb_error_msg("repl:'%s'", repl);
6671                         for (loc = (char*)repl; *loc; loc++) {
6672                                 char *restart_detect = stackblock();
6673                                 if (quotes && *loc == '\\') {
6674                                         STPUTC(CTLESC, expdest);
6675                                         len++;
6676                                 }
6677                                 STPUTC(*loc, expdest);
6678                                 if (stackblock() != restart_detect)
6679                                         goto restart;
6680                                 len++;
6681                         }
6682
6683                         if (subtype == VSREPLACE) {
6684                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6685                                 while (*idx) {
6686                                         char *restart_detect = stackblock();
6687                                         STPUTC(*idx, expdest);
6688                                         if (stackblock() != restart_detect)
6689                                                 goto restart;
6690                                         len++;
6691                                         idx++;
6692                                 }
6693                                 break;
6694                         }
6695                 }
6696
6697                 /* We've put the replaced text into a buffer at workloc, now
6698                  * move it to the right place and adjust the stack.
6699                  */
6700                 STPUTC('\0', expdest);
6701                 startp = (char *)stackblock() + startloc;
6702                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6703                 //bb_error_msg("startp:'%s'", startp);
6704                 amount = expdest - (startp + len);
6705                 STADJUST(-amount, expdest);
6706                 return startp;
6707         }
6708 #endif /* ENABLE_ASH_BASH_COMPAT */
6709
6710         subtype -= VSTRIMRIGHT;
6711 #if DEBUG
6712         if (subtype < 0 || subtype > 7)
6713                 abort();
6714 #endif
6715         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6716         zero = subtype >> 1;
6717         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6718         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6719
6720         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6721         if (loc) {
6722                 if (zero) {
6723                         memmove(startp, loc, str - loc);
6724                         loc = startp + (str - loc) - 1;
6725                 }
6726                 *loc = '\0';
6727                 amount = loc - expdest;
6728                 STADJUST(amount, expdest);
6729         }
6730         return loc;
6731 }
6732
6733 /*
6734  * Add the value of a specialized variable to the stack string.
6735  * name parameter (examples):
6736  * ash -c 'echo $1'      name:'1='
6737  * ash -c 'echo $qwe'    name:'qwe='
6738  * ash -c 'echo $$'      name:'$='
6739  * ash -c 'echo ${$}'    name:'$='
6740  * ash -c 'echo ${$##q}' name:'$=q'
6741  * ash -c 'echo ${#$}'   name:'$='
6742  * note: examples with bad shell syntax:
6743  * ash -c 'echo ${#$1}'  name:'$=1'
6744  * ash -c 'echo ${#1#}'  name:'1=#'
6745  */
6746 static NOINLINE ssize_t
6747 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6748 {
6749         const char *p;
6750         int num;
6751         int i;
6752         ssize_t len = 0;
6753         int sep;
6754         int quoted = *quotedp;
6755         int subtype = varflags & VSTYPE;
6756         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6757         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6758         int syntax;
6759
6760         sep = (flags & EXP_FULL) << CHAR_BIT;
6761         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6762
6763         switch (*name) {
6764         case '$':
6765                 num = rootpid;
6766                 goto numvar;
6767         case '?':
6768                 num = exitstatus;
6769                 goto numvar;
6770         case '#':
6771                 num = shellparam.nparam;
6772                 goto numvar;
6773         case '!':
6774                 num = backgndpid;
6775                 if (num == 0)
6776                         return -1;
6777  numvar:
6778                 len = cvtnum(num);
6779                 goto check_1char_name;
6780         case '-':
6781                 expdest = makestrspace(NOPTS, expdest);
6782                 for (i = NOPTS - 1; i >= 0; i--) {
6783                         if (optlist[i]) {
6784                                 USTPUTC(optletters(i), expdest);
6785                                 len++;
6786                         }
6787                 }
6788  check_1char_name:
6789 #if 0
6790                 /* handles cases similar to ${#$1} */
6791                 if (name[2] != '\0')
6792                         raise_error_syntax("bad substitution");
6793 #endif
6794                 break;
6795         case '@':
6796                 if (quoted && sep)
6797                         goto param;
6798                 /* fall through */
6799         case '*': {
6800                 char **ap;
6801                 char sepc;
6802
6803                 if (quoted)
6804                         sep = 0;
6805                 sep |= ifsset() ? ifsval()[0] : ' ';
6806  param:
6807                 sepc = sep;
6808                 *quotedp = !sepc;
6809                 ap = shellparam.p;
6810                 if (!ap)
6811                         return -1;
6812                 while ((p = *ap++) != NULL) {
6813                         len += strtodest(p, syntax, quotes);
6814
6815                         if (*ap && sep) {
6816                                 len++;
6817                                 memtodest(&sepc, 1, syntax, quotes);
6818                         }
6819                 }
6820                 break;
6821         } /* case '*' */
6822         case '0':
6823         case '1':
6824         case '2':
6825         case '3':
6826         case '4':
6827         case '5':
6828         case '6':
6829         case '7':
6830         case '8':
6831         case '9':
6832                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6833                 if (num < 0 || num > shellparam.nparam)
6834                         return -1;
6835                 p = num ? shellparam.p[num - 1] : arg0;
6836                 goto value;
6837         default:
6838                 /* NB: name has form "VAR=..." */
6839
6840                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6841                  * which should be considered before we check variables. */
6842                 if (var_str_list) {
6843                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6844                         p = NULL;
6845                         do {
6846                                 char *str, *eq;
6847                                 str = var_str_list->text;
6848                                 eq = strchr(str, '=');
6849                                 if (!eq) /* stop at first non-assignment */
6850                                         break;
6851                                 eq++;
6852                                 if (name_len == (unsigned)(eq - str)
6853                                  && strncmp(str, name, name_len) == 0
6854                                 ) {
6855                                         p = eq;
6856                                         /* goto value; - WRONG! */
6857                                         /* think "A=1 A=2 B=$A" */
6858                                 }
6859                                 var_str_list = var_str_list->next;
6860                         } while (var_str_list);
6861                         if (p)
6862                                 goto value;
6863                 }
6864                 p = lookupvar(name);
6865  value:
6866                 if (!p)
6867                         return -1;
6868
6869                 len = strtodest(p, syntax, quotes);
6870 #if ENABLE_UNICODE_SUPPORT
6871                 if (subtype == VSLENGTH && len > 0) {
6872                         reinit_unicode_for_ash();
6873                         if (unicode_status == UNICODE_ON) {
6874                                 STADJUST(-len, expdest);
6875                                 discard = 0;
6876                                 len = unicode_strlen(p);
6877                         }
6878                 }
6879 #endif
6880                 break;
6881         }
6882
6883         if (discard)
6884                 STADJUST(-len, expdest);
6885         return len;
6886 }
6887
6888 /*
6889  * Expand a variable, and return a pointer to the next character in the
6890  * input string.
6891  */
6892 static char *
6893 evalvar(char *p, int flag, struct strlist *var_str_list)
6894 {
6895         char varflags;
6896         char subtype;
6897         int quoted;
6898         char easy;
6899         char *var;
6900         int patloc;
6901         int startloc;
6902         ssize_t varlen;
6903
6904         varflags = (unsigned char) *p++;
6905         subtype = varflags & VSTYPE;
6906
6907         if (!subtype)
6908                 raise_error_syntax("bad substitution");
6909
6910         quoted = flag & EXP_QUOTED;
6911         var = p;
6912         easy = (!quoted || (*var == '@' && shellparam.nparam));
6913         startloc = expdest - (char *)stackblock();
6914         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
6915
6916  again:
6917         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
6918         if (varflags & VSNUL)
6919                 varlen--;
6920
6921         if (subtype == VSPLUS) {
6922                 varlen = -1 - varlen;
6923                 goto vsplus;
6924         }
6925
6926         if (subtype == VSMINUS) {
6927  vsplus:
6928                 if (varlen < 0) {
6929                         argstr(
6930                                 p,
6931                                 flag | EXP_TILDE | EXP_WORD,
6932                                 var_str_list
6933                         );
6934                         goto end;
6935                 }
6936                 goto record;
6937         }
6938
6939         if (subtype == VSASSIGN || subtype == VSQUESTION) {
6940                 if (varlen >= 0)
6941                         goto record;
6942
6943                 subevalvar(p, var, 0, subtype, startloc, varflags,
6944                            flag & ~QUOTES_ESC, var_str_list);
6945                 varflags &= ~VSNUL;
6946                 /*
6947                  * Remove any recorded regions beyond
6948                  * start of variable
6949                  */
6950                 removerecordregions(startloc);
6951                 goto again;
6952         }
6953
6954         if (varlen < 0 && uflag)
6955                 varunset(p, var, 0, 0);
6956
6957         if (subtype == VSLENGTH) {
6958                 cvtnum(varlen > 0 ? varlen : 0);
6959                 goto record;
6960         }
6961
6962         if (subtype == VSNORMAL) {
6963  record:
6964                 if (!easy)
6965                         goto end;
6966                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6967                 goto end;
6968         }
6969
6970 #if DEBUG
6971         switch (subtype) {
6972         case VSTRIMLEFT:
6973         case VSTRIMLEFTMAX:
6974         case VSTRIMRIGHT:
6975         case VSTRIMRIGHTMAX:
6976 #if ENABLE_ASH_BASH_COMPAT
6977         case VSSUBSTR:
6978         case VSREPLACE:
6979         case VSREPLACEALL:
6980 #endif
6981                 break;
6982         default:
6983                 abort();
6984         }
6985 #endif
6986
6987         if (varlen >= 0) {
6988                 /*
6989                  * Terminate the string and start recording the pattern
6990                  * right after it
6991                  */
6992                 STPUTC('\0', expdest);
6993                 patloc = expdest - (char *)stackblock();
6994                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
6995                                 startloc, varflags, flag, var_str_list)) {
6996                         int amount = expdest - (
6997                                 (char *)stackblock() + patloc - 1
6998                         );
6999                         STADJUST(-amount, expdest);
7000                 }
7001                 /* Remove any recorded regions beyond start of variable */
7002                 removerecordregions(startloc);
7003                 goto record;
7004         }
7005
7006  end:
7007         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7008                 int nesting = 1;
7009                 for (;;) {
7010                         unsigned char c = *p++;
7011                         if (c == CTLESC)
7012                                 p++;
7013                         else if (c == CTLBACKQ) {
7014                                 if (varlen >= 0)
7015                                         argbackq = argbackq->next;
7016                         } else if (c == CTLVAR) {
7017                                 if ((*p++ & VSTYPE) != VSNORMAL)
7018                                         nesting++;
7019                         } else if (c == CTLENDVAR) {
7020                                 if (--nesting == 0)
7021                                         break;
7022                         }
7023                 }
7024         }
7025         return p;
7026 }
7027
7028 /*
7029  * Add a file name to the list.
7030  */
7031 static void
7032 addfname(const char *name)
7033 {
7034         struct strlist *sp;
7035
7036         sp = stzalloc(sizeof(*sp));
7037         sp->text = sstrdup(name);
7038         *exparg.lastp = sp;
7039         exparg.lastp = &sp->next;
7040 }
7041
7042 /* If we want to use glob() from libc... */
7043 #if !ENABLE_ASH_INTERNAL_GLOB
7044
7045 /* Add the result of glob() to the list */
7046 static void
7047 addglob(const glob_t *pglob)
7048 {
7049         char **p = pglob->gl_pathv;
7050
7051         do {
7052                 addfname(*p);
7053         } while (*++p);
7054 }
7055 static void
7056 expandmeta(struct strlist *str /*, int flag*/)
7057 {
7058         /* TODO - EXP_REDIR */
7059
7060         while (str) {
7061                 char *p;
7062                 glob_t pglob;
7063                 int i;
7064
7065                 if (fflag)
7066                         goto nometa;
7067
7068                 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7069                 p = str->text;
7070                 while (*p) {
7071                         if (*p == '*')
7072                                 goto need_glob;
7073                         if (*p == '?')
7074                                 goto need_glob;
7075                         if (*p == '[')
7076                                 goto need_glob;
7077                         p++;
7078                 }
7079                 goto nometa;
7080
7081  need_glob:
7082                 INT_OFF;
7083                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7084 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7085 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7086 //
7087 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7088 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7089 // Which means you need to unescape the string, right? Not so fast:
7090 // if there _is_ a file named "file\?" (with backslash), it is returned
7091 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7092 // You DONT KNOW by looking at the result whether you need to unescape it.
7093 //
7094 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7095 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7096 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7097 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7098 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7099 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7100                 i = glob(p, 0, NULL, &pglob);
7101                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7102                 if (p != str->text)
7103                         free(p);
7104                 switch (i) {
7105                 case 0:
7106 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7107                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7108                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7109                                 goto nometa2;
7110 #endif
7111                         addglob(&pglob);
7112                         globfree(&pglob);
7113                         INT_ON;
7114                         break;
7115                 case GLOB_NOMATCH:
7116  //nometa2:
7117                         globfree(&pglob);
7118                         INT_ON;
7119  nometa:
7120                         *exparg.lastp = str;
7121                         rmescapes(str->text, 0);
7122                         exparg.lastp = &str->next;
7123                         break;
7124                 default:        /* GLOB_NOSPACE */
7125                         globfree(&pglob);
7126                         INT_ON;
7127                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7128                 }
7129                 str = str->next;
7130         }
7131 }
7132
7133 #else
7134 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7135
7136 /*
7137  * Do metacharacter (i.e. *, ?, [...]) expansion.
7138  */
7139 static void
7140 expmeta(char *expdir, char *enddir, char *name)
7141 {
7142         char *p;
7143         const char *cp;
7144         char *start;
7145         char *endname;
7146         int metaflag;
7147         struct stat statb;
7148         DIR *dirp;
7149         struct dirent *dp;
7150         int atend;
7151         int matchdot;
7152         int esc;
7153
7154         metaflag = 0;
7155         start = name;
7156         for (p = name; esc = 0, *p; p += esc + 1) {
7157                 if (*p == '*' || *p == '?')
7158                         metaflag = 1;
7159                 else if (*p == '[') {
7160                         char *q = p + 1;
7161                         if (*q == '!')
7162                                 q++;
7163                         for (;;) {
7164                                 if (*q == '\\')
7165                                         q++;
7166                                 if (*q == '/' || *q == '\0')
7167                                         break;
7168                                 if (*++q == ']') {
7169                                         metaflag = 1;
7170                                         break;
7171                                 }
7172                         }
7173                 } else {
7174                         if (*p == '\\')
7175                                 esc++;
7176                         if (p[esc] == '/') {
7177                                 if (metaflag)
7178                                         break;
7179                                 start = p + esc + 1;
7180                         }
7181                 }
7182         }
7183         if (metaflag == 0) {    /* we've reached the end of the file name */
7184                 if (enddir != expdir)
7185                         metaflag++;
7186                 p = name;
7187                 do {
7188                         if (*p == '\\')
7189                                 p++;
7190                         *enddir++ = *p;
7191                 } while (*p++);
7192                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7193                         addfname(expdir);
7194                 return;
7195         }
7196         endname = p;
7197         if (name < start) {
7198                 p = name;
7199                 do {
7200                         if (*p == '\\')
7201                                 p++;
7202                         *enddir++ = *p++;
7203                 } while (p < start);
7204         }
7205         if (enddir == expdir) {
7206                 cp = ".";
7207         } else if (enddir == expdir + 1 && *expdir == '/') {
7208                 cp = "/";
7209         } else {
7210                 cp = expdir;
7211                 enddir[-1] = '\0';
7212         }
7213         dirp = opendir(cp);
7214         if (dirp == NULL)
7215                 return;
7216         if (enddir != expdir)
7217                 enddir[-1] = '/';
7218         if (*endname == 0) {
7219                 atend = 1;
7220         } else {
7221                 atend = 0;
7222                 *endname = '\0';
7223                 endname += esc + 1;
7224         }
7225         matchdot = 0;
7226         p = start;
7227         if (*p == '\\')
7228                 p++;
7229         if (*p == '.')
7230                 matchdot++;
7231         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7232                 if (dp->d_name[0] == '.' && !matchdot)
7233                         continue;
7234                 if (pmatch(start, dp->d_name)) {
7235                         if (atend) {
7236                                 strcpy(enddir, dp->d_name);
7237                                 addfname(expdir);
7238                         } else {
7239                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7240                                         continue;
7241                                 p[-1] = '/';
7242                                 expmeta(expdir, p, endname);
7243                         }
7244                 }
7245         }
7246         closedir(dirp);
7247         if (!atend)
7248                 endname[-esc - 1] = esc ? '\\' : '/';
7249 }
7250
7251 static struct strlist *
7252 msort(struct strlist *list, int len)
7253 {
7254         struct strlist *p, *q = NULL;
7255         struct strlist **lpp;
7256         int half;
7257         int n;
7258
7259         if (len <= 1)
7260                 return list;
7261         half = len >> 1;
7262         p = list;
7263         for (n = half; --n >= 0;) {
7264                 q = p;
7265                 p = p->next;
7266         }
7267         q->next = NULL;                 /* terminate first half of list */
7268         q = msort(list, half);          /* sort first half of list */
7269         p = msort(p, len - half);               /* sort second half */
7270         lpp = &list;
7271         for (;;) {
7272 #if ENABLE_LOCALE_SUPPORT
7273                 if (strcoll(p->text, q->text) < 0)
7274 #else
7275                 if (strcmp(p->text, q->text) < 0)
7276 #endif
7277                                                 {
7278                         *lpp = p;
7279                         lpp = &p->next;
7280                         p = *lpp;
7281                         if (p == NULL) {
7282                                 *lpp = q;
7283                                 break;
7284                         }
7285                 } else {
7286                         *lpp = q;
7287                         lpp = &q->next;
7288                         q = *lpp;
7289                         if (q == NULL) {
7290                                 *lpp = p;
7291                                 break;
7292                         }
7293                 }
7294         }
7295         return list;
7296 }
7297
7298 /*
7299  * Sort the results of file name expansion.  It calculates the number of
7300  * strings to sort and then calls msort (short for merge sort) to do the
7301  * work.
7302  */
7303 static struct strlist *
7304 expsort(struct strlist *str)
7305 {
7306         int len;
7307         struct strlist *sp;
7308
7309         len = 0;
7310         for (sp = str; sp; sp = sp->next)
7311                 len++;
7312         return msort(str, len);
7313 }
7314
7315 static void
7316 expandmeta(struct strlist *str /*, int flag*/)
7317 {
7318         static const char metachars[] ALIGN1 = {
7319                 '*', '?', '[', 0
7320         };
7321         /* TODO - EXP_REDIR */
7322
7323         while (str) {
7324                 char *expdir;
7325                 struct strlist **savelastp;
7326                 struct strlist *sp;
7327                 char *p;
7328
7329                 if (fflag)
7330                         goto nometa;
7331                 if (!strpbrk(str->text, metachars))
7332                         goto nometa;
7333                 savelastp = exparg.lastp;
7334
7335                 INT_OFF;
7336                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7337                 {
7338                         int i = strlen(str->text);
7339 //BUGGY estimation of how long expanded name can be
7340                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7341                 }
7342                 expmeta(expdir, expdir, p);
7343                 free(expdir);
7344                 if (p != str->text)
7345                         free(p);
7346                 INT_ON;
7347                 if (exparg.lastp == savelastp) {
7348                         /*
7349                          * no matches
7350                          */
7351  nometa:
7352                         *exparg.lastp = str;
7353                         rmescapes(str->text, 0);
7354                         exparg.lastp = &str->next;
7355                 } else {
7356                         *exparg.lastp = NULL;
7357                         *savelastp = sp = expsort(*savelastp);
7358                         while (sp->next != NULL)
7359                                 sp = sp->next;
7360                         exparg.lastp = &sp->next;
7361                 }
7362                 str = str->next;
7363         }
7364 }
7365 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7366
7367 /*
7368  * Perform variable substitution and command substitution on an argument,
7369  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7370  * perform splitting and file name expansion.  When arglist is NULL, perform
7371  * here document expansion.
7372  */
7373 static void
7374 expandarg(union node *arg, struct arglist *arglist, int flag)
7375 {
7376         struct strlist *sp;
7377         char *p;
7378
7379         argbackq = arg->narg.backquote;
7380         STARTSTACKSTR(expdest);
7381         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7382         argstr(arg->narg.text, flag,
7383                         /* var_str_list: */ arglist ? arglist->list : NULL);
7384         p = _STPUTC('\0', expdest);
7385         expdest = p - 1;
7386         if (arglist == NULL) {
7387                 /* here document expanded */
7388                 goto out;
7389         }
7390         p = grabstackstr(p);
7391         TRACE(("expandarg: p:'%s'\n", p));
7392         exparg.lastp = &exparg.list;
7393         /*
7394          * TODO - EXP_REDIR
7395          */
7396         if (flag & EXP_FULL) {
7397                 ifsbreakup(p, &exparg);
7398                 *exparg.lastp = NULL;
7399                 exparg.lastp = &exparg.list;
7400                 expandmeta(exparg.list /*, flag*/);
7401         } else {
7402                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7403                         rmescapes(p, 0);
7404                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7405                 }
7406                 sp = stzalloc(sizeof(*sp));
7407                 sp->text = p;
7408                 *exparg.lastp = sp;
7409                 exparg.lastp = &sp->next;
7410         }
7411         *exparg.lastp = NULL;
7412         if (exparg.list) {
7413                 *arglist->lastp = exparg.list;
7414                 arglist->lastp = exparg.lastp;
7415         }
7416
7417  out:
7418         ifsfree();
7419 }
7420
7421 /*
7422  * Expand shell variables and backquotes inside a here document.
7423  */
7424 static void
7425 expandhere(union node *arg, int fd)
7426 {
7427         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7428         full_write(fd, stackblock(), expdest - (char *)stackblock());
7429 }
7430
7431 /*
7432  * Returns true if the pattern matches the string.
7433  */
7434 static int
7435 patmatch(char *pattern, const char *string)
7436 {
7437         return pmatch(preglob(pattern, 0), string);
7438 }
7439
7440 /*
7441  * See if a pattern matches in a case statement.
7442  */
7443 static int
7444 casematch(union node *pattern, char *val)
7445 {
7446         struct stackmark smark;
7447         int result;
7448
7449         setstackmark(&smark);
7450         argbackq = pattern->narg.backquote;
7451         STARTSTACKSTR(expdest);
7452         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7453                         /* var_str_list: */ NULL);
7454         STACKSTRNUL(expdest);
7455         ifsfree();
7456         result = patmatch(stackblock(), val);
7457         popstackmark(&smark);
7458         return result;
7459 }
7460
7461
7462 /* ============ find_command */
7463
7464 struct builtincmd {
7465         const char *name;
7466         int (*builtin)(int, char **) FAST_FUNC;
7467         /* unsigned flags; */
7468 };
7469 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7470 /* "regular" builtins always take precedence over commands,
7471  * regardless of PATH=....%builtin... position */
7472 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7473 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7474
7475 struct cmdentry {
7476         smallint cmdtype;       /* CMDxxx */
7477         union param {
7478                 int index;
7479                 /* index >= 0 for commands without path (slashes) */
7480                 /* (TODO: what exactly does the value mean? PATH position?) */
7481                 /* index == -1 for commands with slashes */
7482                 /* index == (-2 - applet_no) for NOFORK applets */
7483                 const struct builtincmd *cmd;
7484                 struct funcnode *func;
7485         } u;
7486 };
7487 /* values of cmdtype */
7488 #define CMDUNKNOWN      -1      /* no entry in table for command */
7489 #define CMDNORMAL       0       /* command is an executable program */
7490 #define CMDFUNCTION     1       /* command is a shell function */
7491 #define CMDBUILTIN      2       /* command is a shell builtin */
7492
7493 /* action to find_command() */
7494 #define DO_ERR          0x01    /* prints errors */
7495 #define DO_ABS          0x02    /* checks absolute paths */
7496 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7497 #define DO_ALTPATH      0x08    /* using alternate path */
7498 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7499
7500 static void find_command(char *, struct cmdentry *, int, const char *);
7501
7502
7503 /* ============ Hashing commands */
7504
7505 /*
7506  * When commands are first encountered, they are entered in a hash table.
7507  * This ensures that a full path search will not have to be done for them
7508  * on each invocation.
7509  *
7510  * We should investigate converting to a linear search, even though that
7511  * would make the command name "hash" a misnomer.
7512  */
7513
7514 struct tblentry {
7515         struct tblentry *next;  /* next entry in hash chain */
7516         union param param;      /* definition of builtin function */
7517         smallint cmdtype;       /* CMDxxx */
7518         char rehash;            /* if set, cd done since entry created */
7519         char cmdname[1];        /* name of command */
7520 };
7521
7522 static struct tblentry **cmdtable;
7523 #define INIT_G_cmdtable() do { \
7524         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7525 } while (0)
7526
7527 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7528
7529
7530 static void
7531 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7532 {
7533 #if ENABLE_FEATURE_SH_STANDALONE
7534         if (applet_no >= 0) {
7535                 if (APPLET_IS_NOEXEC(applet_no)) {
7536                         clearenv();
7537                         while (*envp)
7538                                 putenv(*envp++);
7539                         run_applet_no_and_exit(applet_no, argv);
7540                 }
7541                 /* re-exec ourselves with the new arguments */
7542                 execve(bb_busybox_exec_path, argv, envp);
7543                 /* If they called chroot or otherwise made the binary no longer
7544                  * executable, fall through */
7545         }
7546 #endif
7547
7548  repeat:
7549 #ifdef SYSV
7550         do {
7551                 execve(cmd, argv, envp);
7552         } while (errno == EINTR);
7553 #else
7554         execve(cmd, argv, envp);
7555 #endif
7556         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7557                 /* Run "cmd" as a shell script:
7558                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7559                  * "If the execve() function fails with ENOEXEC, the shell
7560                  * shall execute a command equivalent to having a shell invoked
7561                  * with the command name as its first operand,
7562                  * with any remaining arguments passed to the new shell"
7563                  *
7564                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7565                  * just call ourselves.
7566                  *
7567                  * Note that bash reads ~80 chars of the file, and if it sees
7568                  * a zero byte before it sees newline, it doesn't try to
7569                  * interpret it, but fails with "cannot execute binary file"
7570                  * message and exit code 126. For one, this prevents attempts
7571                  * to interpret foreign ELF binaries as shell scripts.
7572                  */
7573                 argv[0] = cmd;
7574                 cmd = (char*) bb_busybox_exec_path;
7575                 /* NB: this is only possible because all callers of shellexec()
7576                  * ensure that the argv[-1] slot exists!
7577                  */
7578                 argv--;
7579                 argv[0] = (char*) "ash";
7580                 goto repeat;
7581         }
7582 }
7583
7584 /*
7585  * Exec a program.  Never returns.  If you change this routine, you may
7586  * have to change the find_command routine as well.
7587  * argv[-1] must exist and be writable! See tryexec() for why.
7588  */
7589 static void shellexec(char **, const char *, int) NORETURN;
7590 static void
7591 shellexec(char **argv, const char *path, int idx)
7592 {
7593         char *cmdname;
7594         int e;
7595         char **envp;
7596         int exerrno;
7597         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7598
7599         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7600         if (strchr(argv[0], '/') != NULL
7601 #if ENABLE_FEATURE_SH_STANDALONE
7602          || (applet_no = find_applet_by_name(argv[0])) >= 0
7603 #endif
7604         ) {
7605                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7606                 if (applet_no >= 0) {
7607                         /* We tried execing ourself, but it didn't work.
7608                          * Maybe /proc/self/exe doesn't exist?
7609                          * Try $PATH search.
7610                          */
7611                         goto try_PATH;
7612                 }
7613                 e = errno;
7614         } else {
7615  try_PATH:
7616                 e = ENOENT;
7617                 while ((cmdname = path_advance(&path, argv[0])) != NULL) {
7618                         if (--idx < 0 && pathopt == NULL) {
7619                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7620                                 if (errno != ENOENT && errno != ENOTDIR)
7621                                         e = errno;
7622                         }
7623                         stunalloc(cmdname);
7624                 }
7625         }
7626
7627         /* Map to POSIX errors */
7628         switch (e) {
7629         case EACCES:
7630                 exerrno = 126;
7631                 break;
7632         case ENOENT:
7633                 exerrno = 127;
7634                 break;
7635         default:
7636                 exerrno = 2;
7637                 break;
7638         }
7639         exitstatus = exerrno;
7640         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7641                 argv[0], e, suppress_int));
7642         ash_msg_and_raise(EXEXIT, "%s: %s", argv[0], errmsg(e, "not found"));
7643         /* NOTREACHED */
7644 }
7645
7646 static void
7647 printentry(struct tblentry *cmdp)
7648 {
7649         int idx;
7650         const char *path;
7651         char *name;
7652
7653         idx = cmdp->param.index;
7654         path = pathval();
7655         do {
7656                 name = path_advance(&path, cmdp->cmdname);
7657                 stunalloc(name);
7658         } while (--idx >= 0);
7659         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7660 }
7661
7662 /*
7663  * Clear out command entries.  The argument specifies the first entry in
7664  * PATH which has changed.
7665  */
7666 static void
7667 clearcmdentry(int firstchange)
7668 {
7669         struct tblentry **tblp;
7670         struct tblentry **pp;
7671         struct tblentry *cmdp;
7672
7673         INT_OFF;
7674         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7675                 pp = tblp;
7676                 while ((cmdp = *pp) != NULL) {
7677                         if ((cmdp->cmdtype == CMDNORMAL &&
7678                              cmdp->param.index >= firstchange)
7679                          || (cmdp->cmdtype == CMDBUILTIN &&
7680                              builtinloc >= firstchange)
7681                         ) {
7682                                 *pp = cmdp->next;
7683                                 free(cmdp);
7684                         } else {
7685                                 pp = &cmdp->next;
7686                         }
7687                 }
7688         }
7689         INT_ON;
7690 }
7691
7692 /*
7693  * Locate a command in the command hash table.  If "add" is nonzero,
7694  * add the command to the table if it is not already present.  The
7695  * variable "lastcmdentry" is set to point to the address of the link
7696  * pointing to the entry, so that delete_cmd_entry can delete the
7697  * entry.
7698  *
7699  * Interrupts must be off if called with add != 0.
7700  */
7701 static struct tblentry **lastcmdentry;
7702
7703 static struct tblentry *
7704 cmdlookup(const char *name, int add)
7705 {
7706         unsigned int hashval;
7707         const char *p;
7708         struct tblentry *cmdp;
7709         struct tblentry **pp;
7710
7711         p = name;
7712         hashval = (unsigned char)*p << 4;
7713         while (*p)
7714                 hashval += (unsigned char)*p++;
7715         hashval &= 0x7FFF;
7716         pp = &cmdtable[hashval % CMDTABLESIZE];
7717         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7718                 if (strcmp(cmdp->cmdname, name) == 0)
7719                         break;
7720                 pp = &cmdp->next;
7721         }
7722         if (add && cmdp == NULL) {
7723                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7724                                 + strlen(name)
7725                                 /* + 1 - already done because
7726                                  * tblentry::cmdname is char[1] */);
7727                 /*cmdp->next = NULL; - ckzalloc did it */
7728                 cmdp->cmdtype = CMDUNKNOWN;
7729                 strcpy(cmdp->cmdname, name);
7730         }
7731         lastcmdentry = pp;
7732         return cmdp;
7733 }
7734
7735 /*
7736  * Delete the command entry returned on the last lookup.
7737  */
7738 static void
7739 delete_cmd_entry(void)
7740 {
7741         struct tblentry *cmdp;
7742
7743         INT_OFF;
7744         cmdp = *lastcmdentry;
7745         *lastcmdentry = cmdp->next;
7746         if (cmdp->cmdtype == CMDFUNCTION)
7747                 freefunc(cmdp->param.func);
7748         free(cmdp);
7749         INT_ON;
7750 }
7751
7752 /*
7753  * Add a new command entry, replacing any existing command entry for
7754  * the same name - except special builtins.
7755  */
7756 static void
7757 addcmdentry(char *name, struct cmdentry *entry)
7758 {
7759         struct tblentry *cmdp;
7760
7761         cmdp = cmdlookup(name, 1);
7762         if (cmdp->cmdtype == CMDFUNCTION) {
7763                 freefunc(cmdp->param.func);
7764         }
7765         cmdp->cmdtype = entry->cmdtype;
7766         cmdp->param = entry->u;
7767         cmdp->rehash = 0;
7768 }
7769
7770 static int FAST_FUNC
7771 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7772 {
7773         struct tblentry **pp;
7774         struct tblentry *cmdp;
7775         int c;
7776         struct cmdentry entry;
7777         char *name;
7778
7779         if (nextopt("r") != '\0') {
7780                 clearcmdentry(0);
7781                 return 0;
7782         }
7783
7784         if (*argptr == NULL) {
7785                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7786                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7787                                 if (cmdp->cmdtype == CMDNORMAL)
7788                                         printentry(cmdp);
7789                         }
7790                 }
7791                 return 0;
7792         }
7793
7794         c = 0;
7795         while ((name = *argptr) != NULL) {
7796                 cmdp = cmdlookup(name, 0);
7797                 if (cmdp != NULL
7798                  && (cmdp->cmdtype == CMDNORMAL
7799                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7800                 ) {
7801                         delete_cmd_entry();
7802                 }
7803                 find_command(name, &entry, DO_ERR, pathval());
7804                 if (entry.cmdtype == CMDUNKNOWN)
7805                         c = 1;
7806                 argptr++;
7807         }
7808         return c;
7809 }
7810
7811 /*
7812  * Called when a cd is done.  Marks all commands so the next time they
7813  * are executed they will be rehashed.
7814  */
7815 static void
7816 hashcd(void)
7817 {
7818         struct tblentry **pp;
7819         struct tblentry *cmdp;
7820
7821         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7822                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7823                         if (cmdp->cmdtype == CMDNORMAL
7824                          || (cmdp->cmdtype == CMDBUILTIN
7825                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7826                              && builtinloc > 0)
7827                         ) {
7828                                 cmdp->rehash = 1;
7829                         }
7830                 }
7831         }
7832 }
7833
7834 /*
7835  * Fix command hash table when PATH changed.
7836  * Called before PATH is changed.  The argument is the new value of PATH;
7837  * pathval() still returns the old value at this point.
7838  * Called with interrupts off.
7839  */
7840 static void FAST_FUNC
7841 changepath(const char *new)
7842 {
7843         const char *old;
7844         int firstchange;
7845         int idx;
7846         int idx_bltin;
7847
7848         old = pathval();
7849         firstchange = 9999;     /* assume no change */
7850         idx = 0;
7851         idx_bltin = -1;
7852         for (;;) {
7853                 if (*old != *new) {
7854                         firstchange = idx;
7855                         if ((*old == '\0' && *new == ':')
7856                          || (*old == ':' && *new == '\0')
7857                         ) {
7858                                 firstchange++;
7859                         }
7860                         old = new;      /* ignore subsequent differences */
7861                 }
7862                 if (*new == '\0')
7863                         break;
7864                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7865                         idx_bltin = idx;
7866                 if (*new == ':')
7867                         idx++;
7868                 new++;
7869                 old++;
7870         }
7871         if (builtinloc < 0 && idx_bltin >= 0)
7872                 builtinloc = idx_bltin;             /* zap builtins */
7873         if (builtinloc >= 0 && idx_bltin < 0)
7874                 firstchange = 0;
7875         clearcmdentry(firstchange);
7876         builtinloc = idx_bltin;
7877 }
7878 enum {
7879         TEOF,
7880         TNL,
7881         TREDIR,
7882         TWORD,
7883         TSEMI,
7884         TBACKGND,
7885         TAND,
7886         TOR,
7887         TPIPE,
7888         TLP,
7889         TRP,
7890         TENDCASE,
7891         TENDBQUOTE,
7892         TNOT,
7893         TCASE,
7894         TDO,
7895         TDONE,
7896         TELIF,
7897         TELSE,
7898         TESAC,
7899         TFI,
7900         TFOR,
7901 #if ENABLE_ASH_BASH_COMPAT
7902         TFUNCTION,
7903 #endif
7904         TIF,
7905         TIN,
7906         TTHEN,
7907         TUNTIL,
7908         TWHILE,
7909         TBEGIN,
7910         TEND
7911 };
7912 typedef smallint token_id_t;
7913
7914 /* Nth bit indicates if token marks the end of a list */
7915 enum {
7916         tokendlist = 0
7917         /*  0 */ | (1u << TEOF)
7918         /*  1 */ | (0u << TNL)
7919         /*  2 */ | (0u << TREDIR)
7920         /*  3 */ | (0u << TWORD)
7921         /*  4 */ | (0u << TSEMI)
7922         /*  5 */ | (0u << TBACKGND)
7923         /*  6 */ | (0u << TAND)
7924         /*  7 */ | (0u << TOR)
7925         /*  8 */ | (0u << TPIPE)
7926         /*  9 */ | (0u << TLP)
7927         /* 10 */ | (1u << TRP)
7928         /* 11 */ | (1u << TENDCASE)
7929         /* 12 */ | (1u << TENDBQUOTE)
7930         /* 13 */ | (0u << TNOT)
7931         /* 14 */ | (0u << TCASE)
7932         /* 15 */ | (1u << TDO)
7933         /* 16 */ | (1u << TDONE)
7934         /* 17 */ | (1u << TELIF)
7935         /* 18 */ | (1u << TELSE)
7936         /* 19 */ | (1u << TESAC)
7937         /* 20 */ | (1u << TFI)
7938         /* 21 */ | (0u << TFOR)
7939 #if ENABLE_ASH_BASH_COMPAT
7940         /* 22 */ | (0u << TFUNCTION)
7941 #endif
7942         /* 23 */ | (0u << TIF)
7943         /* 24 */ | (0u << TIN)
7944         /* 25 */ | (1u << TTHEN)
7945         /* 26 */ | (0u << TUNTIL)
7946         /* 27 */ | (0u << TWHILE)
7947         /* 28 */ | (0u << TBEGIN)
7948         /* 29 */ | (1u << TEND)
7949         , /* thus far 29 bits used */
7950 };
7951
7952 static const char *const tokname_array[] = {
7953         "end of file",
7954         "newline",
7955         "redirection",
7956         "word",
7957         ";",
7958         "&",
7959         "&&",
7960         "||",
7961         "|",
7962         "(",
7963         ")",
7964         ";;",
7965         "`",
7966 #define KWDOFFSET 13
7967         /* the following are keywords */
7968         "!",
7969         "case",
7970         "do",
7971         "done",
7972         "elif",
7973         "else",
7974         "esac",
7975         "fi",
7976         "for",
7977 #if ENABLE_ASH_BASH_COMPAT
7978         "function",
7979 #endif
7980         "if",
7981         "in",
7982         "then",
7983         "until",
7984         "while",
7985         "{",
7986         "}",
7987 };
7988
7989 /* Wrapper around strcmp for qsort/bsearch/... */
7990 static int
7991 pstrcmp(const void *a, const void *b)
7992 {
7993         return strcmp((char*)a, *(char**)b);
7994 }
7995
7996 static const char *const *
7997 findkwd(const char *s)
7998 {
7999         return bsearch(s, tokname_array + KWDOFFSET,
8000                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8001                         sizeof(tokname_array[0]), pstrcmp);
8002 }
8003
8004 /*
8005  * Locate and print what a word is...
8006  */
8007 static int
8008 describe_command(char *command, const char *path, int describe_command_verbose)
8009 {
8010         struct cmdentry entry;
8011         struct tblentry *cmdp;
8012 #if ENABLE_ASH_ALIAS
8013         const struct alias *ap;
8014 #endif
8015
8016         path = path ? path : pathval();
8017
8018         if (describe_command_verbose) {
8019                 out1str(command);
8020         }
8021
8022         /* First look at the keywords */
8023         if (findkwd(command)) {
8024                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8025                 goto out;
8026         }
8027
8028 #if ENABLE_ASH_ALIAS
8029         /* Then look at the aliases */
8030         ap = lookupalias(command, 0);
8031         if (ap != NULL) {
8032                 if (!describe_command_verbose) {
8033                         out1str("alias ");
8034                         printalias(ap);
8035                         return 0;
8036                 }
8037                 out1fmt(" is an alias for %s", ap->val);
8038                 goto out;
8039         }
8040 #endif
8041         /* Then check if it is a tracked alias */
8042         cmdp = cmdlookup(command, 0);
8043         if (cmdp != NULL) {
8044                 entry.cmdtype = cmdp->cmdtype;
8045                 entry.u = cmdp->param;
8046         } else {
8047                 /* Finally use brute force */
8048                 find_command(command, &entry, DO_ABS, path);
8049         }
8050
8051         switch (entry.cmdtype) {
8052         case CMDNORMAL: {
8053                 int j = entry.u.index;
8054                 char *p;
8055                 if (j < 0) {
8056                         p = command;
8057                 } else {
8058                         do {
8059                                 p = path_advance(&path, command);
8060                                 stunalloc(p);
8061                         } while (--j >= 0);
8062                 }
8063                 if (describe_command_verbose) {
8064                         out1fmt(" is%s %s",
8065                                 (cmdp ? " a tracked alias for" : nullstr), p
8066                         );
8067                 } else {
8068                         out1str(p);
8069                 }
8070                 break;
8071         }
8072
8073         case CMDFUNCTION:
8074                 if (describe_command_verbose) {
8075                         out1str(" is a shell function");
8076                 } else {
8077                         out1str(command);
8078                 }
8079                 break;
8080
8081         case CMDBUILTIN:
8082                 if (describe_command_verbose) {
8083                         out1fmt(" is a %sshell builtin",
8084                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8085                                         "special " : nullstr
8086                         );
8087                 } else {
8088                         out1str(command);
8089                 }
8090                 break;
8091
8092         default:
8093                 if (describe_command_verbose) {
8094                         out1str(": not found\n");
8095                 }
8096                 return 127;
8097         }
8098  out:
8099         out1str("\n");
8100         return 0;
8101 }
8102
8103 static int FAST_FUNC
8104 typecmd(int argc UNUSED_PARAM, char **argv)
8105 {
8106         int i = 1;
8107         int err = 0;
8108         int verbose = 1;
8109
8110         /* type -p ... ? (we don't bother checking for 'p') */
8111         if (argv[1] && argv[1][0] == '-') {
8112                 i++;
8113                 verbose = 0;
8114         }
8115         while (argv[i]) {
8116                 err |= describe_command(argv[i++], NULL, verbose);
8117         }
8118         return err;
8119 }
8120
8121 #if ENABLE_ASH_CMDCMD
8122 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8123 static char **
8124 parse_command_args(char **argv, const char **path)
8125 {
8126         char *cp, c;
8127
8128         for (;;) {
8129                 cp = *++argv;
8130                 if (!cp)
8131                         return NULL;
8132                 if (*cp++ != '-')
8133                         break;
8134                 c = *cp++;
8135                 if (!c)
8136                         break;
8137                 if (c == '-' && !*cp) {
8138                         if (!*++argv)
8139                                 return NULL;
8140                         break;
8141                 }
8142                 do {
8143                         switch (c) {
8144                         case 'p':
8145                                 *path = bb_default_path;
8146                                 break;
8147                         default:
8148                                 /* run 'typecmd' for other options */
8149                                 return NULL;
8150                         }
8151                         c = *cp++;
8152                 } while (c);
8153         }
8154         return argv;
8155 }
8156
8157 static int FAST_FUNC
8158 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8159 {
8160         char *cmd;
8161         int c;
8162         enum {
8163                 VERIFY_BRIEF = 1,
8164                 VERIFY_VERBOSE = 2,
8165         } verify = 0;
8166         const char *path = NULL;
8167
8168         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8169          * never reaches this function.
8170          */
8171
8172         while ((c = nextopt("pvV")) != '\0')
8173                 if (c == 'V')
8174                         verify |= VERIFY_VERBOSE;
8175                 else if (c == 'v')
8176                         /*verify |= VERIFY_BRIEF*/;
8177 #if DEBUG
8178                 else if (c != 'p')
8179                         abort();
8180 #endif
8181                 else
8182                         path = bb_default_path;
8183
8184         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8185         cmd = *argptr;
8186         if (/*verify && */ cmd)
8187                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8188
8189         return 0;
8190 }
8191 #endif
8192
8193
8194 /*static int funcblocksize;     // size of structures in function */
8195 /*static int funcstringsize;    // size of strings in node */
8196 static void *funcblock;         /* block to allocate function from */
8197 static char *funcstring_end;    /* end of block to allocate strings from */
8198
8199 /* flags in argument to evaltree */
8200 #define EV_EXIT    01           /* exit after evaluating tree */
8201 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8202
8203 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8204         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8205         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8206         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8207         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8208         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8209         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8210         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8211         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8212         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8213         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8214         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8215         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8216         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8217         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8218         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8219         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8220         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8221 #if ENABLE_ASH_BASH_COMPAT
8222         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8223 #endif
8224         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8225         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8226         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8227         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8228         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8229         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8230         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8231         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8232         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8233 };
8234
8235 static int calcsize(int funcblocksize, union node *n);
8236
8237 static int
8238 sizenodelist(int funcblocksize, struct nodelist *lp)
8239 {
8240         while (lp) {
8241                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8242                 funcblocksize = calcsize(funcblocksize, lp->n);
8243                 lp = lp->next;
8244         }
8245         return funcblocksize;
8246 }
8247
8248 static int
8249 calcsize(int funcblocksize, union node *n)
8250 {
8251         if (n == NULL)
8252                 return funcblocksize;
8253         funcblocksize += nodesize[n->type];
8254         switch (n->type) {
8255         case NCMD:
8256                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8257                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8258                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8259                 break;
8260         case NPIPE:
8261                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8262                 break;
8263         case NREDIR:
8264         case NBACKGND:
8265         case NSUBSHELL:
8266                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8267                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8268                 break;
8269         case NAND:
8270         case NOR:
8271         case NSEMI:
8272         case NWHILE:
8273         case NUNTIL:
8274                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8275                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8276                 break;
8277         case NIF:
8278                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8279                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8280                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8281                 break;
8282         case NFOR:
8283                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8284                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8285                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8286                 break;
8287         case NCASE:
8288                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8289                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8290                 break;
8291         case NCLIST:
8292                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8293                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8294                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8295                 break;
8296         case NDEFUN:
8297         case NARG:
8298                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8299                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8300                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8301                 break;
8302         case NTO:
8303 #if ENABLE_ASH_BASH_COMPAT
8304         case NTO2:
8305 #endif
8306         case NCLOBBER:
8307         case NFROM:
8308         case NFROMTO:
8309         case NAPPEND:
8310                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8311                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8312                 break;
8313         case NTOFD:
8314         case NFROMFD:
8315                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8316                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8317         break;
8318         case NHERE:
8319         case NXHERE:
8320                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8321                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8322                 break;
8323         case NNOT:
8324                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8325                 break;
8326         };
8327         return funcblocksize;
8328 }
8329
8330 static char *
8331 nodeckstrdup(char *s)
8332 {
8333         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8334         return strcpy(funcstring_end, s);
8335 }
8336
8337 static union node *copynode(union node *);
8338
8339 static struct nodelist *
8340 copynodelist(struct nodelist *lp)
8341 {
8342         struct nodelist *start;
8343         struct nodelist **lpp;
8344
8345         lpp = &start;
8346         while (lp) {
8347                 *lpp = funcblock;
8348                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8349                 (*lpp)->n = copynode(lp->n);
8350                 lp = lp->next;
8351                 lpp = &(*lpp)->next;
8352         }
8353         *lpp = NULL;
8354         return start;
8355 }
8356
8357 static union node *
8358 copynode(union node *n)
8359 {
8360         union node *new;
8361
8362         if (n == NULL)
8363                 return NULL;
8364         new = funcblock;
8365         funcblock = (char *) funcblock + nodesize[n->type];
8366
8367         switch (n->type) {
8368         case NCMD:
8369                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8370                 new->ncmd.args = copynode(n->ncmd.args);
8371                 new->ncmd.assign = copynode(n->ncmd.assign);
8372                 break;
8373         case NPIPE:
8374                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8375                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8376                 break;
8377         case NREDIR:
8378         case NBACKGND:
8379         case NSUBSHELL:
8380                 new->nredir.redirect = copynode(n->nredir.redirect);
8381                 new->nredir.n = copynode(n->nredir.n);
8382                 break;
8383         case NAND:
8384         case NOR:
8385         case NSEMI:
8386         case NWHILE:
8387         case NUNTIL:
8388                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8389                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8390                 break;
8391         case NIF:
8392                 new->nif.elsepart = copynode(n->nif.elsepart);
8393                 new->nif.ifpart = copynode(n->nif.ifpart);
8394                 new->nif.test = copynode(n->nif.test);
8395                 break;
8396         case NFOR:
8397                 new->nfor.var = nodeckstrdup(n->nfor.var);
8398                 new->nfor.body = copynode(n->nfor.body);
8399                 new->nfor.args = copynode(n->nfor.args);
8400                 break;
8401         case NCASE:
8402                 new->ncase.cases = copynode(n->ncase.cases);
8403                 new->ncase.expr = copynode(n->ncase.expr);
8404                 break;
8405         case NCLIST:
8406                 new->nclist.body = copynode(n->nclist.body);
8407                 new->nclist.pattern = copynode(n->nclist.pattern);
8408                 new->nclist.next = copynode(n->nclist.next);
8409                 break;
8410         case NDEFUN:
8411         case NARG:
8412                 new->narg.backquote = copynodelist(n->narg.backquote);
8413                 new->narg.text = nodeckstrdup(n->narg.text);
8414                 new->narg.next = copynode(n->narg.next);
8415                 break;
8416         case NTO:
8417 #if ENABLE_ASH_BASH_COMPAT
8418         case NTO2:
8419 #endif
8420         case NCLOBBER:
8421         case NFROM:
8422         case NFROMTO:
8423         case NAPPEND:
8424                 new->nfile.fname = copynode(n->nfile.fname);
8425                 new->nfile.fd = n->nfile.fd;
8426                 new->nfile.next = copynode(n->nfile.next);
8427                 break;
8428         case NTOFD:
8429         case NFROMFD:
8430                 new->ndup.vname = copynode(n->ndup.vname);
8431                 new->ndup.dupfd = n->ndup.dupfd;
8432                 new->ndup.fd = n->ndup.fd;
8433                 new->ndup.next = copynode(n->ndup.next);
8434                 break;
8435         case NHERE:
8436         case NXHERE:
8437                 new->nhere.doc = copynode(n->nhere.doc);
8438                 new->nhere.fd = n->nhere.fd;
8439                 new->nhere.next = copynode(n->nhere.next);
8440                 break;
8441         case NNOT:
8442                 new->nnot.com = copynode(n->nnot.com);
8443                 break;
8444         };
8445         new->type = n->type;
8446         return new;
8447 }
8448
8449 /*
8450  * Make a copy of a parse tree.
8451  */
8452 static struct funcnode *
8453 copyfunc(union node *n)
8454 {
8455         struct funcnode *f;
8456         size_t blocksize;
8457
8458         /*funcstringsize = 0;*/
8459         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8460         f = ckzalloc(blocksize /* + funcstringsize */);
8461         funcblock = (char *) f + offsetof(struct funcnode, n);
8462         funcstring_end = (char *) f + blocksize;
8463         copynode(n);
8464         /* f->count = 0; - ckzalloc did it */
8465         return f;
8466 }
8467
8468 /*
8469  * Define a shell function.
8470  */
8471 static void
8472 defun(union node *func)
8473 {
8474         struct cmdentry entry;
8475
8476         INT_OFF;
8477         entry.cmdtype = CMDFUNCTION;
8478         entry.u.func = copyfunc(func);
8479         addcmdentry(func->narg.text, &entry);
8480         INT_ON;
8481 }
8482
8483 /* Reasons for skipping commands (see comment on breakcmd routine) */
8484 #define SKIPBREAK      (1 << 0)
8485 #define SKIPCONT       (1 << 1)
8486 #define SKIPFUNC       (1 << 2)
8487 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8488 static int skipcount;           /* number of levels to skip */
8489 static int funcnest;            /* depth of function calls */
8490 static int loopnest;            /* current loop nesting level */
8491
8492 /* Forward decl way out to parsing code - dotrap needs it */
8493 static int evalstring(char *s, int flags);
8494
8495 /* Called to execute a trap.
8496  * Single callsite - at the end of evaltree().
8497  * If we return non-zero, evaltree raises EXEXIT exception.
8498  *
8499  * Perhaps we should avoid entering new trap handlers
8500  * while we are executing a trap handler. [is it a TODO?]
8501  */
8502 static void
8503 dotrap(void)
8504 {
8505         uint8_t *g;
8506         int sig;
8507         uint8_t last_status;
8508
8509         if (!pending_sig)
8510                 return;
8511
8512         last_status = exitstatus;
8513         pending_sig = 0;
8514         barrier();
8515
8516         TRACE(("dotrap entered\n"));
8517         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8518                 char *p;
8519
8520                 if (!*g)
8521                         continue;
8522
8523                 if (evalskip) {
8524                         pending_sig = sig;
8525                         break;
8526                 }
8527
8528                 p = trap[sig];
8529                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8530                  * don't upset it by resetting gotsig[SIGINT-1] */
8531                 if (sig == SIGINT && !p)
8532                         continue;
8533
8534                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8535                 *g = 0;
8536                 if (!p)
8537                         continue;
8538                 evalstring(p, 0);
8539         }
8540         exitstatus = last_status;
8541         TRACE(("dotrap returns\n"));
8542 }
8543
8544 /* forward declarations - evaluation is fairly recursive business... */
8545 static int evalloop(union node *, int);
8546 static int evalfor(union node *, int);
8547 static int evalcase(union node *, int);
8548 static int evalsubshell(union node *, int);
8549 static void expredir(union node *);
8550 static int evalpipe(union node *, int);
8551 static int evalcommand(union node *, int);
8552 static int evalbltin(const struct builtincmd *, int, char **, int);
8553 static void prehash(union node *);
8554
8555 /*
8556  * Evaluate a parse tree.  The value is left in the global variable
8557  * exitstatus.
8558  */
8559 static int
8560 evaltree(union node *n, int flags)
8561 {
8562         int checkexit = 0;
8563         int (*evalfn)(union node *, int);
8564         int status = 0;
8565
8566         if (n == NULL) {
8567                 TRACE(("evaltree(NULL) called\n"));
8568                 goto out;
8569         }
8570         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8571
8572         dotrap();
8573
8574         switch (n->type) {
8575         default:
8576 #if DEBUG
8577                 out1fmt("Node type = %d\n", n->type);
8578                 fflush_all();
8579                 break;
8580 #endif
8581         case NNOT:
8582                 status = !evaltree(n->nnot.com, EV_TESTED);
8583                 goto setstatus;
8584         case NREDIR:
8585                 expredir(n->nredir.redirect);
8586                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8587                 if (!status) {
8588                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8589                 }
8590                 if (n->nredir.redirect)
8591                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8592                 goto setstatus;
8593         case NCMD:
8594                 evalfn = evalcommand;
8595  checkexit:
8596                 if (eflag && !(flags & EV_TESTED))
8597                         checkexit = ~0;
8598                 goto calleval;
8599         case NFOR:
8600                 evalfn = evalfor;
8601                 goto calleval;
8602         case NWHILE:
8603         case NUNTIL:
8604                 evalfn = evalloop;
8605                 goto calleval;
8606         case NSUBSHELL:
8607         case NBACKGND:
8608                 evalfn = evalsubshell;
8609                 goto checkexit;
8610         case NPIPE:
8611                 evalfn = evalpipe;
8612                 goto checkexit;
8613         case NCASE:
8614                 evalfn = evalcase;
8615                 goto calleval;
8616         case NAND:
8617         case NOR:
8618         case NSEMI: {
8619
8620 #if NAND + 1 != NOR
8621 #error NAND + 1 != NOR
8622 #endif
8623 #if NOR + 1 != NSEMI
8624 #error NOR + 1 != NSEMI
8625 #endif
8626                 unsigned is_or = n->type - NAND;
8627                 status = evaltree(
8628                         n->nbinary.ch1,
8629                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8630                 );
8631                 if ((!status) == is_or || evalskip)
8632                         break;
8633                 n = n->nbinary.ch2;
8634  evaln:
8635                 evalfn = evaltree;
8636  calleval:
8637                 status = evalfn(n, flags);
8638                 goto setstatus;
8639         }
8640         case NIF:
8641                 status = evaltree(n->nif.test, EV_TESTED);
8642                 if (evalskip)
8643                         break;
8644                 if (!status) {
8645                         n = n->nif.ifpart;
8646                         goto evaln;
8647                 }
8648                 if (n->nif.elsepart) {
8649                         n = n->nif.elsepart;
8650                         goto evaln;
8651                 }
8652                 status = 0;
8653                 goto setstatus;
8654         case NDEFUN:
8655                 defun(n);
8656                 /* Not necessary. To test it:
8657                  * "false; f() { qwerty; }; echo $?" should print 0.
8658                  */
8659                 /* status = 0; */
8660  setstatus:
8661                 exitstatus = status;
8662                 break;
8663         }
8664  out:
8665         /* Order of checks below is important:
8666          * signal handlers trigger before exit caused by "set -e".
8667          */
8668         dotrap();
8669
8670         if (checkexit & status)
8671                 raise_exception(EXEXIT);
8672         if (flags & EV_EXIT)
8673                 raise_exception(EXEXIT);
8674
8675         TRACE(("leaving evaltree (no interrupts)\n"));
8676         return exitstatus;
8677 }
8678
8679 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8680 static
8681 #endif
8682 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8683
8684 static int
8685 skiploop(void)
8686 {
8687         int skip = evalskip;
8688
8689         switch (skip) {
8690         case 0:
8691                 break;
8692         case SKIPBREAK:
8693         case SKIPCONT:
8694                 if (--skipcount <= 0) {
8695                         evalskip = 0;
8696                         break;
8697                 }
8698                 skip = SKIPBREAK;
8699                 break;
8700         }
8701         return skip;
8702 }
8703
8704 static int
8705 evalloop(union node *n, int flags)
8706 {
8707         int skip;
8708         int status;
8709
8710         loopnest++;
8711         status = 0;
8712         flags &= EV_TESTED;
8713         do {
8714                 int i;
8715
8716                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8717                 skip = skiploop();
8718                 if (skip == SKIPFUNC)
8719                         status = i;
8720                 if (skip)
8721                         continue;
8722                 if (n->type != NWHILE)
8723                         i = !i;
8724                 if (i != 0)
8725                         break;
8726                 status = evaltree(n->nbinary.ch2, flags);
8727                 skip = skiploop();
8728         } while (!(skip & ~SKIPCONT));
8729         loopnest--;
8730
8731         return status;
8732 }
8733
8734 static int
8735 evalfor(union node *n, int flags)
8736 {
8737         struct arglist arglist;
8738         union node *argp;
8739         struct strlist *sp;
8740         struct stackmark smark;
8741         int status = 0;
8742
8743         setstackmark(&smark);
8744         arglist.list = NULL;
8745         arglist.lastp = &arglist.list;
8746         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8747                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8748         }
8749         *arglist.lastp = NULL;
8750
8751         loopnest++;
8752         flags &= EV_TESTED;
8753         for (sp = arglist.list; sp; sp = sp->next) {
8754                 setvar0(n->nfor.var, sp->text);
8755                 status = evaltree(n->nfor.body, flags);
8756                 if (skiploop() & ~SKIPCONT)
8757                         break;
8758         }
8759         loopnest--;
8760         popstackmark(&smark);
8761
8762         return status;
8763 }
8764
8765 static int
8766 evalcase(union node *n, int flags)
8767 {
8768         union node *cp;
8769         union node *patp;
8770         struct arglist arglist;
8771         struct stackmark smark;
8772         int status = 0;
8773
8774         setstackmark(&smark);
8775         arglist.list = NULL;
8776         arglist.lastp = &arglist.list;
8777         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8778         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8779                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8780                         if (casematch(patp, arglist.list->text)) {
8781                                 /* Ensure body is non-empty as otherwise
8782                                  * EV_EXIT may prevent us from setting the
8783                                  * exit status.
8784                                  */
8785                                 if (evalskip == 0 && cp->nclist.body) {
8786                                         status = evaltree(cp->nclist.body, flags);
8787                                 }
8788                                 goto out;
8789                         }
8790                 }
8791         }
8792  out:
8793         popstackmark(&smark);
8794
8795         return status;
8796 }
8797
8798 /*
8799  * Kick off a subshell to evaluate a tree.
8800  */
8801 static int
8802 evalsubshell(union node *n, int flags)
8803 {
8804         struct job *jp;
8805         int backgnd = (n->type == NBACKGND);
8806         int status;
8807
8808         expredir(n->nredir.redirect);
8809         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8810                 goto nofork;
8811         INT_OFF;
8812         jp = makejob(/*n,*/ 1);
8813         if (forkshell(jp, n, backgnd) == 0) {
8814                 /* child */
8815                 INT_ON;
8816                 flags |= EV_EXIT;
8817                 if (backgnd)
8818                         flags &= ~EV_TESTED;
8819  nofork:
8820                 redirect(n->nredir.redirect, 0);
8821                 evaltreenr(n->nredir.n, flags);
8822                 /* never returns */
8823         }
8824         /* parent */
8825         status = 0;
8826         if (!backgnd)
8827                 status = waitforjob(jp);
8828         INT_ON;
8829         return status;
8830 }
8831
8832 /*
8833  * Compute the names of the files in a redirection list.
8834  */
8835 static void fixredir(union node *, const char *, int);
8836 static void
8837 expredir(union node *n)
8838 {
8839         union node *redir;
8840
8841         for (redir = n; redir; redir = redir->nfile.next) {
8842                 struct arglist fn;
8843
8844                 fn.list = NULL;
8845                 fn.lastp = &fn.list;
8846                 switch (redir->type) {
8847                 case NFROMTO:
8848                 case NFROM:
8849                 case NTO:
8850 #if ENABLE_ASH_BASH_COMPAT
8851                 case NTO2:
8852 #endif
8853                 case NCLOBBER:
8854                 case NAPPEND:
8855                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8856                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
8857 #if ENABLE_ASH_BASH_COMPAT
8858  store_expfname:
8859 #endif
8860 #if 0
8861 // By the design of stack allocator, the loop of this kind:
8862 //      while true; do while true; do break; done </dev/null; done
8863 // will look like a memory leak: ash plans to free expfname's
8864 // of "/dev/null" as soon as it finishes running the loop
8865 // (in this case, never).
8866 // This "fix" is wrong:
8867                         if (redir->nfile.expfname)
8868                                 stunalloc(redir->nfile.expfname);
8869 // It results in corrupted state of stacked allocations.
8870 #endif
8871                         redir->nfile.expfname = fn.list->text;
8872                         break;
8873                 case NFROMFD:
8874                 case NTOFD: /* >& */
8875                         if (redir->ndup.vname) {
8876                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8877                                 if (fn.list == NULL)
8878                                         ash_msg_and_raise_error("redir error");
8879 #if ENABLE_ASH_BASH_COMPAT
8880 //FIXME: we used expandarg with different args!
8881                                 if (!isdigit_str9(fn.list->text)) {
8882                                         /* >&file, not >&fd */
8883                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
8884                                                 ash_msg_and_raise_error("redir error");
8885                                         redir->type = NTO2;
8886                                         goto store_expfname;
8887                                 }
8888 #endif
8889                                 fixredir(redir, fn.list->text, 1);
8890                         }
8891                         break;
8892                 }
8893         }
8894 }
8895
8896 /*
8897  * Evaluate a pipeline.  All the processes in the pipeline are children
8898  * of the process creating the pipeline.  (This differs from some versions
8899  * of the shell, which make the last process in a pipeline the parent
8900  * of all the rest.)
8901  */
8902 static int
8903 evalpipe(union node *n, int flags)
8904 {
8905         struct job *jp;
8906         struct nodelist *lp;
8907         int pipelen;
8908         int prevfd;
8909         int pip[2];
8910         int status = 0;
8911
8912         TRACE(("evalpipe(0x%lx) called\n", (long)n));
8913         pipelen = 0;
8914         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8915                 pipelen++;
8916         flags |= EV_EXIT;
8917         INT_OFF;
8918         jp = makejob(/*n,*/ pipelen);
8919         prevfd = -1;
8920         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8921                 prehash(lp->n);
8922                 pip[1] = -1;
8923                 if (lp->next) {
8924                         if (pipe(pip) < 0) {
8925                                 close(prevfd);
8926                                 ash_msg_and_raise_error("pipe call failed");
8927                         }
8928                 }
8929                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8930                         /* child */
8931                         INT_ON;
8932                         if (pip[1] >= 0) {
8933                                 close(pip[0]);
8934                         }
8935                         if (prevfd > 0) {
8936                                 dup2(prevfd, 0);
8937                                 close(prevfd);
8938                         }
8939                         if (pip[1] > 1) {
8940                                 dup2(pip[1], 1);
8941                                 close(pip[1]);
8942                         }
8943                         evaltreenr(lp->n, flags);
8944                         /* never returns */
8945                 }
8946                 /* parent */
8947                 if (prevfd >= 0)
8948                         close(prevfd);
8949                 prevfd = pip[0];
8950                 /* Don't want to trigger debugging */
8951                 if (pip[1] != -1)
8952                         close(pip[1]);
8953         }
8954         if (n->npipe.pipe_backgnd == 0) {
8955                 status = waitforjob(jp);
8956                 TRACE(("evalpipe:  job done exit status %d\n", status));
8957         }
8958         INT_ON;
8959
8960         return status;
8961 }
8962
8963 /*
8964  * Controls whether the shell is interactive or not.
8965  */
8966 static void
8967 setinteractive(int on)
8968 {
8969         static smallint is_interactive;
8970
8971         if (++on == is_interactive)
8972                 return;
8973         is_interactive = on;
8974         setsignal(SIGINT);
8975         setsignal(SIGQUIT);
8976         setsignal(SIGTERM);
8977 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8978         if (is_interactive > 1) {
8979                 /* Looks like they want an interactive shell */
8980                 static smallint did_banner;
8981
8982                 if (!did_banner) {
8983                         /* note: ash and hush share this string */
8984                         out1fmt("\n\n%s %s\n"
8985                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
8986                                 "\n",
8987                                 bb_banner,
8988                                 "built-in shell (ash)"
8989                         );
8990                         did_banner = 1;
8991                 }
8992         }
8993 #endif
8994 }
8995
8996 static void
8997 optschanged(void)
8998 {
8999 #if DEBUG
9000         opentrace();
9001 #endif
9002         setinteractive(iflag);
9003         setjobctl(mflag);
9004 #if ENABLE_FEATURE_EDITING_VI
9005         if (viflag)
9006                 line_input_state->flags |= VI_MODE;
9007         else
9008                 line_input_state->flags &= ~VI_MODE;
9009 #else
9010         viflag = 0; /* forcibly keep the option off */
9011 #endif
9012 }
9013
9014 static struct localvar *localvars;
9015
9016 /*
9017  * Called after a function returns.
9018  * Interrupts must be off.
9019  */
9020 static void
9021 poplocalvars(void)
9022 {
9023         struct localvar *lvp;
9024         struct var *vp;
9025
9026         while ((lvp = localvars) != NULL) {
9027                 localvars = lvp->next;
9028                 vp = lvp->vp;
9029                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9030                 if (vp == NULL) {       /* $- saved */
9031                         memcpy(optlist, lvp->text, sizeof(optlist));
9032                         free((char*)lvp->text);
9033                         optschanged();
9034                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9035                         unsetvar(vp->var_text);
9036                 } else {
9037                         if (vp->var_func)
9038                                 vp->var_func(var_end(lvp->text));
9039                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9040                                 free((char*)vp->var_text);
9041                         vp->flags = lvp->flags;
9042                         vp->var_text = lvp->text;
9043                 }
9044                 free(lvp);
9045         }
9046 }
9047
9048 static int
9049 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9050 {
9051         volatile struct shparam saveparam;
9052         struct localvar *volatile savelocalvars;
9053         struct jmploc *volatile savehandler;
9054         struct jmploc jmploc;
9055         int e;
9056
9057         saveparam = shellparam;
9058         savelocalvars = localvars;
9059         savehandler = exception_handler;
9060         e = setjmp(jmploc.loc);
9061         if (e) {
9062                 goto funcdone;
9063         }
9064         INT_OFF;
9065         exception_handler = &jmploc;
9066         localvars = NULL;
9067         shellparam.malloced = 0;
9068         func->count++;
9069         funcnest++;
9070         INT_ON;
9071         shellparam.nparam = argc - 1;
9072         shellparam.p = argv + 1;
9073 #if ENABLE_ASH_GETOPTS
9074         shellparam.optind = 1;
9075         shellparam.optoff = -1;
9076 #endif
9077         evaltree(func->n.narg.next, flags & EV_TESTED);
9078  funcdone:
9079         INT_OFF;
9080         funcnest--;
9081         freefunc(func);
9082         poplocalvars();
9083         localvars = savelocalvars;
9084         freeparam(&shellparam);
9085         shellparam = saveparam;
9086         exception_handler = savehandler;
9087         INT_ON;
9088         evalskip &= ~SKIPFUNC;
9089         return e;
9090 }
9091
9092 /*
9093  * Make a variable a local variable.  When a variable is made local, it's
9094  * value and flags are saved in a localvar structure.  The saved values
9095  * will be restored when the shell function returns.  We handle the name
9096  * "-" as a special case: it makes changes to "set +-options" local
9097  * (options will be restored on return from the function).
9098  */
9099 static void
9100 mklocal(char *name)
9101 {
9102         struct localvar *lvp;
9103         struct var **vpp;
9104         struct var *vp;
9105         char *eq = strchr(name, '=');
9106
9107         INT_OFF;
9108         /* Cater for duplicate "local". Examples:
9109          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9110          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9111          */
9112         lvp = localvars;
9113         while (lvp) {
9114                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9115                         if (eq)
9116                                 setvareq(name, 0);
9117                         /* else:
9118                          * it's a duplicate "local VAR" declaration, do nothing
9119                          */
9120                         goto ret;
9121                 }
9122                 lvp = lvp->next;
9123         }
9124
9125         lvp = ckzalloc(sizeof(*lvp));
9126         if (LONE_DASH(name)) {
9127                 char *p;
9128                 p = ckmalloc(sizeof(optlist));
9129                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9130                 vp = NULL;
9131         } else {
9132                 vpp = hashvar(name);
9133                 vp = *findvar(vpp, name);
9134                 if (vp == NULL) {
9135                         /* variable did not exist yet */
9136                         if (eq)
9137                                 setvareq(name, VSTRFIXED);
9138                         else
9139                                 setvar(name, NULL, VSTRFIXED);
9140                         vp = *vpp;      /* the new variable */
9141                         lvp->flags = VUNSET;
9142                 } else {
9143                         lvp->text = vp->var_text;
9144                         lvp->flags = vp->flags;
9145                         /* make sure neither "struct var" nor string gets freed
9146                          * during (un)setting:
9147                          */
9148                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9149                         if (eq)
9150                                 setvareq(name, 0);
9151                         else
9152                                 /* "local VAR" unsets VAR: */
9153                                 setvar0(name, NULL);
9154                 }
9155         }
9156         lvp->vp = vp;
9157         lvp->next = localvars;
9158         localvars = lvp;
9159  ret:
9160         INT_ON;
9161 }
9162
9163 /*
9164  * The "local" command.
9165  */
9166 static int FAST_FUNC
9167 localcmd(int argc UNUSED_PARAM, char **argv)
9168 {
9169         char *name;
9170
9171         if (!funcnest)
9172                 ash_msg_and_raise_error("not in a function");
9173
9174         argv = argptr;
9175         while ((name = *argv++) != NULL) {
9176                 mklocal(name);
9177         }
9178         return 0;
9179 }
9180
9181 static int FAST_FUNC
9182 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9183 {
9184         return 1;
9185 }
9186
9187 static int FAST_FUNC
9188 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9189 {
9190         return 0;
9191 }
9192
9193 static int FAST_FUNC
9194 execcmd(int argc UNUSED_PARAM, char **argv)
9195 {
9196         if (argv[1]) {
9197                 iflag = 0;              /* exit on error */
9198                 mflag = 0;
9199                 optschanged();
9200                 /* We should set up signals for "exec CMD"
9201                  * the same way as for "CMD" without "exec".
9202                  * But optschanged->setinteractive->setsignal
9203                  * still thought we are a root shell. Therefore, for example,
9204                  * SIGQUIT is still set to IGN. Fix it:
9205                  */
9206                 shlvl++;
9207                 setsignal(SIGQUIT);
9208                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9209                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9210                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9211
9212                 shellexec(argv + 1, pathval(), 0);
9213                 /* NOTREACHED */
9214         }
9215         return 0;
9216 }
9217
9218 /*
9219  * The return command.
9220  */
9221 static int FAST_FUNC
9222 returncmd(int argc UNUSED_PARAM, char **argv)
9223 {
9224         /*
9225          * If called outside a function, do what ksh does;
9226          * skip the rest of the file.
9227          */
9228         evalskip = SKIPFUNC;
9229         return argv[1] ? number(argv[1]) : exitstatus;
9230 }
9231
9232 /* Forward declarations for builtintab[] */
9233 static int breakcmd(int, char **) FAST_FUNC;
9234 static int dotcmd(int, char **) FAST_FUNC;
9235 static int evalcmd(int, char **, int) FAST_FUNC;
9236 static int exitcmd(int, char **) FAST_FUNC;
9237 static int exportcmd(int, char **) FAST_FUNC;
9238 #if ENABLE_ASH_GETOPTS
9239 static int getoptscmd(int, char **) FAST_FUNC;
9240 #endif
9241 #if ENABLE_ASH_HELP
9242 static int helpcmd(int, char **) FAST_FUNC;
9243 #endif
9244 #if MAX_HISTORY
9245 static int historycmd(int, char **) FAST_FUNC;
9246 #endif
9247 #if ENABLE_SH_MATH_SUPPORT
9248 static int letcmd(int, char **) FAST_FUNC;
9249 #endif
9250 static int readcmd(int, char **) FAST_FUNC;
9251 static int setcmd(int, char **) FAST_FUNC;
9252 static int shiftcmd(int, char **) FAST_FUNC;
9253 static int timescmd(int, char **) FAST_FUNC;
9254 static int trapcmd(int, char **) FAST_FUNC;
9255 static int umaskcmd(int, char **) FAST_FUNC;
9256 static int unsetcmd(int, char **) FAST_FUNC;
9257 static int ulimitcmd(int, char **) FAST_FUNC;
9258
9259 #define BUILTIN_NOSPEC          "0"
9260 #define BUILTIN_SPECIAL         "1"
9261 #define BUILTIN_REGULAR         "2"
9262 #define BUILTIN_SPEC_REG        "3"
9263 #define BUILTIN_ASSIGN          "4"
9264 #define BUILTIN_SPEC_ASSG       "5"
9265 #define BUILTIN_REG_ASSG        "6"
9266 #define BUILTIN_SPEC_REG_ASSG   "7"
9267
9268 /* Stubs for calling non-FAST_FUNC's */
9269 #if ENABLE_ASH_BUILTIN_ECHO
9270 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9271 #endif
9272 #if ENABLE_ASH_BUILTIN_PRINTF
9273 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9274 #endif
9275 #if ENABLE_ASH_BUILTIN_TEST
9276 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9277 #endif
9278
9279 /* Keep these in proper order since it is searched via bsearch() */
9280 static const struct builtincmd builtintab[] = {
9281         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9282         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9283 #if ENABLE_ASH_BUILTIN_TEST
9284         { BUILTIN_REGULAR       "["       , testcmd    },
9285 # if ENABLE_ASH_BASH_COMPAT
9286         { BUILTIN_REGULAR       "[["      , testcmd    },
9287 # endif
9288 #endif
9289 #if ENABLE_ASH_ALIAS
9290         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9291 #endif
9292 #if JOBS
9293         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9294 #endif
9295         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9296         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9297         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9298 #if ENABLE_ASH_CMDCMD
9299         { BUILTIN_REGULAR       "command" , commandcmd },
9300 #endif
9301         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9302 #if ENABLE_ASH_BUILTIN_ECHO
9303         { BUILTIN_REGULAR       "echo"    , echocmd    },
9304 #endif
9305         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9306         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9307         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9308         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9309         { BUILTIN_REGULAR       "false"   , falsecmd   },
9310 #if JOBS
9311         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9312 #endif
9313 #if ENABLE_ASH_GETOPTS
9314         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9315 #endif
9316         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9317 #if ENABLE_ASH_HELP
9318         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9319 #endif
9320 #if MAX_HISTORY
9321         { BUILTIN_NOSPEC        "history" , historycmd },
9322 #endif
9323 #if JOBS
9324         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9325         { BUILTIN_REGULAR       "kill"    , killcmd    },
9326 #endif
9327 #if ENABLE_SH_MATH_SUPPORT
9328         { BUILTIN_NOSPEC        "let"     , letcmd     },
9329 #endif
9330         { BUILTIN_ASSIGN        "local"   , localcmd   },
9331 #if ENABLE_ASH_BUILTIN_PRINTF
9332         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9333 #endif
9334         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9335         { BUILTIN_REGULAR       "read"    , readcmd    },
9336         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9337         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9338         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9339         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9340 #if ENABLE_ASH_BASH_COMPAT
9341         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9342 #endif
9343 #if ENABLE_ASH_BUILTIN_TEST
9344         { BUILTIN_REGULAR       "test"    , testcmd    },
9345 #endif
9346         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9347         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9348         { BUILTIN_REGULAR       "true"    , truecmd    },
9349         { BUILTIN_NOSPEC        "type"    , typecmd    },
9350         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9351         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9352 #if ENABLE_ASH_ALIAS
9353         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9354 #endif
9355         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9356         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9357 };
9358
9359 /* Should match the above table! */
9360 #define COMMANDCMD (builtintab + \
9361         /* . : */       2 + \
9362         /* [ */         1 * ENABLE_ASH_BUILTIN_TEST + \
9363         /* [[ */        1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
9364         /* alias */     1 * ENABLE_ASH_ALIAS + \
9365         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9366         /* break cd cddir  */   3)
9367 #define EVALCMD (COMMANDCMD + \
9368         /* command */   1 * ENABLE_ASH_CMDCMD + \
9369         /* continue */  1 + \
9370         /* echo */      1 * ENABLE_ASH_BUILTIN_ECHO + \
9371         0)
9372 #define EXECCMD (EVALCMD + \
9373         /* eval */      1)
9374
9375 /*
9376  * Search the table of builtin commands.
9377  */
9378 static int
9379 pstrcmp1(const void *a, const void *b)
9380 {
9381         return strcmp((char*)a, *(char**)b + 1);
9382 }
9383 static struct builtincmd *
9384 find_builtin(const char *name)
9385 {
9386         struct builtincmd *bp;
9387
9388         bp = bsearch(
9389                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9390                 pstrcmp1
9391         );
9392         return bp;
9393 }
9394
9395 /*
9396  * Execute a simple command.
9397  */
9398 static int
9399 isassignment(const char *p)
9400 {
9401         const char *q = endofname(p);
9402         if (p == q)
9403                 return 0;
9404         return *q == '=';
9405 }
9406 static int FAST_FUNC
9407 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9408 {
9409         /* Preserve exitstatus of a previous possible redirection
9410          * as POSIX mandates */
9411         return back_exitstatus;
9412 }
9413 static int
9414 evalcommand(union node *cmd, int flags)
9415 {
9416         static const struct builtincmd null_bltin = {
9417                 "\0\0", bltincmd /* why three NULs? */
9418         };
9419         struct stackmark smark;
9420         union node *argp;
9421         struct arglist arglist;
9422         struct arglist varlist;
9423         char **argv;
9424         int argc;
9425         const struct strlist *sp;
9426         struct cmdentry cmdentry;
9427         struct job *jp;
9428         char *lastarg;
9429         const char *path;
9430         int spclbltin;
9431         int status;
9432         char **nargv;
9433         struct builtincmd *bcmd;
9434         smallint cmd_is_exec;
9435         smallint pseudovarflag = 0;
9436
9437         /* First expand the arguments. */
9438         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9439         setstackmark(&smark);
9440         back_exitstatus = 0;
9441
9442         cmdentry.cmdtype = CMDBUILTIN;
9443         cmdentry.u.cmd = &null_bltin;
9444         varlist.lastp = &varlist.list;
9445         *varlist.lastp = NULL;
9446         arglist.lastp = &arglist.list;
9447         *arglist.lastp = NULL;
9448
9449         argc = 0;
9450         if (cmd->ncmd.args) {
9451                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9452                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9453         }
9454
9455         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9456                 struct strlist **spp;
9457
9458                 spp = arglist.lastp;
9459                 if (pseudovarflag && isassignment(argp->narg.text))
9460                         expandarg(argp, &arglist, EXP_VARTILDE);
9461                 else
9462                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9463
9464                 for (sp = *spp; sp; sp = sp->next)
9465                         argc++;
9466         }
9467
9468         /* Reserve one extra spot at the front for shellexec. */
9469         nargv = stalloc(sizeof(char *) * (argc + 2));
9470         argv = ++nargv;
9471         for (sp = arglist.list; sp; sp = sp->next) {
9472                 TRACE(("evalcommand arg: %s\n", sp->text));
9473                 *nargv++ = sp->text;
9474         }
9475         *nargv = NULL;
9476
9477         lastarg = NULL;
9478         if (iflag && funcnest == 0 && argc > 0)
9479                 lastarg = nargv[-1];
9480
9481         preverrout_fd = 2;
9482         expredir(cmd->ncmd.redirect);
9483         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9484
9485         path = vpath.var_text;
9486         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9487                 struct strlist **spp;
9488                 char *p;
9489
9490                 spp = varlist.lastp;
9491                 expandarg(argp, &varlist, EXP_VARTILDE);
9492
9493                 /*
9494                  * Modify the command lookup path, if a PATH= assignment
9495                  * is present
9496                  */
9497                 p = (*spp)->text;
9498                 if (varcmp(p, path) == 0)
9499                         path = p;
9500         }
9501
9502         /* Print the command if xflag is set. */
9503         if (xflag) {
9504                 int n;
9505                 const char *p = " %s" + 1;
9506
9507                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9508                 sp = varlist.list;
9509                 for (n = 0; n < 2; n++) {
9510                         while (sp) {
9511                                 fdprintf(preverrout_fd, p, sp->text);
9512                                 sp = sp->next;
9513                                 p = " %s";
9514                         }
9515                         sp = arglist.list;
9516                 }
9517                 safe_write(preverrout_fd, "\n", 1);
9518         }
9519
9520         cmd_is_exec = 0;
9521         spclbltin = -1;
9522
9523         /* Now locate the command. */
9524         if (argc) {
9525                 int cmd_flag = DO_ERR;
9526 #if ENABLE_ASH_CMDCMD
9527                 const char *oldpath = path + 5;
9528 #endif
9529                 path += 5;
9530                 for (;;) {
9531                         find_command(argv[0], &cmdentry, cmd_flag, path);
9532                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9533                                 flush_stdout_stderr();
9534                                 status = 127;
9535                                 goto bail;
9536                         }
9537
9538                         /* implement bltin and command here */
9539                         if (cmdentry.cmdtype != CMDBUILTIN)
9540                                 break;
9541                         if (spclbltin < 0)
9542                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9543                         if (cmdentry.u.cmd == EXECCMD)
9544                                 cmd_is_exec = 1;
9545 #if ENABLE_ASH_CMDCMD
9546                         if (cmdentry.u.cmd == COMMANDCMD) {
9547                                 path = oldpath;
9548                                 nargv = parse_command_args(argv, &path);
9549                                 if (!nargv)
9550                                         break;
9551                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9552                                  * nargv => "PROG". path is updated if -p.
9553                                  */
9554                                 argc -= nargv - argv;
9555                                 argv = nargv;
9556                                 cmd_flag |= DO_NOFUNC;
9557                         } else
9558 #endif
9559                                 break;
9560                 }
9561         }
9562
9563         if (status) {
9564                 /* We have a redirection error. */
9565                 if (spclbltin > 0)
9566                         raise_exception(EXERROR);
9567  bail:
9568                 exitstatus = status;
9569                 goto out;
9570         }
9571
9572         /* Execute the command. */
9573         switch (cmdentry.cmdtype) {
9574         default: {
9575
9576 #if ENABLE_FEATURE_SH_NOFORK
9577 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9578  *     around run_nofork_applet() call.
9579  * (2) Should this check also be done in forkshell()?
9580  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9581  */
9582                 /* find_command() encodes applet_no as (-2 - applet_no) */
9583                 int applet_no = (- cmdentry.u.index - 2);
9584                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9585                         listsetvar(varlist.list, VEXPORT|VSTACK);
9586                         /* run <applet>_main() */
9587                         status = run_nofork_applet(applet_no, argv);
9588                         break;
9589                 }
9590 #endif
9591                 /* Can we avoid forking off? For example, very last command
9592                  * in a script or a subshell does not need forking,
9593                  * we can just exec it.
9594                  */
9595                 if (!(flags & EV_EXIT) || may_have_traps) {
9596                         /* No, forking off a child is necessary */
9597                         INT_OFF;
9598                         jp = makejob(/*cmd,*/ 1);
9599                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9600                                 /* parent */
9601                                 status = waitforjob(jp);
9602                                 INT_ON;
9603                                 TRACE(("forked child exited with %d\n", status));
9604                                 break;
9605                         }
9606                         /* child */
9607                         FORCE_INT_ON;
9608                         /* fall through to exec'ing external program */
9609                 }
9610                 listsetvar(varlist.list, VEXPORT|VSTACK);
9611                 shellexec(argv, path, cmdentry.u.index);
9612                 /* NOTREACHED */
9613         } /* default */
9614         case CMDBUILTIN:
9615                 cmdenviron = varlist.list;
9616                 if (cmdenviron) {
9617                         struct strlist *list = cmdenviron;
9618                         int i = VNOSET;
9619                         if (spclbltin > 0 || argc == 0) {
9620                                 i = 0;
9621                                 if (cmd_is_exec && argc > 1)
9622                                         i = VEXPORT;
9623                         }
9624                         listsetvar(list, i);
9625                 }
9626                 /* Tight loop with builtins only:
9627                  * "while kill -0 $child; do true; done"
9628                  * will never exit even if $child died, unless we do this
9629                  * to reap the zombie and make kill detect that it's gone: */
9630                 dowait(DOWAIT_NONBLOCK, NULL);
9631
9632                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9633                         if (exception_type == EXERROR && spclbltin <= 0) {
9634                                 FORCE_INT_ON;
9635                                 goto readstatus;
9636                         }
9637  raise:
9638                         longjmp(exception_handler->loc, 1);
9639                 }
9640                 goto readstatus;
9641
9642         case CMDFUNCTION:
9643                 listsetvar(varlist.list, 0);
9644                 /* See above for the rationale */
9645                 dowait(DOWAIT_NONBLOCK, NULL);
9646                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9647                         goto raise;
9648  readstatus:
9649                 status = exitstatus;
9650                 break;
9651         } /* switch */
9652
9653  out:
9654         if (cmd->ncmd.redirect)
9655                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9656         if (lastarg) {
9657                 /* dsl: I think this is intended to be used to support
9658                  * '_' in 'vi' command mode during line editing...
9659                  * However I implemented that within libedit itself.
9660                  */
9661                 setvar0("_", lastarg);
9662         }
9663         popstackmark(&smark);
9664
9665         return status;
9666 }
9667
9668 static int
9669 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9670 {
9671         char *volatile savecmdname;
9672         struct jmploc *volatile savehandler;
9673         struct jmploc jmploc;
9674         int status;
9675         int i;
9676
9677         savecmdname = commandname;
9678         savehandler = exception_handler;
9679         i = setjmp(jmploc.loc);
9680         if (i)
9681                 goto cmddone;
9682         exception_handler = &jmploc;
9683         commandname = argv[0];
9684         argptr = argv + 1;
9685         optptr = NULL;                  /* initialize nextopt */
9686         if (cmd == EVALCMD)
9687                 status = evalcmd(argc, argv, flags);
9688         else
9689                 status = (*cmd->builtin)(argc, argv);
9690         flush_stdout_stderr();
9691         status |= ferror(stdout);
9692         exitstatus = status;
9693  cmddone:
9694         clearerr(stdout);
9695         commandname = savecmdname;
9696         exception_handler = savehandler;
9697
9698         return i;
9699 }
9700
9701 static int
9702 goodname(const char *p)
9703 {
9704         return endofname(p)[0] == '\0';
9705 }
9706
9707
9708 /*
9709  * Search for a command.  This is called before we fork so that the
9710  * location of the command will be available in the parent as well as
9711  * the child.  The check for "goodname" is an overly conservative
9712  * check that the name will not be subject to expansion.
9713  */
9714 static void
9715 prehash(union node *n)
9716 {
9717         struct cmdentry entry;
9718
9719         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9720                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9721 }
9722
9723
9724 /* ============ Builtin commands
9725  *
9726  * Builtin commands whose functions are closely tied to evaluation
9727  * are implemented here.
9728  */
9729
9730 /*
9731  * Handle break and continue commands.  Break, continue, and return are
9732  * all handled by setting the evalskip flag.  The evaluation routines
9733  * above all check this flag, and if it is set they start skipping
9734  * commands rather than executing them.  The variable skipcount is
9735  * the number of loops to break/continue, or the number of function
9736  * levels to return.  (The latter is always 1.)  It should probably
9737  * be an error to break out of more loops than exist, but it isn't
9738  * in the standard shell so we don't make it one here.
9739  */
9740 static int FAST_FUNC
9741 breakcmd(int argc UNUSED_PARAM, char **argv)
9742 {
9743         int n = argv[1] ? number(argv[1]) : 1;
9744
9745         if (n <= 0)
9746                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9747         if (n > loopnest)
9748                 n = loopnest;
9749         if (n > 0) {
9750                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9751                 skipcount = n;
9752         }
9753         return 0;
9754 }
9755
9756
9757 /*
9758  * This implements the input routines used by the parser.
9759  */
9760
9761 enum {
9762         INPUT_PUSH_FILE = 1,
9763         INPUT_NOFILE_OK = 2,
9764 };
9765
9766 static smallint checkkwd;
9767 /* values of checkkwd variable */
9768 #define CHKALIAS        0x1
9769 #define CHKKWD          0x2
9770 #define CHKNL           0x4
9771
9772 /*
9773  * Push a string back onto the input at this current parsefile level.
9774  * We handle aliases this way.
9775  */
9776 #if !ENABLE_ASH_ALIAS
9777 #define pushstring(s, ap) pushstring(s)
9778 #endif
9779 static void
9780 pushstring(char *s, struct alias *ap)
9781 {
9782         struct strpush *sp;
9783         int len;
9784
9785         len = strlen(s);
9786         INT_OFF;
9787         if (g_parsefile->strpush) {
9788                 sp = ckzalloc(sizeof(*sp));
9789                 sp->prev = g_parsefile->strpush;
9790         } else {
9791                 sp = &(g_parsefile->basestrpush);
9792         }
9793         g_parsefile->strpush = sp;
9794         sp->prev_string = g_parsefile->next_to_pgetc;
9795         sp->prev_left_in_line = g_parsefile->left_in_line;
9796         sp->unget = g_parsefile->unget;
9797         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9798 #if ENABLE_ASH_ALIAS
9799         sp->ap = ap;
9800         if (ap) {
9801                 ap->flag |= ALIASINUSE;
9802                 sp->string = s;
9803         }
9804 #endif
9805         g_parsefile->next_to_pgetc = s;
9806         g_parsefile->left_in_line = len;
9807         g_parsefile->unget = 0;
9808         INT_ON;
9809 }
9810
9811 static void
9812 popstring(void)
9813 {
9814         struct strpush *sp = g_parsefile->strpush;
9815
9816         INT_OFF;
9817 #if ENABLE_ASH_ALIAS
9818         if (sp->ap) {
9819                 if (g_parsefile->next_to_pgetc[-1] == ' '
9820                  || g_parsefile->next_to_pgetc[-1] == '\t'
9821                 ) {
9822                         checkkwd |= CHKALIAS;
9823                 }
9824                 if (sp->string != sp->ap->val) {
9825                         free(sp->string);
9826                 }
9827                 sp->ap->flag &= ~ALIASINUSE;
9828                 if (sp->ap->flag & ALIASDEAD) {
9829                         unalias(sp->ap->name);
9830                 }
9831         }
9832 #endif
9833         g_parsefile->next_to_pgetc = sp->prev_string;
9834         g_parsefile->left_in_line = sp->prev_left_in_line;
9835         g_parsefile->unget = sp->unget;
9836         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
9837         g_parsefile->strpush = sp->prev;
9838         if (sp != &(g_parsefile->basestrpush))
9839                 free(sp);
9840         INT_ON;
9841 }
9842
9843 static int
9844 preadfd(void)
9845 {
9846         int nr;
9847         char *buf = g_parsefile->buf;
9848
9849         g_parsefile->next_to_pgetc = buf;
9850 #if ENABLE_FEATURE_EDITING
9851  retry:
9852         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
9853                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9854         else {
9855                 int timeout = -1;
9856 # if ENABLE_ASH_IDLE_TIMEOUT
9857                 if (iflag) {
9858                         const char *tmout_var = lookupvar("TMOUT");
9859                         if (tmout_var) {
9860                                 timeout = atoi(tmout_var) * 1000;
9861                                 if (timeout <= 0)
9862                                         timeout = -1;
9863                         }
9864                 }
9865 # endif
9866 # if ENABLE_FEATURE_TAB_COMPLETION
9867                 line_input_state->path_lookup = pathval();
9868 # endif
9869                 reinit_unicode_for_ash();
9870                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
9871                 if (nr == 0) {
9872                         /* ^C pressed, "convert" to SIGINT */
9873                         write(STDOUT_FILENO, "^C", 2);
9874                         if (trap[SIGINT]) {
9875                                 buf[0] = '\n';
9876                                 buf[1] = '\0';
9877                                 raise(SIGINT);
9878                                 return 1;
9879                         }
9880                         exitstatus = 128 + SIGINT;
9881                         bb_putchar('\n');
9882                         goto retry;
9883                 }
9884                 if (nr < 0) {
9885                         if (errno == 0) {
9886                                 /* Ctrl+D pressed */
9887                                 nr = 0;
9888                         }
9889 # if ENABLE_ASH_IDLE_TIMEOUT
9890                         else if (errno == EAGAIN && timeout > 0) {
9891                                 puts("\007timed out waiting for input: auto-logout");
9892                                 exitshell();
9893                         }
9894 # endif
9895                 }
9896         }
9897 #else
9898         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9899 #endif
9900
9901 #if 0 /* disabled: nonblock_immune_read() handles this problem */
9902         if (nr < 0) {
9903                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9904                         int flags = fcntl(0, F_GETFL);
9905                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9906                                 flags &= ~O_NONBLOCK;
9907                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9908                                         out2str("sh: turning off NDELAY mode\n");
9909                                         goto retry;
9910                                 }
9911                         }
9912                 }
9913         }
9914 #endif
9915         return nr;
9916 }
9917
9918 /*
9919  * Refill the input buffer and return the next input character:
9920  *
9921  * 1) If a string was pushed back on the input, pop it;
9922  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9923  *    or we are reading from a string so we can't refill the buffer,
9924  *    return EOF.
9925  * 3) If there is more stuff in this buffer, use it else call read to fill it.
9926  * 4) Process input up to the next newline, deleting nul characters.
9927  */
9928 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9929 #define pgetc_debug(...) ((void)0)
9930 static int pgetc(void);
9931 static int
9932 preadbuffer(void)
9933 {
9934         char *q;
9935         int more;
9936
9937         if (g_parsefile->strpush) {
9938 #if ENABLE_ASH_ALIAS
9939                 if (g_parsefile->left_in_line == -1
9940                  && g_parsefile->strpush->ap
9941                  && g_parsefile->next_to_pgetc[-1] != ' '
9942                  && g_parsefile->next_to_pgetc[-1] != '\t'
9943                 ) {
9944                         pgetc_debug("preadbuffer PEOA");
9945                         return PEOA;
9946                 }
9947 #endif
9948                 popstring();
9949                 return pgetc();
9950         }
9951         /* on both branches above g_parsefile->left_in_line < 0.
9952          * "pgetc" needs refilling.
9953          */
9954
9955         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9956          * pungetc() may increment it a few times.
9957          * Assuming it won't increment it to less than -90.
9958          */
9959         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9960                 pgetc_debug("preadbuffer PEOF1");
9961                 /* even in failure keep left_in_line and next_to_pgetc
9962                  * in lock step, for correct multi-layer pungetc.
9963                  * left_in_line was decremented before preadbuffer(),
9964                  * must inc next_to_pgetc: */
9965                 g_parsefile->next_to_pgetc++;
9966                 return PEOF;
9967         }
9968
9969         more = g_parsefile->left_in_buffer;
9970         if (more <= 0) {
9971                 flush_stdout_stderr();
9972  again:
9973                 more = preadfd();
9974                 if (more <= 0) {
9975                         /* don't try reading again */
9976                         g_parsefile->left_in_line = -99;
9977                         pgetc_debug("preadbuffer PEOF2");
9978                         g_parsefile->next_to_pgetc++;
9979                         return PEOF;
9980                 }
9981         }
9982
9983         /* Find out where's the end of line.
9984          * Set g_parsefile->left_in_line
9985          * and g_parsefile->left_in_buffer acordingly.
9986          * NUL chars are deleted.
9987          */
9988         q = g_parsefile->next_to_pgetc;
9989         for (;;) {
9990                 char c;
9991
9992                 more--;
9993
9994                 c = *q;
9995                 if (c == '\0') {
9996                         memmove(q, q + 1, more);
9997                 } else {
9998                         q++;
9999                         if (c == '\n') {
10000                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10001                                 break;
10002                         }
10003                 }
10004
10005                 if (more <= 0) {
10006                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10007                         if (g_parsefile->left_in_line < 0)
10008                                 goto again;
10009                         break;
10010                 }
10011         }
10012         g_parsefile->left_in_buffer = more;
10013
10014         if (vflag) {
10015                 char save = *q;
10016                 *q = '\0';
10017                 out2str(g_parsefile->next_to_pgetc);
10018                 *q = save;
10019         }
10020
10021         pgetc_debug("preadbuffer at %d:%p'%s'",
10022                         g_parsefile->left_in_line,
10023                         g_parsefile->next_to_pgetc,
10024                         g_parsefile->next_to_pgetc);
10025         return (unsigned char)*g_parsefile->next_to_pgetc++;
10026 }
10027
10028 static void
10029 nlprompt(void)
10030 {
10031         g_parsefile->linno++;
10032         setprompt_if(doprompt, 2);
10033 }
10034 static void
10035 nlnoprompt(void)
10036 {
10037         g_parsefile->linno++;
10038         needprompt = doprompt;
10039 }
10040
10041 static int
10042 pgetc(void)
10043 {
10044         int c;
10045
10046         pgetc_debug("pgetc at %d:%p'%s'",
10047                         g_parsefile->left_in_line,
10048                         g_parsefile->next_to_pgetc,
10049                         g_parsefile->next_to_pgetc);
10050         if (g_parsefile->unget)
10051                 return g_parsefile->lastc[--g_parsefile->unget];
10052
10053         if (--g_parsefile->left_in_line >= 0)
10054                 c = (signed char)*g_parsefile->next_to_pgetc++;
10055         else
10056                 c = preadbuffer();
10057
10058         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10059         g_parsefile->lastc[0] = c;
10060
10061         return c;
10062 }
10063
10064 #if ENABLE_ASH_ALIAS
10065 static int
10066 pgetc_without_PEOA(void)
10067 {
10068         int c;
10069         do {
10070                 pgetc_debug("pgetc at %d:%p'%s'",
10071                                 g_parsefile->left_in_line,
10072                                 g_parsefile->next_to_pgetc,
10073                                 g_parsefile->next_to_pgetc);
10074                 c = pgetc();
10075         } while (c == PEOA);
10076         return c;
10077 }
10078 #else
10079 # define pgetc_without_PEOA() pgetc()
10080 #endif
10081
10082 /*
10083  * Read a line from the script.
10084  */
10085 static char *
10086 pfgets(char *line, int len)
10087 {
10088         char *p = line;
10089         int nleft = len;
10090         int c;
10091
10092         while (--nleft > 0) {
10093                 c = pgetc_without_PEOA();
10094                 if (c == PEOF) {
10095                         if (p == line)
10096                                 return NULL;
10097                         break;
10098                 }
10099                 *p++ = c;
10100                 if (c == '\n')
10101                         break;
10102         }
10103         *p = '\0';
10104         return line;
10105 }
10106
10107 /*
10108  * Undo a call to pgetc.  Only two characters may be pushed back.
10109  * PEOF may be pushed back.
10110  */
10111 static void
10112 pungetc(void)
10113 {
10114         g_parsefile->unget++;
10115 }
10116
10117 /* This one eats backslash+newline */
10118 static int
10119 pgetc_eatbnl(void)
10120 {
10121         int c;
10122
10123         while ((c = pgetc()) == '\\') {
10124                 if (pgetc() != '\n') {
10125                         pungetc();
10126                         break;
10127                 }
10128
10129                 nlprompt();
10130         }
10131
10132         return c;
10133 }
10134
10135 /*
10136  * To handle the "." command, a stack of input files is used.  Pushfile
10137  * adds a new entry to the stack and popfile restores the previous level.
10138  */
10139 static void
10140 pushfile(void)
10141 {
10142         struct parsefile *pf;
10143
10144         pf = ckzalloc(sizeof(*pf));
10145         pf->prev = g_parsefile;
10146         pf->pf_fd = -1;
10147         /*pf->strpush = NULL; - ckzalloc did it */
10148         /*pf->basestrpush.prev = NULL;*/
10149         /*pf->unget = 0;*/
10150         g_parsefile = pf;
10151 }
10152
10153 static void
10154 popfile(void)
10155 {
10156         struct parsefile *pf = g_parsefile;
10157
10158         if (pf == &basepf)
10159                 return;
10160
10161         INT_OFF;
10162         if (pf->pf_fd >= 0)
10163                 close(pf->pf_fd);
10164         free(pf->buf);
10165         while (pf->strpush)
10166                 popstring();
10167         g_parsefile = pf->prev;
10168         free(pf);
10169         INT_ON;
10170 }
10171
10172 /*
10173  * Return to top level.
10174  */
10175 static void
10176 popallfiles(void)
10177 {
10178         while (g_parsefile != &basepf)
10179                 popfile();
10180 }
10181
10182 /*
10183  * Close the file(s) that the shell is reading commands from.  Called
10184  * after a fork is done.
10185  */
10186 static void
10187 closescript(void)
10188 {
10189         popallfiles();
10190         if (g_parsefile->pf_fd > 0) {
10191                 close(g_parsefile->pf_fd);
10192                 g_parsefile->pf_fd = 0;
10193         }
10194 }
10195
10196 /*
10197  * Like setinputfile, but takes an open file descriptor.  Call this with
10198  * interrupts off.
10199  */
10200 static void
10201 setinputfd(int fd, int push)
10202 {
10203         if (push) {
10204                 pushfile();
10205                 g_parsefile->buf = NULL;
10206         }
10207         g_parsefile->pf_fd = fd;
10208         if (g_parsefile->buf == NULL)
10209                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10210         g_parsefile->left_in_buffer = 0;
10211         g_parsefile->left_in_line = 0;
10212         g_parsefile->linno = 1;
10213 }
10214
10215 /*
10216  * Set the input to take input from a file.  If push is set, push the
10217  * old input onto the stack first.
10218  */
10219 static int
10220 setinputfile(const char *fname, int flags)
10221 {
10222         int fd;
10223
10224         INT_OFF;
10225         fd = open(fname, O_RDONLY);
10226         if (fd < 0) {
10227                 if (flags & INPUT_NOFILE_OK)
10228                         goto out;
10229                 exitstatus = 127;
10230                 ash_msg_and_raise_error("can't open '%s'", fname);
10231         }
10232         if (fd < 10)
10233                 fd = savefd(fd);
10234         else
10235                 close_on_exec_on(fd);
10236         setinputfd(fd, flags & INPUT_PUSH_FILE);
10237  out:
10238         INT_ON;
10239         return fd;
10240 }
10241
10242 /*
10243  * Like setinputfile, but takes input from a string.
10244  */
10245 static void
10246 setinputstring(char *string)
10247 {
10248         INT_OFF;
10249         pushfile();
10250         g_parsefile->next_to_pgetc = string;
10251         g_parsefile->left_in_line = strlen(string);
10252         g_parsefile->buf = NULL;
10253         g_parsefile->linno = 1;
10254         INT_ON;
10255 }
10256
10257
10258 /*
10259  * Routines to check for mail.
10260  */
10261
10262 #if ENABLE_ASH_MAIL
10263
10264 /* Hash of mtimes of mailboxes */
10265 static unsigned mailtime_hash;
10266 /* Set if MAIL or MAILPATH is changed. */
10267 static smallint mail_var_path_changed;
10268
10269 /*
10270  * Print appropriate message(s) if mail has arrived.
10271  * If mail_var_path_changed is set,
10272  * then the value of MAIL has mail_var_path_changed,
10273  * so we just update the values.
10274  */
10275 static void
10276 chkmail(void)
10277 {
10278         const char *mpath;
10279         char *p;
10280         char *q;
10281         unsigned new_hash;
10282         struct stackmark smark;
10283         struct stat statb;
10284
10285         setstackmark(&smark);
10286         mpath = mpathset() ? mpathval() : mailval();
10287         new_hash = 0;
10288         for (;;) {
10289                 p = path_advance(&mpath, nullstr);
10290                 if (p == NULL)
10291                         break;
10292                 if (*p == '\0')
10293                         continue;
10294                 for (q = p; *q; q++)
10295                         continue;
10296 #if DEBUG
10297                 if (q[-1] != '/')
10298                         abort();
10299 #endif
10300                 q[-1] = '\0';                   /* delete trailing '/' */
10301                 if (stat(p, &statb) < 0) {
10302                         continue;
10303                 }
10304                 /* Very simplistic "hash": just a sum of all mtimes */
10305                 new_hash += (unsigned)statb.st_mtime;
10306         }
10307         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10308                 if (mailtime_hash != 0)
10309                         out2str("you have mail\n");
10310                 mailtime_hash = new_hash;
10311         }
10312         mail_var_path_changed = 0;
10313         popstackmark(&smark);
10314 }
10315
10316 static void FAST_FUNC
10317 changemail(const char *val UNUSED_PARAM)
10318 {
10319         mail_var_path_changed = 1;
10320 }
10321
10322 #endif /* ASH_MAIL */
10323
10324
10325 /* ============ ??? */
10326
10327 /*
10328  * Set the shell parameters.
10329  */
10330 static void
10331 setparam(char **argv)
10332 {
10333         char **newparam;
10334         char **ap;
10335         int nparam;
10336
10337         for (nparam = 0; argv[nparam]; nparam++)
10338                 continue;
10339         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10340         while (*argv) {
10341                 *ap++ = ckstrdup(*argv++);
10342         }
10343         *ap = NULL;
10344         freeparam(&shellparam);
10345         shellparam.malloced = 1;
10346         shellparam.nparam = nparam;
10347         shellparam.p = newparam;
10348 #if ENABLE_ASH_GETOPTS
10349         shellparam.optind = 1;
10350         shellparam.optoff = -1;
10351 #endif
10352 }
10353
10354 /*
10355  * Process shell options.  The global variable argptr contains a pointer
10356  * to the argument list; we advance it past the options.
10357  *
10358  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10359  * For a non-interactive shell, an error condition encountered
10360  * by a special built-in ... shall cause the shell to write a diagnostic message
10361  * to standard error and exit as shown in the following table:
10362  * Error                                           Special Built-In
10363  * ...
10364  * Utility syntax error (option or operand error)  Shall exit
10365  * ...
10366  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10367  * we see that bash does not do that (set "finishes" with error code 1 instead,
10368  * and shell continues), and people rely on this behavior!
10369  * Testcase:
10370  * set -o barfoo 2>/dev/null
10371  * echo $?
10372  *
10373  * Oh well. Let's mimic that.
10374  */
10375 static int
10376 plus_minus_o(char *name, int val)
10377 {
10378         int i;
10379
10380         if (name) {
10381                 for (i = 0; i < NOPTS; i++) {
10382                         if (strcmp(name, optnames(i)) == 0) {
10383                                 optlist[i] = val;
10384                                 return 0;
10385                         }
10386                 }
10387                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10388                 return 1;
10389         }
10390         for (i = 0; i < NOPTS; i++) {
10391                 if (val) {
10392                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10393                 } else {
10394                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10395                 }
10396         }
10397         return 0;
10398 }
10399 static void
10400 setoption(int flag, int val)
10401 {
10402         int i;
10403
10404         for (i = 0; i < NOPTS; i++) {
10405                 if (optletters(i) == flag) {
10406                         optlist[i] = val;
10407                         return;
10408                 }
10409         }
10410         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10411         /* NOTREACHED */
10412 }
10413 static int
10414 options(int cmdline)
10415 {
10416         char *p;
10417         int val;
10418         int c;
10419
10420         if (cmdline)
10421                 minusc = NULL;
10422         while ((p = *argptr) != NULL) {
10423                 c = *p++;
10424                 if (c != '-' && c != '+')
10425                         break;
10426                 argptr++;
10427                 val = 0; /* val = 0 if c == '+' */
10428                 if (c == '-') {
10429                         val = 1;
10430                         if (p[0] == '\0' || LONE_DASH(p)) {
10431                                 if (!cmdline) {
10432                                         /* "-" means turn off -x and -v */
10433                                         if (p[0] == '\0')
10434                                                 xflag = vflag = 0;
10435                                         /* "--" means reset params */
10436                                         else if (*argptr == NULL)
10437                                                 setparam(argptr);
10438                                 }
10439                                 break;    /* "-" or "--" terminates options */
10440                         }
10441                 }
10442                 /* first char was + or - */
10443                 while ((c = *p++) != '\0') {
10444                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10445                         if (c == 'c' && cmdline) {
10446                                 minusc = p;     /* command is after shell args */
10447                         } else if (c == 'o') {
10448                                 if (plus_minus_o(*argptr, val)) {
10449                                         /* it already printed err message */
10450                                         return 1; /* error */
10451                                 }
10452                                 if (*argptr)
10453                                         argptr++;
10454                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10455                                 isloginsh = 1;
10456                         /* bash does not accept +-login, we also won't */
10457                         } else if (cmdline && val && (c == '-')) { /* long options */
10458                                 if (strcmp(p, "login") == 0)
10459                                         isloginsh = 1;
10460                                 break;
10461                         } else {
10462                                 setoption(c, val);
10463                         }
10464                 }
10465         }
10466         return 0;
10467 }
10468
10469 /*
10470  * The shift builtin command.
10471  */
10472 static int FAST_FUNC
10473 shiftcmd(int argc UNUSED_PARAM, char **argv)
10474 {
10475         int n;
10476         char **ap1, **ap2;
10477
10478         n = 1;
10479         if (argv[1])
10480                 n = number(argv[1]);
10481         if (n > shellparam.nparam)
10482                 n = 0; /* bash compat, was = shellparam.nparam; */
10483         INT_OFF;
10484         shellparam.nparam -= n;
10485         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10486                 if (shellparam.malloced)
10487                         free(*ap1);
10488         }
10489         ap2 = shellparam.p;
10490         while ((*ap2++ = *ap1++) != NULL)
10491                 continue;
10492 #if ENABLE_ASH_GETOPTS
10493         shellparam.optind = 1;
10494         shellparam.optoff = -1;
10495 #endif
10496         INT_ON;
10497         return 0;
10498 }
10499
10500 /*
10501  * POSIX requires that 'set' (but not export or readonly) output the
10502  * variables in lexicographic order - by the locale's collating order (sigh).
10503  * Maybe we could keep them in an ordered balanced binary tree
10504  * instead of hashed lists.
10505  * For now just roll 'em through qsort for printing...
10506  */
10507 static int
10508 showvars(const char *sep_prefix, int on, int off)
10509 {
10510         const char *sep;
10511         char **ep, **epend;
10512
10513         ep = listvars(on, off, &epend);
10514         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10515
10516         sep = *sep_prefix ? " " : sep_prefix;
10517
10518         for (; ep < epend; ep++) {
10519                 const char *p;
10520                 const char *q;
10521
10522                 p = strchrnul(*ep, '=');
10523                 q = nullstr;
10524                 if (*p)
10525                         q = single_quote(++p);
10526                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10527         }
10528         return 0;
10529 }
10530
10531 /*
10532  * The set command builtin.
10533  */
10534 static int FAST_FUNC
10535 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10536 {
10537         int retval;
10538
10539         if (!argv[1])
10540                 return showvars(nullstr, 0, VUNSET);
10541
10542         INT_OFF;
10543         retval = options(/*cmdline:*/ 0);
10544         if (retval == 0) { /* if no parse error... */
10545                 optschanged();
10546                 if (*argptr != NULL) {
10547                         setparam(argptr);
10548                 }
10549         }
10550         INT_ON;
10551         return retval;
10552 }
10553
10554 #if ENABLE_ASH_RANDOM_SUPPORT
10555 static void FAST_FUNC
10556 change_random(const char *value)
10557 {
10558         uint32_t t;
10559
10560         if (value == NULL) {
10561                 /* "get", generate */
10562                 t = next_random(&random_gen);
10563                 /* set without recursion */
10564                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10565                 vrandom.flags &= ~VNOFUNC;
10566         } else {
10567                 /* set/reset */
10568                 t = strtoul(value, NULL, 10);
10569                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10570         }
10571 }
10572 #endif
10573
10574 #if ENABLE_ASH_GETOPTS
10575 static int
10576 getopts(char *optstr, char *optvar, char **optfirst)
10577 {
10578         char *p, *q;
10579         char c = '?';
10580         int done = 0;
10581         char sbuf[2];
10582         char **optnext;
10583         int ind = shellparam.optind;
10584         int off = shellparam.optoff;
10585
10586         sbuf[1] = '\0';
10587
10588         shellparam.optind = -1;
10589         optnext = optfirst + ind - 1;
10590
10591         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10592                 p = NULL;
10593         else
10594                 p = optnext[-1] + off;
10595         if (p == NULL || *p == '\0') {
10596                 /* Current word is done, advance */
10597                 p = *optnext;
10598                 if (p == NULL || *p != '-' || *++p == '\0') {
10599  atend:
10600                         p = NULL;
10601                         done = 1;
10602                         goto out;
10603                 }
10604                 optnext++;
10605                 if (LONE_DASH(p))        /* check for "--" */
10606                         goto atend;
10607         }
10608
10609         c = *p++;
10610         for (q = optstr; *q != c;) {
10611                 if (*q == '\0') {
10612                         if (optstr[0] == ':') {
10613                                 sbuf[0] = c;
10614                                 /*sbuf[1] = '\0'; - already is */
10615                                 setvar0("OPTARG", sbuf);
10616                         } else {
10617                                 fprintf(stderr, "Illegal option -%c\n", c);
10618                                 unsetvar("OPTARG");
10619                         }
10620                         c = '?';
10621                         goto out;
10622                 }
10623                 if (*++q == ':')
10624                         q++;
10625         }
10626
10627         if (*++q == ':') {
10628                 if (*p == '\0' && (p = *optnext) == NULL) {
10629                         if (optstr[0] == ':') {
10630                                 sbuf[0] = c;
10631                                 /*sbuf[1] = '\0'; - already is */
10632                                 setvar0("OPTARG", sbuf);
10633                                 c = ':';
10634                         } else {
10635                                 fprintf(stderr, "No arg for -%c option\n", c);
10636                                 unsetvar("OPTARG");
10637                                 c = '?';
10638                         }
10639                         goto out;
10640                 }
10641
10642                 if (p == *optnext)
10643                         optnext++;
10644                 setvar0("OPTARG", p);
10645                 p = NULL;
10646         } else
10647                 setvar0("OPTARG", nullstr);
10648  out:
10649         ind = optnext - optfirst + 1;
10650         setvar("OPTIND", itoa(ind), VNOFUNC);
10651         sbuf[0] = c;
10652         /*sbuf[1] = '\0'; - already is */
10653         setvar0(optvar, sbuf);
10654
10655         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10656         shellparam.optind = ind;
10657
10658         return done;
10659 }
10660
10661 /*
10662  * The getopts builtin.  Shellparam.optnext points to the next argument
10663  * to be processed.  Shellparam.optptr points to the next character to
10664  * be processed in the current argument.  If shellparam.optnext is NULL,
10665  * then it's the first time getopts has been called.
10666  */
10667 static int FAST_FUNC
10668 getoptscmd(int argc, char **argv)
10669 {
10670         char **optbase;
10671
10672         if (argc < 3)
10673                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10674         if (argc == 3) {
10675                 optbase = shellparam.p;
10676                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10677                         shellparam.optind = 1;
10678                         shellparam.optoff = -1;
10679                 }
10680         } else {
10681                 optbase = &argv[3];
10682                 if ((unsigned)shellparam.optind > argc - 2) {
10683                         shellparam.optind = 1;
10684                         shellparam.optoff = -1;
10685                 }
10686         }
10687
10688         return getopts(argv[1], argv[2], optbase);
10689 }
10690 #endif /* ASH_GETOPTS */
10691
10692
10693 /* ============ Shell parser */
10694
10695 struct heredoc {
10696         struct heredoc *next;   /* next here document in list */
10697         union node *here;       /* redirection node */
10698         char *eofmark;          /* string indicating end of input */
10699         smallint striptabs;     /* if set, strip leading tabs */
10700 };
10701
10702 static smallint tokpushback;           /* last token pushed back */
10703 static smallint quoteflag;             /* set if (part of) last token was quoted */
10704 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10705 static struct heredoc *heredoclist;    /* list of here documents to read */
10706 static char *wordtext;                 /* text of last word returned by readtoken */
10707 static struct nodelist *backquotelist;
10708 static union node *redirnode;
10709 static struct heredoc *heredoc;
10710
10711 static const char *
10712 tokname(char *buf, int tok)
10713 {
10714         if (tok < TSEMI)
10715                 return tokname_array[tok];
10716         sprintf(buf, "\"%s\"", tokname_array[tok]);
10717         return buf;
10718 }
10719
10720 /* raise_error_unexpected_syntax:
10721  * Called when an unexpected token is read during the parse.  The argument
10722  * is the token that is expected, or -1 if more than one type of token can
10723  * occur at this point.
10724  */
10725 static void raise_error_unexpected_syntax(int) NORETURN;
10726 static void
10727 raise_error_unexpected_syntax(int token)
10728 {
10729         char msg[64];
10730         char buf[16];
10731         int l;
10732
10733         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10734         if (token >= 0)
10735                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10736         raise_error_syntax(msg);
10737         /* NOTREACHED */
10738 }
10739
10740 #define EOFMARKLEN 79
10741
10742 /* parsing is heavily cross-recursive, need these forward decls */
10743 static union node *andor(void);
10744 static union node *pipeline(void);
10745 static union node *parse_command(void);
10746 static void parseheredoc(void);
10747 static int peektoken(void);
10748 static int readtoken(void);
10749
10750 static union node *
10751 list(int nlflag)
10752 {
10753         union node *n1, *n2, *n3;
10754         int tok;
10755
10756         n1 = NULL;
10757         for (;;) {
10758                 switch (peektoken()) {
10759                 case TNL:
10760                         if (!(nlflag & 1))
10761                                 break;
10762                         parseheredoc();
10763                         return n1;
10764
10765                 case TEOF:
10766                         if (!n1 && (nlflag & 1))
10767                                 n1 = NODE_EOF;
10768                         parseheredoc();
10769                         return n1;
10770                 }
10771
10772                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10773                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10774                         return n1;
10775                 nlflag |= 2;
10776
10777                 n2 = andor();
10778                 tok = readtoken();
10779                 if (tok == TBACKGND) {
10780                         if (n2->type == NPIPE) {
10781                                 n2->npipe.pipe_backgnd = 1;
10782                         } else {
10783                                 if (n2->type != NREDIR) {
10784                                         n3 = stzalloc(sizeof(struct nredir));
10785                                         n3->nredir.n = n2;
10786                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10787                                         n2 = n3;
10788                                 }
10789                                 n2->type = NBACKGND;
10790                         }
10791                 }
10792                 if (n1 == NULL) {
10793                         n1 = n2;
10794                 } else {
10795                         n3 = stzalloc(sizeof(struct nbinary));
10796                         n3->type = NSEMI;
10797                         n3->nbinary.ch1 = n1;
10798                         n3->nbinary.ch2 = n2;
10799                         n1 = n3;
10800                 }
10801                 switch (tok) {
10802                 case TNL:
10803                 case TEOF:
10804                         tokpushback = 1;
10805                         /* fall through */
10806                 case TBACKGND:
10807                 case TSEMI:
10808                         break;
10809                 default:
10810                         if ((nlflag & 1))
10811                                 raise_error_unexpected_syntax(-1);
10812                         tokpushback = 1;
10813                         return n1;
10814                 }
10815         }
10816 }
10817
10818 static union node *
10819 andor(void)
10820 {
10821         union node *n1, *n2, *n3;
10822         int t;
10823
10824         n1 = pipeline();
10825         for (;;) {
10826                 t = readtoken();
10827                 if (t == TAND) {
10828                         t = NAND;
10829                 } else if (t == TOR) {
10830                         t = NOR;
10831                 } else {
10832                         tokpushback = 1;
10833                         return n1;
10834                 }
10835                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10836                 n2 = pipeline();
10837                 n3 = stzalloc(sizeof(struct nbinary));
10838                 n3->type = t;
10839                 n3->nbinary.ch1 = n1;
10840                 n3->nbinary.ch2 = n2;
10841                 n1 = n3;
10842         }
10843 }
10844
10845 static union node *
10846 pipeline(void)
10847 {
10848         union node *n1, *n2, *pipenode;
10849         struct nodelist *lp, *prev;
10850         int negate;
10851
10852         negate = 0;
10853         TRACE(("pipeline: entered\n"));
10854         if (readtoken() == TNOT) {
10855                 negate = !negate;
10856                 checkkwd = CHKKWD | CHKALIAS;
10857         } else
10858                 tokpushback = 1;
10859         n1 = parse_command();
10860         if (readtoken() == TPIPE) {
10861                 pipenode = stzalloc(sizeof(struct npipe));
10862                 pipenode->type = NPIPE;
10863                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10864                 lp = stzalloc(sizeof(struct nodelist));
10865                 pipenode->npipe.cmdlist = lp;
10866                 lp->n = n1;
10867                 do {
10868                         prev = lp;
10869                         lp = stzalloc(sizeof(struct nodelist));
10870                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10871                         lp->n = parse_command();
10872                         prev->next = lp;
10873                 } while (readtoken() == TPIPE);
10874                 lp->next = NULL;
10875                 n1 = pipenode;
10876         }
10877         tokpushback = 1;
10878         if (negate) {
10879                 n2 = stzalloc(sizeof(struct nnot));
10880                 n2->type = NNOT;
10881                 n2->nnot.com = n1;
10882                 return n2;
10883         }
10884         return n1;
10885 }
10886
10887 static union node *
10888 makename(void)
10889 {
10890         union node *n;
10891
10892         n = stzalloc(sizeof(struct narg));
10893         n->type = NARG;
10894         /*n->narg.next = NULL; - stzalloc did it */
10895         n->narg.text = wordtext;
10896         n->narg.backquote = backquotelist;
10897         return n;
10898 }
10899
10900 static void
10901 fixredir(union node *n, const char *text, int err)
10902 {
10903         int fd;
10904
10905         TRACE(("Fix redir %s %d\n", text, err));
10906         if (!err)
10907                 n->ndup.vname = NULL;
10908
10909         fd = bb_strtou(text, NULL, 10);
10910         if (!errno && fd >= 0)
10911                 n->ndup.dupfd = fd;
10912         else if (LONE_DASH(text))
10913                 n->ndup.dupfd = -1;
10914         else {
10915                 if (err)
10916                         raise_error_syntax("bad fd number");
10917                 n->ndup.vname = makename();
10918         }
10919 }
10920
10921 /*
10922  * Returns true if the text contains nothing to expand (no dollar signs
10923  * or backquotes).
10924  */
10925 static int
10926 noexpand(const char *text)
10927 {
10928         unsigned char c;
10929
10930         while ((c = *text++) != '\0') {
10931                 if (c == CTLQUOTEMARK)
10932                         continue;
10933                 if (c == CTLESC)
10934                         text++;
10935                 else if (SIT(c, BASESYNTAX) == CCTL)
10936                         return 0;
10937         }
10938         return 1;
10939 }
10940
10941 static void
10942 parsefname(void)
10943 {
10944         union node *n = redirnode;
10945
10946         if (readtoken() != TWORD)
10947                 raise_error_unexpected_syntax(-1);
10948         if (n->type == NHERE) {
10949                 struct heredoc *here = heredoc;
10950                 struct heredoc *p;
10951                 int i;
10952
10953                 if (quoteflag == 0)
10954                         n->type = NXHERE;
10955                 TRACE(("Here document %d\n", n->type));
10956                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10957                         raise_error_syntax("illegal eof marker for << redirection");
10958                 rmescapes(wordtext, 0);
10959                 here->eofmark = wordtext;
10960                 here->next = NULL;
10961                 if (heredoclist == NULL)
10962                         heredoclist = here;
10963                 else {
10964                         for (p = heredoclist; p->next; p = p->next)
10965                                 continue;
10966                         p->next = here;
10967                 }
10968         } else if (n->type == NTOFD || n->type == NFROMFD) {
10969                 fixredir(n, wordtext, 0);
10970         } else {
10971                 n->nfile.fname = makename();
10972         }
10973 }
10974
10975 static union node *
10976 simplecmd(void)
10977 {
10978         union node *args, **app;
10979         union node *n = NULL;
10980         union node *vars, **vpp;
10981         union node **rpp, *redir;
10982         int savecheckkwd;
10983 #if ENABLE_ASH_BASH_COMPAT
10984         smallint double_brackets_flag = 0;
10985         smallint function_flag = 0;
10986 #endif
10987
10988         args = NULL;
10989         app = &args;
10990         vars = NULL;
10991         vpp = &vars;
10992         redir = NULL;
10993         rpp = &redir;
10994
10995         savecheckkwd = CHKALIAS;
10996         for (;;) {
10997                 int t;
10998                 checkkwd = savecheckkwd;
10999                 t = readtoken();
11000                 switch (t) {
11001 #if ENABLE_ASH_BASH_COMPAT
11002                 case TFUNCTION:
11003                         if (peektoken() != TWORD)
11004                                 raise_error_unexpected_syntax(TWORD);
11005                         function_flag = 1;
11006                         break;
11007                 case TAND: /* "&&" */
11008                 case TOR: /* "||" */
11009                         if (!double_brackets_flag) {
11010                                 tokpushback = 1;
11011                                 goto out;
11012                         }
11013                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11014 #endif
11015                 case TWORD:
11016                         n = stzalloc(sizeof(struct narg));
11017                         n->type = NARG;
11018                         /*n->narg.next = NULL; - stzalloc did it */
11019                         n->narg.text = wordtext;
11020 #if ENABLE_ASH_BASH_COMPAT
11021                         if (strcmp("[[", wordtext) == 0)
11022                                 double_brackets_flag = 1;
11023                         else if (strcmp("]]", wordtext) == 0)
11024                                 double_brackets_flag = 0;
11025 #endif
11026                         n->narg.backquote = backquotelist;
11027                         if (savecheckkwd && isassignment(wordtext)) {
11028                                 *vpp = n;
11029                                 vpp = &n->narg.next;
11030                         } else {
11031                                 *app = n;
11032                                 app = &n->narg.next;
11033                                 savecheckkwd = 0;
11034                         }
11035 #if ENABLE_ASH_BASH_COMPAT
11036                         if (function_flag) {
11037                                 checkkwd = CHKNL | CHKKWD;
11038                                 switch (peektoken()) {
11039                                 case TBEGIN:
11040                                 case TIF:
11041                                 case TCASE:
11042                                 case TUNTIL:
11043                                 case TWHILE:
11044                                 case TFOR:
11045                                         goto do_func;
11046                                 case TLP:
11047                                         function_flag = 0;
11048                                         break;
11049                                 case TWORD:
11050                                         if (strcmp("[[", wordtext) == 0)
11051                                                 goto do_func;
11052                                         /* fall through */
11053                                 default:
11054                                         raise_error_unexpected_syntax(-1);
11055                                 }
11056                         }
11057 #endif
11058                         break;
11059                 case TREDIR:
11060                         *rpp = n = redirnode;
11061                         rpp = &n->nfile.next;
11062                         parsefname();   /* read name of redirection file */
11063                         break;
11064                 case TLP:
11065  IF_ASH_BASH_COMPAT(do_func:)
11066                         if (args && app == &args->narg.next
11067                          && !vars && !redir
11068                         ) {
11069                                 struct builtincmd *bcmd;
11070                                 const char *name;
11071
11072                                 /* We have a function */
11073                                 if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP)
11074                                         raise_error_unexpected_syntax(TRP);
11075                                 name = n->narg.text;
11076                                 if (!goodname(name)
11077                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11078                                 ) {
11079                                         raise_error_syntax("bad function name");
11080                                 }
11081                                 n->type = NDEFUN;
11082                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11083                                 n->narg.next = parse_command();
11084                                 return n;
11085                         }
11086                         IF_ASH_BASH_COMPAT(function_flag = 0;)
11087                         /* fall through */
11088                 default:
11089                         tokpushback = 1;
11090                         goto out;
11091                 }
11092         }
11093  out:
11094         *app = NULL;
11095         *vpp = NULL;
11096         *rpp = NULL;
11097         n = stzalloc(sizeof(struct ncmd));
11098         n->type = NCMD;
11099         n->ncmd.args = args;
11100         n->ncmd.assign = vars;
11101         n->ncmd.redirect = redir;
11102         return n;
11103 }
11104
11105 static union node *
11106 parse_command(void)
11107 {
11108         union node *n1, *n2;
11109         union node *ap, **app;
11110         union node *cp, **cpp;
11111         union node *redir, **rpp;
11112         union node **rpp2;
11113         int t;
11114
11115         redir = NULL;
11116         rpp2 = &redir;
11117
11118         switch (readtoken()) {
11119         default:
11120                 raise_error_unexpected_syntax(-1);
11121                 /* NOTREACHED */
11122         case TIF:
11123                 n1 = stzalloc(sizeof(struct nif));
11124                 n1->type = NIF;
11125                 n1->nif.test = list(0);
11126                 if (readtoken() != TTHEN)
11127                         raise_error_unexpected_syntax(TTHEN);
11128                 n1->nif.ifpart = list(0);
11129                 n2 = n1;
11130                 while (readtoken() == TELIF) {
11131                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11132                         n2 = n2->nif.elsepart;
11133                         n2->type = NIF;
11134                         n2->nif.test = list(0);
11135                         if (readtoken() != TTHEN)
11136                                 raise_error_unexpected_syntax(TTHEN);
11137                         n2->nif.ifpart = list(0);
11138                 }
11139                 if (lasttoken == TELSE)
11140                         n2->nif.elsepart = list(0);
11141                 else {
11142                         n2->nif.elsepart = NULL;
11143                         tokpushback = 1;
11144                 }
11145                 t = TFI;
11146                 break;
11147         case TWHILE:
11148         case TUNTIL: {
11149                 int got;
11150                 n1 = stzalloc(sizeof(struct nbinary));
11151                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11152                 n1->nbinary.ch1 = list(0);
11153                 got = readtoken();
11154                 if (got != TDO) {
11155                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11156                                         got == TWORD ? wordtext : ""));
11157                         raise_error_unexpected_syntax(TDO);
11158                 }
11159                 n1->nbinary.ch2 = list(0);
11160                 t = TDONE;
11161                 break;
11162         }
11163         case TFOR:
11164                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11165                         raise_error_syntax("bad for loop variable");
11166                 n1 = stzalloc(sizeof(struct nfor));
11167                 n1->type = NFOR;
11168                 n1->nfor.var = wordtext;
11169                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11170                 if (readtoken() == TIN) {
11171                         app = &ap;
11172                         while (readtoken() == TWORD) {
11173                                 n2 = stzalloc(sizeof(struct narg));
11174                                 n2->type = NARG;
11175                                 /*n2->narg.next = NULL; - stzalloc did it */
11176                                 n2->narg.text = wordtext;
11177                                 n2->narg.backquote = backquotelist;
11178                                 *app = n2;
11179                                 app = &n2->narg.next;
11180                         }
11181                         *app = NULL;
11182                         n1->nfor.args = ap;
11183                         if (lasttoken != TNL && lasttoken != TSEMI)
11184                                 raise_error_unexpected_syntax(-1);
11185                 } else {
11186                         n2 = stzalloc(sizeof(struct narg));
11187                         n2->type = NARG;
11188                         /*n2->narg.next = NULL; - stzalloc did it */
11189                         n2->narg.text = (char *)dolatstr;
11190                         /*n2->narg.backquote = NULL;*/
11191                         n1->nfor.args = n2;
11192                         /*
11193                          * Newline or semicolon here is optional (but note
11194                          * that the original Bourne shell only allowed NL).
11195                          */
11196                         if (lasttoken != TSEMI)
11197                                 tokpushback = 1;
11198                 }
11199                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11200                 if (readtoken() != TDO)
11201                         raise_error_unexpected_syntax(TDO);
11202                 n1->nfor.body = list(0);
11203                 t = TDONE;
11204                 break;
11205         case TCASE:
11206                 n1 = stzalloc(sizeof(struct ncase));
11207                 n1->type = NCASE;
11208                 if (readtoken() != TWORD)
11209                         raise_error_unexpected_syntax(TWORD);
11210                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11211                 n2->type = NARG;
11212                 /*n2->narg.next = NULL; - stzalloc did it */
11213                 n2->narg.text = wordtext;
11214                 n2->narg.backquote = backquotelist;
11215                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11216                 if (readtoken() != TIN)
11217                         raise_error_unexpected_syntax(TIN);
11218                 cpp = &n1->ncase.cases;
11219  next_case:
11220                 checkkwd = CHKNL | CHKKWD;
11221                 t = readtoken();
11222                 while (t != TESAC) {
11223                         if (lasttoken == TLP)
11224                                 readtoken();
11225                         *cpp = cp = stzalloc(sizeof(struct nclist));
11226                         cp->type = NCLIST;
11227                         app = &cp->nclist.pattern;
11228                         for (;;) {
11229                                 *app = ap = stzalloc(sizeof(struct narg));
11230                                 ap->type = NARG;
11231                                 /*ap->narg.next = NULL; - stzalloc did it */
11232                                 ap->narg.text = wordtext;
11233                                 ap->narg.backquote = backquotelist;
11234                                 if (readtoken() != TPIPE)
11235                                         break;
11236                                 app = &ap->narg.next;
11237                                 readtoken();
11238                         }
11239                         //ap->narg.next = NULL;
11240                         if (lasttoken != TRP)
11241                                 raise_error_unexpected_syntax(TRP);
11242                         cp->nclist.body = list(2);
11243
11244                         cpp = &cp->nclist.next;
11245
11246                         checkkwd = CHKNL | CHKKWD;
11247                         t = readtoken();
11248                         if (t != TESAC) {
11249                                 if (t != TENDCASE)
11250                                         raise_error_unexpected_syntax(TENDCASE);
11251                                 goto next_case;
11252                         }
11253                 }
11254                 *cpp = NULL;
11255                 goto redir;
11256         case TLP:
11257                 n1 = stzalloc(sizeof(struct nredir));
11258                 n1->type = NSUBSHELL;
11259                 n1->nredir.n = list(0);
11260                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11261                 t = TRP;
11262                 break;
11263         case TBEGIN:
11264                 n1 = list(0);
11265                 t = TEND;
11266                 break;
11267         IF_ASH_BASH_COMPAT(case TFUNCTION:)
11268         case TWORD:
11269         case TREDIR:
11270                 tokpushback = 1;
11271                 return simplecmd();
11272         }
11273
11274         if (readtoken() != t)
11275                 raise_error_unexpected_syntax(t);
11276
11277  redir:
11278         /* Now check for redirection which may follow command */
11279         checkkwd = CHKKWD | CHKALIAS;
11280         rpp = rpp2;
11281         while (readtoken() == TREDIR) {
11282                 *rpp = n2 = redirnode;
11283                 rpp = &n2->nfile.next;
11284                 parsefname();
11285         }
11286         tokpushback = 1;
11287         *rpp = NULL;
11288         if (redir) {
11289                 if (n1->type != NSUBSHELL) {
11290                         n2 = stzalloc(sizeof(struct nredir));
11291                         n2->type = NREDIR;
11292                         n2->nredir.n = n1;
11293                         n1 = n2;
11294                 }
11295                 n1->nredir.redirect = redir;
11296         }
11297         return n1;
11298 }
11299
11300 #if ENABLE_ASH_BASH_COMPAT
11301 static int
11302 decode_dollar_squote(void)
11303 {
11304         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11305         int c, cnt;
11306         char *p;
11307         char buf[4];
11308
11309         c = pgetc();
11310         p = strchr(C_escapes, c);
11311         if (p) {
11312                 buf[0] = c;
11313                 p = buf;
11314                 cnt = 3;
11315                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11316                         do {
11317                                 c = pgetc();
11318                                 *++p = c;
11319                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11320                         pungetc();
11321                 } else if (c == 'x') { /* \xHH */
11322                         do {
11323                                 c = pgetc();
11324                                 *++p = c;
11325                         } while (isxdigit(c) && --cnt);
11326                         pungetc();
11327                         if (cnt == 3) { /* \x but next char is "bad" */
11328                                 c = 'x';
11329                                 goto unrecognized;
11330                         }
11331                 } else { /* simple seq like \\ or \t */
11332                         p++;
11333                 }
11334                 *p = '\0';
11335                 p = buf;
11336                 c = bb_process_escape_sequence((void*)&p);
11337         } else { /* unrecognized "\z": print both chars unless ' or " */
11338                 if (c != '\'' && c != '"') {
11339  unrecognized:
11340                         c |= 0x100; /* "please encode \, then me" */
11341                 }
11342         }
11343         return c;
11344 }
11345 #endif
11346
11347 /*
11348  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11349  * is not NULL, read a here document.  In the latter case, eofmark is the
11350  * word which marks the end of the document and striptabs is true if
11351  * leading tabs should be stripped from the document.  The argument c
11352  * is the first character of the input token or document.
11353  *
11354  * Because C does not have internal subroutines, I have simulated them
11355  * using goto's to implement the subroutine linkage.  The following macros
11356  * will run code that appears at the end of readtoken1.
11357  */
11358 #define CHECKEND()      {goto checkend; checkend_return:;}
11359 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11360 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11361 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11362 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11363 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11364 static int
11365 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11366 {
11367         /* NB: syntax parameter fits into smallint */
11368         /* c parameter is an unsigned char or PEOF or PEOA */
11369         char *out;
11370         size_t len;
11371         char line[EOFMARKLEN + 1];
11372         struct nodelist *bqlist;
11373         smallint quotef;
11374         smallint dblquote;
11375         smallint oldstyle;
11376         smallint prevsyntax; /* syntax before arithmetic */
11377 #if ENABLE_ASH_EXPAND_PRMT
11378         smallint pssyntax;   /* we are expanding a prompt string */
11379 #endif
11380         int varnest;         /* levels of variables expansion */
11381         int arinest;         /* levels of arithmetic expansion */
11382         int parenlevel;      /* levels of parens in arithmetic */
11383         int dqvarnest;       /* levels of variables expansion within double quotes */
11384
11385         IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
11386
11387         startlinno = g_parsefile->linno;
11388         bqlist = NULL;
11389         quotef = 0;
11390         prevsyntax = 0;
11391 #if ENABLE_ASH_EXPAND_PRMT
11392         pssyntax = (syntax == PSSYNTAX);
11393         if (pssyntax)
11394                 syntax = DQSYNTAX;
11395 #endif
11396         dblquote = (syntax == DQSYNTAX);
11397         varnest = 0;
11398         arinest = 0;
11399         parenlevel = 0;
11400         dqvarnest = 0;
11401
11402         STARTSTACKSTR(out);
11403  loop:
11404         /* For each line, until end of word */
11405         CHECKEND();     /* set c to PEOF if at end of here document */
11406         for (;;) {      /* until end of line or end of word */
11407                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11408                 switch (SIT(c, syntax)) {
11409                 case CNL:       /* '\n' */
11410                         if (syntax == BASESYNTAX)
11411                                 goto endword;   /* exit outer loop */
11412                         USTPUTC(c, out);
11413                         nlprompt();
11414                         c = pgetc();
11415                         goto loop;              /* continue outer loop */
11416                 case CWORD:
11417                         USTPUTC(c, out);
11418                         break;
11419                 case CCTL:
11420 #if ENABLE_ASH_BASH_COMPAT
11421                         if (c == '\\' && bash_dollar_squote) {
11422                                 c = decode_dollar_squote();
11423                                 if (c == '\0') {
11424                                         /* skip $'\000', $'\x00' (like bash) */
11425                                         break;
11426                                 }
11427                                 if (c & 0x100) {
11428                                         /* Unknown escape. Encode as '\z' */
11429                                         c = (unsigned char)c;
11430                                         if (eofmark == NULL || dblquote)
11431                                                 USTPUTC(CTLESC, out);
11432                                         USTPUTC('\\', out);
11433                                 }
11434                         }
11435 #endif
11436                         if (eofmark == NULL || dblquote)
11437                                 USTPUTC(CTLESC, out);
11438                         USTPUTC(c, out);
11439                         break;
11440                 case CBACK:     /* backslash */
11441                         c = pgetc_without_PEOA();
11442                         if (c == PEOF) {
11443                                 USTPUTC(CTLESC, out);
11444                                 USTPUTC('\\', out);
11445                                 pungetc();
11446                         } else if (c == '\n') {
11447                                 nlprompt();
11448                         } else {
11449 #if ENABLE_ASH_EXPAND_PRMT
11450                                 if (c == '$' && pssyntax) {
11451                                         USTPUTC(CTLESC, out);
11452                                         USTPUTC('\\', out);
11453                                 }
11454 #endif
11455                                 /* Backslash is retained if we are in "str" and next char isn't special */
11456                                 if (dblquote
11457                                  && c != '\\'
11458                                  && c != '`'
11459                                  && c != '$'
11460                                  && (c != '"' || eofmark != NULL)
11461                                 ) {
11462                                         USTPUTC('\\', out);
11463                                 }
11464                                 USTPUTC(CTLESC, out);
11465                                 USTPUTC(c, out);
11466                                 quotef = 1;
11467                         }
11468                         break;
11469                 case CSQUOTE:
11470                         syntax = SQSYNTAX;
11471  quotemark:
11472                         if (eofmark == NULL) {
11473                                 USTPUTC(CTLQUOTEMARK, out);
11474                         }
11475                         break;
11476                 case CDQUOTE:
11477                         syntax = DQSYNTAX;
11478                         dblquote = 1;
11479                         goto quotemark;
11480                 case CENDQUOTE:
11481                         IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
11482                         if (eofmark != NULL && varnest == 0) {
11483                                 USTPUTC(c, out);
11484                         } else {
11485                                 if (dqvarnest == 0) {
11486                                         syntax = BASESYNTAX;
11487                                         dblquote = 0;
11488                                 }
11489                                 quotef = 1;
11490                                 goto quotemark;
11491                         }
11492                         break;
11493                 case CVAR:      /* '$' */
11494                         PARSESUB();             /* parse substitution */
11495                         break;
11496                 case CENDVAR:   /* '}' */
11497                         if (varnest > 0) {
11498                                 varnest--;
11499                                 if (dqvarnest > 0) {
11500                                         dqvarnest--;
11501                                 }
11502                                 c = CTLENDVAR;
11503                         }
11504                         USTPUTC(c, out);
11505                         break;
11506 #if ENABLE_SH_MATH_SUPPORT
11507                 case CLP:       /* '(' in arithmetic */
11508                         parenlevel++;
11509                         USTPUTC(c, out);
11510                         break;
11511                 case CRP:       /* ')' in arithmetic */
11512                         if (parenlevel > 0) {
11513                                 parenlevel--;
11514                         } else {
11515                                 if (pgetc_eatbnl() == ')') {
11516                                         c = CTLENDARI;
11517                                         if (--arinest == 0) {
11518                                                 syntax = prevsyntax;
11519                                         }
11520                                 } else {
11521                                         /*
11522                                          * unbalanced parens
11523                                          * (don't 2nd guess - no error)
11524                                          */
11525                                         pungetc();
11526                                 }
11527                         }
11528                         USTPUTC(c, out);
11529                         break;
11530 #endif
11531                 case CBQUOTE:   /* '`' */
11532                         PARSEBACKQOLD();
11533                         break;
11534                 case CENDFILE:
11535                         goto endword;           /* exit outer loop */
11536                 case CIGN:
11537                         break;
11538                 default:
11539                         if (varnest == 0) {
11540 #if ENABLE_ASH_BASH_COMPAT
11541                                 if (c == '&') {
11542 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11543                                         if (pgetc() == '>')
11544                                                 c = 0x100 + '>'; /* flag &> */
11545                                         pungetc();
11546                                 }
11547 #endif
11548                                 goto endword;   /* exit outer loop */
11549                         }
11550                         IF_ASH_ALIAS(if (c != PEOA))
11551                                 USTPUTC(c, out);
11552                 }
11553                 c = pgetc();
11554         } /* for (;;) */
11555  endword:
11556
11557 #if ENABLE_SH_MATH_SUPPORT
11558         if (syntax == ARISYNTAX)
11559                 raise_error_syntax("missing '))'");
11560 #endif
11561         if (syntax != BASESYNTAX && eofmark == NULL)
11562                 raise_error_syntax("unterminated quoted string");
11563         if (varnest != 0) {
11564                 startlinno = g_parsefile->linno;
11565                 /* { */
11566                 raise_error_syntax("missing '}'");
11567         }
11568         USTPUTC('\0', out);
11569         len = out - (char *)stackblock();
11570         out = stackblock();
11571         if (eofmark == NULL) {
11572                 if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>'))
11573                  && quotef == 0
11574                 ) {
11575                         if (isdigit_str9(out)) {
11576                                 PARSEREDIR(); /* passed as params: out, c */
11577                                 lasttoken = TREDIR;
11578                                 return lasttoken;
11579                         }
11580                         /* else: non-number X seen, interpret it
11581                          * as "NNNX>file" = "NNNX >file" */
11582                 }
11583                 pungetc();
11584         }
11585         quoteflag = quotef;
11586         backquotelist = bqlist;
11587         grabstackblock(len);
11588         wordtext = out;
11589         lasttoken = TWORD;
11590         return lasttoken;
11591 /* end of readtoken routine */
11592
11593 /*
11594  * Check to see whether we are at the end of the here document.  When this
11595  * is called, c is set to the first character of the next input line.  If
11596  * we are at the end of the here document, this routine sets the c to PEOF.
11597  */
11598 checkend: {
11599         if (eofmark) {
11600 #if ENABLE_ASH_ALIAS
11601                 if (c == PEOA)
11602                         c = pgetc_without_PEOA();
11603 #endif
11604                 if (striptabs) {
11605                         while (c == '\t') {
11606                                 c = pgetc_without_PEOA();
11607                         }
11608                 }
11609                 if (c == *eofmark) {
11610                         if (pfgets(line, sizeof(line)) != NULL) {
11611                                 char *p, *q;
11612                                 int cc;
11613
11614                                 p = line;
11615                                 for (q = eofmark + 1;; p++, q++) {
11616                                         cc = *p;
11617                                         if (cc == '\n')
11618                                                 cc = 0;
11619                                         if (!*q || cc != *q)
11620                                                 break;
11621                                 }
11622                                 if (cc == *q) {
11623                                         c = PEOF;
11624                                         nlnoprompt();
11625                                 } else {
11626                                         pushstring(line, NULL);
11627                                 }
11628                         }
11629                 }
11630         }
11631         goto checkend_return;
11632 }
11633
11634 /*
11635  * Parse a redirection operator.  The variable "out" points to a string
11636  * specifying the fd to be redirected.  The variable "c" contains the
11637  * first character of the redirection operator.
11638  */
11639 parseredir: {
11640         /* out is already checked to be a valid number or "" */
11641         int fd = (*out == '\0' ? -1 : atoi(out));
11642         union node *np;
11643
11644         np = stzalloc(sizeof(struct nfile));
11645         if (c == '>') {
11646                 np->nfile.fd = 1;
11647                 c = pgetc();
11648                 if (c == '>')
11649                         np->type = NAPPEND;
11650                 else if (c == '|')
11651                         np->type = NCLOBBER;
11652                 else if (c == '&')
11653                         np->type = NTOFD;
11654                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11655                 else {
11656                         np->type = NTO;
11657                         pungetc();
11658                 }
11659         }
11660 #if ENABLE_ASH_BASH_COMPAT
11661         else if (c == 0x100 + '>') { /* this flags &> redirection */
11662                 np->nfile.fd = 1;
11663                 pgetc(); /* this is '>', no need to check */
11664                 np->type = NTO2;
11665         }
11666 #endif
11667         else { /* c == '<' */
11668                 /*np->nfile.fd = 0; - stzalloc did it */
11669                 c = pgetc();
11670                 switch (c) {
11671                 case '<':
11672                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11673                                 np = stzalloc(sizeof(struct nhere));
11674                                 /*np->nfile.fd = 0; - stzalloc did it */
11675                         }
11676                         np->type = NHERE;
11677                         heredoc = stzalloc(sizeof(struct heredoc));
11678                         heredoc->here = np;
11679                         c = pgetc();
11680                         if (c == '-') {
11681                                 heredoc->striptabs = 1;
11682                         } else {
11683                                 /*heredoc->striptabs = 0; - stzalloc did it */
11684                                 pungetc();
11685                         }
11686                         break;
11687
11688                 case '&':
11689                         np->type = NFROMFD;
11690                         break;
11691
11692                 case '>':
11693                         np->type = NFROMTO;
11694                         break;
11695
11696                 default:
11697                         np->type = NFROM;
11698                         pungetc();
11699                         break;
11700                 }
11701         }
11702         if (fd >= 0)
11703                 np->nfile.fd = fd;
11704         redirnode = np;
11705         goto parseredir_return;
11706 }
11707
11708 /*
11709  * Parse a substitution.  At this point, we have read the dollar sign
11710  * and nothing else.
11711  */
11712
11713 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11714  * (assuming ascii char codes, as the original implementation did) */
11715 #define is_special(c) \
11716         (((unsigned)(c) - 33 < 32) \
11717                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11718 parsesub: {
11719         unsigned char subtype;
11720         int typeloc;
11721
11722         c = pgetc_eatbnl();
11723         if (c > 255 /* PEOA or PEOF */
11724          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11725         ) {
11726 #if ENABLE_ASH_BASH_COMPAT
11727                 if (syntax != DQSYNTAX && c == '\'')
11728                         bash_dollar_squote = 1;
11729                 else
11730 #endif
11731                         USTPUTC('$', out);
11732                 pungetc();
11733         } else if (c == '(') {
11734                 /* $(command) or $((arith)) */
11735                 if (pgetc_eatbnl() == '(') {
11736 #if ENABLE_SH_MATH_SUPPORT
11737                         PARSEARITH();
11738 #else
11739                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11740 #endif
11741                 } else {
11742                         pungetc();
11743                         PARSEBACKQNEW();
11744                 }
11745         } else {
11746                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11747                 USTPUTC(CTLVAR, out);
11748                 typeloc = out - (char *)stackblock();
11749                 STADJUST(1, out);
11750                 subtype = VSNORMAL;
11751                 if (c == '{') {
11752                         c = pgetc_eatbnl();
11753                         subtype = 0;
11754                 }
11755  varname:
11756                 if (is_name(c)) {
11757                         /* $[{[#]]NAME[}] */
11758                         do {
11759                                 STPUTC(c, out);
11760                                 c = pgetc_eatbnl();
11761                         } while (is_in_name(c));
11762                 } else if (isdigit(c)) {
11763                         /* $[{[#]]NUM[}] */
11764                         do {
11765                                 STPUTC(c, out);
11766                                 c = pgetc_eatbnl();
11767                         } while (isdigit(c));
11768                 } else if (is_special(c)) {
11769                         /* $[{[#]]<specialchar>[}] */
11770                         int cc = c;
11771
11772                         c = pgetc_eatbnl();
11773                         if (!subtype && cc == '#') {
11774                                 subtype = VSLENGTH;
11775                                 if (c == '_' || isalnum(c))
11776                                         goto varname;
11777                                 cc = c;
11778                                 c = pgetc_eatbnl();
11779                                 if (cc == '}' || c != '}') {
11780                                         pungetc();
11781                                         subtype = 0;
11782                                         c = cc;
11783                                         cc = '#';
11784                                 }
11785                         }
11786                         USTPUTC(cc, out);
11787                 } else {
11788                         goto badsub;
11789                 }
11790                 if (c != '}' && subtype == VSLENGTH) {
11791                         /* ${#VAR didn't end with } */
11792                         goto badsub;
11793                 }
11794
11795                 if (subtype == 0) {
11796                         static const char types[] ALIGN1 = "}-+?=";
11797                         /* ${VAR...} but not $VAR or ${#VAR} */
11798                         /* c == first char after VAR */
11799                         switch (c) {
11800                         case ':':
11801                                 c = pgetc_eatbnl();
11802 #if ENABLE_ASH_BASH_COMPAT
11803                                 /* This check is only needed to not misinterpret
11804                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11805                                  * constructs.
11806                                  */
11807                                 if (!strchr(types, c)) {
11808                                         subtype = VSSUBSTR;
11809                                         pungetc();
11810                                         break; /* "goto badsub" is bigger (!) */
11811                                 }
11812 #endif
11813                                 subtype = VSNUL;
11814                                 /*FALLTHROUGH*/
11815                         default: {
11816                                 const char *p = strchr(types, c);
11817                                 if (p == NULL)
11818                                         break;
11819                                 subtype |= p - types + VSNORMAL;
11820                                 break;
11821                         }
11822                         case '%':
11823                         case '#': {
11824                                 int cc = c;
11825                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11826                                 c = pgetc_eatbnl();
11827                                 if (c != cc)
11828                                         goto badsub;
11829                                 subtype++;
11830                                 break;
11831                         }
11832 #if ENABLE_ASH_BASH_COMPAT
11833                         case '/':
11834                                 /* ${v/[/]pattern/repl} */
11835 //TODO: encode pattern and repl separately.
11836 // Currently ${v/$var_with_slash/repl} is horribly broken
11837                                 subtype = VSREPLACE;
11838                                 c = pgetc_eatbnl();
11839                                 if (c != '/')
11840                                         goto badsub;
11841                                 subtype++; /* VSREPLACEALL */
11842                                 break;
11843 #endif
11844                         }
11845                 } else {
11846  badsub:
11847                         pungetc();
11848                 }
11849                 ((unsigned char *)stackblock())[typeloc] = subtype;
11850                 if (subtype != VSNORMAL) {
11851                         varnest++;
11852                         if (dblquote)
11853                                 dqvarnest++;
11854                 }
11855                 STPUTC('=', out);
11856         }
11857         goto parsesub_return;
11858 }
11859
11860 /*
11861  * Called to parse command substitutions.  Newstyle is set if the command
11862  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11863  * list of commands (passed by reference), and savelen is the number of
11864  * characters on the top of the stack which must be preserved.
11865  */
11866 parsebackq: {
11867         struct nodelist **nlpp;
11868         union node *n;
11869         char *str;
11870         size_t savelen;
11871         smallint saveprompt = 0;
11872
11873         str = NULL;
11874         savelen = out - (char *)stackblock();
11875         if (savelen > 0) {
11876                 /*
11877                  * FIXME: this can allocate very large block on stack and SEGV.
11878                  * Example:
11879                  * echo "..<100kbytes>..`true` $(true) `true` ..."
11880                  * allocates 100kb for every command subst. With about
11881                  * a hundred command substitutions stack overflows.
11882                  * With larger prepended string, SEGV happens sooner.
11883                  */
11884                 str = alloca(savelen);
11885                 memcpy(str, stackblock(), savelen);
11886         }
11887
11888         if (oldstyle) {
11889                 /* We must read until the closing backquote, giving special
11890                  * treatment to some slashes, and then push the string and
11891                  * reread it as input, interpreting it normally.
11892                  */
11893                 char *pout;
11894                 size_t psavelen;
11895                 char *pstr;
11896
11897                 STARTSTACKSTR(pout);
11898                 for (;;) {
11899                         int pc;
11900
11901                         setprompt_if(needprompt, 2);
11902                         pc = pgetc();
11903                         switch (pc) {
11904                         case '`':
11905                                 goto done;
11906
11907                         case '\\':
11908                                 pc = pgetc();
11909                                 if (pc == '\n') {
11910                                         nlprompt();
11911                                         /*
11912                                          * If eating a newline, avoid putting
11913                                          * the newline into the new character
11914                                          * stream (via the STPUTC after the
11915                                          * switch).
11916                                          */
11917                                         continue;
11918                                 }
11919                                 if (pc != '\\' && pc != '`' && pc != '$'
11920                                  && (!dblquote || pc != '"')
11921                                 ) {
11922                                         STPUTC('\\', pout);
11923                                 }
11924                                 if (pc <= 255 /* not PEOA or PEOF */) {
11925                                         break;
11926                                 }
11927                                 /* fall through */
11928
11929                         case PEOF:
11930                         IF_ASH_ALIAS(case PEOA:)
11931                                 startlinno = g_parsefile->linno;
11932                                 raise_error_syntax("EOF in backquote substitution");
11933
11934                         case '\n':
11935                                 nlnoprompt();
11936                                 break;
11937
11938                         default:
11939                                 break;
11940                         }
11941                         STPUTC(pc, pout);
11942                 }
11943  done:
11944                 STPUTC('\0', pout);
11945                 psavelen = pout - (char *)stackblock();
11946                 if (psavelen > 0) {
11947                         pstr = grabstackstr(pout);
11948                         setinputstring(pstr);
11949                 }
11950         }
11951         nlpp = &bqlist;
11952         while (*nlpp)
11953                 nlpp = &(*nlpp)->next;
11954         *nlpp = stzalloc(sizeof(**nlpp));
11955         /* (*nlpp)->next = NULL; - stzalloc did it */
11956
11957         if (oldstyle) {
11958                 saveprompt = doprompt;
11959                 doprompt = 0;
11960         }
11961
11962         n = list(2);
11963
11964         if (oldstyle)
11965                 doprompt = saveprompt;
11966         else if (readtoken() != TRP)
11967                 raise_error_unexpected_syntax(TRP);
11968
11969         (*nlpp)->n = n;
11970         if (oldstyle) {
11971                 /*
11972                  * Start reading from old file again, ignoring any pushed back
11973                  * tokens left from the backquote parsing
11974                  */
11975                 popfile();
11976                 tokpushback = 0;
11977         }
11978         while (stackblocksize() <= savelen)
11979                 growstackblock();
11980         STARTSTACKSTR(out);
11981         if (str) {
11982                 memcpy(out, str, savelen);
11983                 STADJUST(savelen, out);
11984         }
11985         USTPUTC(CTLBACKQ, out);
11986         if (oldstyle)
11987                 goto parsebackq_oldreturn;
11988         goto parsebackq_newreturn;
11989 }
11990
11991 #if ENABLE_SH_MATH_SUPPORT
11992 /*
11993  * Parse an arithmetic expansion (indicate start of one and set state)
11994  */
11995 parsearith: {
11996         if (++arinest == 1) {
11997                 prevsyntax = syntax;
11998                 syntax = ARISYNTAX;
11999         }
12000         USTPUTC(CTLARI, out);
12001         goto parsearith_return;
12002 }
12003 #endif
12004 } /* end of readtoken */
12005
12006 /*
12007  * Read the next input token.
12008  * If the token is a word, we set backquotelist to the list of cmds in
12009  *      backquotes.  We set quoteflag to true if any part of the word was
12010  *      quoted.
12011  * If the token is TREDIR, then we set redirnode to a structure containing
12012  *      the redirection.
12013  * In all cases, the variable startlinno is set to the number of the line
12014  *      on which the token starts.
12015  *
12016  * [Change comment:  here documents and internal procedures]
12017  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12018  *  word parsing code into a separate routine.  In this case, readtoken
12019  *  doesn't need to have any internal procedures, but parseword does.
12020  *  We could also make parseoperator in essence the main routine, and
12021  *  have parseword (readtoken1?) handle both words and redirection.]
12022  */
12023 #define NEW_xxreadtoken
12024 #ifdef NEW_xxreadtoken
12025 /* singles must be first! */
12026 static const char xxreadtoken_chars[7] ALIGN1 = {
12027         '\n', '(', ')', /* singles */
12028         '&', '|', ';',  /* doubles */
12029         0
12030 };
12031
12032 #define xxreadtoken_singles 3
12033 #define xxreadtoken_doubles 3
12034
12035 static const char xxreadtoken_tokens[] ALIGN1 = {
12036         TNL, TLP, TRP,          /* only single occurrence allowed */
12037         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12038         TEOF,                   /* corresponds to trailing nul */
12039         TAND, TOR, TENDCASE     /* if double occurrence */
12040 };
12041
12042 static int
12043 xxreadtoken(void)
12044 {
12045         int c;
12046
12047         if (tokpushback) {
12048                 tokpushback = 0;
12049                 return lasttoken;
12050         }
12051         setprompt_if(needprompt, 2);
12052         startlinno = g_parsefile->linno;
12053         for (;;) {                      /* until token or start of word found */
12054                 c = pgetc();
12055                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12056                         continue;
12057
12058                 if (c == '#') {
12059                         while ((c = pgetc()) != '\n' && c != PEOF)
12060                                 continue;
12061                         pungetc();
12062                 } else if (c == '\\') {
12063                         if (pgetc() != '\n') {
12064                                 pungetc();
12065                                 break; /* return readtoken1(...) */
12066                         }
12067                         nlprompt();
12068                 } else {
12069                         const char *p;
12070
12071                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12072                         if (c != PEOF) {
12073                                 if (c == '\n') {
12074                                         nlnoprompt();
12075                                 }
12076
12077                                 p = strchr(xxreadtoken_chars, c);
12078                                 if (p == NULL)
12079                                         break; /* return readtoken1(...) */
12080
12081                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12082                                         int cc = pgetc();
12083                                         if (cc == c) {    /* double occurrence? */
12084                                                 p += xxreadtoken_doubles + 1;
12085                                         } else {
12086                                                 pungetc();
12087 #if ENABLE_ASH_BASH_COMPAT
12088                                                 if (c == '&' && cc == '>') /* &> */
12089                                                         break; /* return readtoken1(...) */
12090 #endif
12091                                         }
12092                                 }
12093                         }
12094                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12095                         return lasttoken;
12096                 }
12097         } /* for (;;) */
12098
12099         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12100 }
12101 #else /* old xxreadtoken */
12102 #define RETURN(token)   return lasttoken = token
12103 static int
12104 xxreadtoken(void)
12105 {
12106         int c;
12107
12108         if (tokpushback) {
12109                 tokpushback = 0;
12110                 return lasttoken;
12111         }
12112         setprompt_if(needprompt, 2);
12113         startlinno = g_parsefile->linno;
12114         for (;;) {      /* until token or start of word found */
12115                 c = pgetc();
12116                 switch (c) {
12117                 case ' ': case '\t':
12118                 IF_ASH_ALIAS(case PEOA:)
12119                         continue;
12120                 case '#':
12121                         while ((c = pgetc()) != '\n' && c != PEOF)
12122                                 continue;
12123                         pungetc();
12124                         continue;
12125                 case '\\':
12126                         if (pgetc() == '\n') {
12127                                 nlprompt();
12128                                 continue;
12129                         }
12130                         pungetc();
12131                         goto breakloop;
12132                 case '\n':
12133                         nlnoprompt();
12134                         RETURN(TNL);
12135                 case PEOF:
12136                         RETURN(TEOF);
12137                 case '&':
12138                         if (pgetc() == '&')
12139                                 RETURN(TAND);
12140                         pungetc();
12141                         RETURN(TBACKGND);
12142                 case '|':
12143                         if (pgetc() == '|')
12144                                 RETURN(TOR);
12145                         pungetc();
12146                         RETURN(TPIPE);
12147                 case ';':
12148                         if (pgetc() == ';')
12149                                 RETURN(TENDCASE);
12150                         pungetc();
12151                         RETURN(TSEMI);
12152                 case '(':
12153                         RETURN(TLP);
12154                 case ')':
12155                         RETURN(TRP);
12156                 default:
12157                         goto breakloop;
12158                 }
12159         }
12160  breakloop:
12161         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12162 #undef RETURN
12163 }
12164 #endif /* old xxreadtoken */
12165
12166 static int
12167 readtoken(void)
12168 {
12169         int t;
12170         int kwd = checkkwd;
12171 #if DEBUG
12172         smallint alreadyseen = tokpushback;
12173 #endif
12174
12175 #if ENABLE_ASH_ALIAS
12176  top:
12177 #endif
12178
12179         t = xxreadtoken();
12180
12181         /*
12182          * eat newlines
12183          */
12184         if (kwd & CHKNL) {
12185                 while (t == TNL) {
12186                         parseheredoc();
12187                         t = xxreadtoken();
12188                 }
12189         }
12190
12191         if (t != TWORD || quoteflag) {
12192                 goto out;
12193         }
12194
12195         /*
12196          * check for keywords
12197          */
12198         if (kwd & CHKKWD) {
12199                 const char *const *pp;
12200
12201                 pp = findkwd(wordtext);
12202                 if (pp) {
12203                         lasttoken = t = pp - tokname_array;
12204                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12205                         goto out;
12206                 }
12207         }
12208
12209         if (checkkwd & CHKALIAS) {
12210 #if ENABLE_ASH_ALIAS
12211                 struct alias *ap;
12212                 ap = lookupalias(wordtext, 1);
12213                 if (ap != NULL) {
12214                         if (*ap->val) {
12215                                 pushstring(ap->val, ap);
12216                         }
12217                         goto top;
12218                 }
12219 #endif
12220         }
12221  out:
12222         checkkwd = 0;
12223 #if DEBUG
12224         if (!alreadyseen)
12225                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12226         else
12227                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12228 #endif
12229         return t;
12230 }
12231
12232 static int
12233 peektoken(void)
12234 {
12235         int t;
12236
12237         t = readtoken();
12238         tokpushback = 1;
12239         return t;
12240 }
12241
12242 /*
12243  * Read and parse a command.  Returns NODE_EOF on end of file.
12244  * (NULL is a valid parse tree indicating a blank line.)
12245  */
12246 static union node *
12247 parsecmd(int interact)
12248 {
12249         tokpushback = 0;
12250         checkkwd = 0;
12251         heredoclist = 0;
12252         doprompt = interact;
12253         setprompt_if(doprompt, doprompt);
12254         needprompt = 0;
12255         return list(1);
12256 }
12257
12258 /*
12259  * Input any here documents.
12260  */
12261 static void
12262 parseheredoc(void)
12263 {
12264         struct heredoc *here;
12265         union node *n;
12266
12267         here = heredoclist;
12268         heredoclist = NULL;
12269
12270         while (here) {
12271                 setprompt_if(needprompt, 2);
12272                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12273                                 here->eofmark, here->striptabs);
12274                 n = stzalloc(sizeof(struct narg));
12275                 n->narg.type = NARG;
12276                 /*n->narg.next = NULL; - stzalloc did it */
12277                 n->narg.text = wordtext;
12278                 n->narg.backquote = backquotelist;
12279                 here->here->nhere.doc = n;
12280                 here = here->next;
12281         }
12282 }
12283
12284
12285 /*
12286  * called by editline -- any expansions to the prompt should be added here.
12287  */
12288 #if ENABLE_ASH_EXPAND_PRMT
12289 static const char *
12290 expandstr(const char *ps)
12291 {
12292         union node n;
12293         int saveprompt;
12294
12295         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12296          * and token processing _can_ alter it (delete NULs etc). */
12297         setinputstring((char *)ps);
12298
12299         saveprompt = doprompt;
12300         doprompt = 0;
12301         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12302         doprompt = saveprompt;
12303
12304         popfile();
12305
12306         n.narg.type = NARG;
12307         n.narg.next = NULL;
12308         n.narg.text = wordtext;
12309         n.narg.backquote = backquotelist;
12310
12311         expandarg(&n, NULL, EXP_QUOTED);
12312         return stackblock();
12313 }
12314 #endif
12315
12316 /*
12317  * Execute a command or commands contained in a string.
12318  */
12319 static int
12320 evalstring(char *s, int flags)
12321 {
12322         struct jmploc *volatile savehandler;
12323         struct jmploc jmploc;
12324         int ex;
12325
12326         union node *n;
12327         struct stackmark smark;
12328         int status;
12329
12330         s = sstrdup(s);
12331         setinputstring(s);
12332         setstackmark(&smark);
12333
12334         status = 0;
12335         /* On exception inside execution loop, we must popfile().
12336          * Try interactively:
12337          *      readonly a=a
12338          *      command eval "a=b"  # throws "is read only" error
12339          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12340          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12341          */
12342         savehandler = exception_handler;
12343         ex = setjmp(jmploc.loc);
12344         if (ex)
12345                 goto out;
12346         exception_handler = &jmploc;
12347
12348         while ((n = parsecmd(0)) != NODE_EOF) {
12349                 int i;
12350
12351                 i = evaltree(n, flags);
12352                 if (n)
12353                         status = i;
12354                 popstackmark(&smark);
12355                 if (evalskip)
12356                         break;
12357         }
12358  out:
12359         popstackmark(&smark);
12360         popfile();
12361         stunalloc(s);
12362
12363         exception_handler = savehandler;
12364         if (ex)
12365                 longjmp(exception_handler->loc, ex);
12366
12367         return status;
12368 }
12369
12370 /*
12371  * The eval command.
12372  */
12373 static int FAST_FUNC
12374 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12375 {
12376         char *p;
12377         char *concat;
12378
12379         if (argv[1]) {
12380                 p = argv[1];
12381                 argv += 2;
12382                 if (argv[0]) {
12383                         STARTSTACKSTR(concat);
12384                         for (;;) {
12385                                 concat = stack_putstr(p, concat);
12386                                 p = *argv++;
12387                                 if (p == NULL)
12388                                         break;
12389                                 STPUTC(' ', concat);
12390                         }
12391                         STPUTC('\0', concat);
12392                         p = grabstackstr(concat);
12393                 }
12394                 return evalstring(p, flags & EV_TESTED);
12395         }
12396         return 0;
12397 }
12398
12399 /*
12400  * Read and execute commands.
12401  * "Top" is nonzero for the top level command loop;
12402  * it turns on prompting if the shell is interactive.
12403  */
12404 static int
12405 cmdloop(int top)
12406 {
12407         union node *n;
12408         struct stackmark smark;
12409         int inter;
12410         int status = 0;
12411         int numeof = 0;
12412
12413         TRACE(("cmdloop(%d) called\n", top));
12414         for (;;) {
12415                 int skip;
12416
12417                 setstackmark(&smark);
12418 #if JOBS
12419                 if (doing_jobctl)
12420                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12421 #endif
12422                 inter = 0;
12423                 if (iflag && top) {
12424                         inter++;
12425                         chkmail();
12426                 }
12427                 n = parsecmd(inter);
12428 #if DEBUG
12429                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12430                         showtree(n);
12431 #endif
12432                 if (n == NODE_EOF) {
12433                         if (!top || numeof >= 50)
12434                                 break;
12435                         if (!stoppedjobs()) {
12436                                 if (!Iflag)
12437                                         break;
12438                                 out2str("\nUse \"exit\" to leave shell.\n");
12439                         }
12440                         numeof++;
12441                 } else if (nflag == 0) {
12442                         int i;
12443
12444                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12445                         job_warning >>= 1;
12446                         numeof = 0;
12447                         i = evaltree(n, 0);
12448                         if (n)
12449                                 status = i;
12450                 }
12451                 popstackmark(&smark);
12452                 skip = evalskip;
12453
12454                 if (skip) {
12455                         evalskip &= ~SKIPFUNC;
12456                         break;
12457                 }
12458         }
12459         return status;
12460 }
12461
12462 /*
12463  * Take commands from a file.  To be compatible we should do a path
12464  * search for the file, which is necessary to find sub-commands.
12465  */
12466 static char *
12467 find_dot_file(char *name)
12468 {
12469         char *fullname;
12470         const char *path = pathval();
12471         struct stat statb;
12472
12473         /* don't try this for absolute or relative paths */
12474         if (strchr(name, '/'))
12475                 return name;
12476
12477         /* IIRC standards do not say whether . is to be searched.
12478          * And it is even smaller this way, making it unconditional for now:
12479          */
12480         if (1) { /* ENABLE_ASH_BASH_COMPAT */
12481                 fullname = name;
12482                 goto try_cur_dir;
12483         }
12484
12485         while ((fullname = path_advance(&path, name)) != NULL) {
12486  try_cur_dir:
12487                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12488                         /*
12489                          * Don't bother freeing here, since it will
12490                          * be freed by the caller.
12491                          */
12492                         return fullname;
12493                 }
12494                 if (fullname != name)
12495                         stunalloc(fullname);
12496         }
12497
12498         /* not found in the PATH */
12499         ash_msg_and_raise_error("%s: not found", name);
12500         /* NOTREACHED */
12501 }
12502
12503 static int FAST_FUNC
12504 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12505 {
12506         /* "false; . empty_file; echo $?" should print 0, not 1: */
12507         int status = 0;
12508         char *fullname;
12509         char **argv;
12510         struct strlist *sp;
12511         volatile struct shparam saveparam;
12512
12513         for (sp = cmdenviron; sp; sp = sp->next)
12514                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12515
12516         nextopt(nullstr); /* handle possible "--" */
12517         argv = argptr;
12518
12519         if (!argv[0]) {
12520                 /* bash says: "bash: .: filename argument required" */
12521                 return 2; /* bash compat */
12522         }
12523
12524         /* This aborts if file isn't found, which is POSIXly correct.
12525          * bash returns exitcode 1 instead.
12526          */
12527         fullname = find_dot_file(argv[0]);
12528         argv++;
12529         if (argv[0]) { /* . FILE ARGS, ARGS exist */
12530                 int argc;
12531                 saveparam = shellparam;
12532                 shellparam.malloced = 0;
12533                 argc = 1;
12534                 while (argv[argc])
12535                         argc++;
12536                 shellparam.nparam = argc;
12537                 shellparam.p = argv;
12538         };
12539
12540         /* This aborts if file can't be opened, which is POSIXly correct.
12541          * bash returns exitcode 1 instead.
12542          */
12543         setinputfile(fullname, INPUT_PUSH_FILE);
12544         commandname = fullname;
12545         status = cmdloop(0);
12546         popfile();
12547
12548         if (argv[0]) {
12549                 freeparam(&shellparam);
12550                 shellparam = saveparam;
12551         };
12552
12553         return status;
12554 }
12555
12556 static int FAST_FUNC
12557 exitcmd(int argc UNUSED_PARAM, char **argv)
12558 {
12559         if (stoppedjobs())
12560                 return 0;
12561         if (argv[1])
12562                 exitstatus = number(argv[1]);
12563         raise_exception(EXEXIT);
12564         /* NOTREACHED */
12565 }
12566
12567 /*
12568  * Read a file containing shell functions.
12569  */
12570 static void
12571 readcmdfile(char *name)
12572 {
12573         setinputfile(name, INPUT_PUSH_FILE);
12574         cmdloop(0);
12575         popfile();
12576 }
12577
12578
12579 /* ============ find_command inplementation */
12580
12581 /*
12582  * Resolve a command name.  If you change this routine, you may have to
12583  * change the shellexec routine as well.
12584  */
12585 static void
12586 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12587 {
12588         struct tblentry *cmdp;
12589         int idx;
12590         int prev;
12591         char *fullname;
12592         struct stat statb;
12593         int e;
12594         int updatetbl;
12595         struct builtincmd *bcmd;
12596
12597         /* If name contains a slash, don't use PATH or hash table */
12598         if (strchr(name, '/') != NULL) {
12599                 entry->u.index = -1;
12600                 if (act & DO_ABS) {
12601                         while (stat(name, &statb) < 0) {
12602 #ifdef SYSV
12603                                 if (errno == EINTR)
12604                                         continue;
12605 #endif
12606                                 entry->cmdtype = CMDUNKNOWN;
12607                                 return;
12608                         }
12609                 }
12610                 entry->cmdtype = CMDNORMAL;
12611                 return;
12612         }
12613
12614 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12615
12616         updatetbl = (path == pathval());
12617         if (!updatetbl) {
12618                 act |= DO_ALTPATH;
12619                 if (strstr(path, "%builtin") != NULL)
12620                         act |= DO_ALTBLTIN;
12621         }
12622
12623         /* If name is in the table, check answer will be ok */
12624         cmdp = cmdlookup(name, 0);
12625         if (cmdp != NULL) {
12626                 int bit;
12627
12628                 switch (cmdp->cmdtype) {
12629                 default:
12630 #if DEBUG
12631                         abort();
12632 #endif
12633                 case CMDNORMAL:
12634                         bit = DO_ALTPATH;
12635                         break;
12636                 case CMDFUNCTION:
12637                         bit = DO_NOFUNC;
12638                         break;
12639                 case CMDBUILTIN:
12640                         bit = DO_ALTBLTIN;
12641                         break;
12642                 }
12643                 if (act & bit) {
12644                         updatetbl = 0;
12645                         cmdp = NULL;
12646                 } else if (cmdp->rehash == 0)
12647                         /* if not invalidated by cd, we're done */
12648                         goto success;
12649         }
12650
12651         /* If %builtin not in path, check for builtin next */
12652         bcmd = find_builtin(name);
12653         if (bcmd) {
12654                 if (IS_BUILTIN_REGULAR(bcmd))
12655                         goto builtin_success;
12656                 if (act & DO_ALTPATH) {
12657                         if (!(act & DO_ALTBLTIN))
12658                                 goto builtin_success;
12659                 } else if (builtinloc <= 0) {
12660                         goto builtin_success;
12661                 }
12662         }
12663
12664 #if ENABLE_FEATURE_SH_STANDALONE
12665         {
12666                 int applet_no = find_applet_by_name(name);
12667                 if (applet_no >= 0) {
12668                         entry->cmdtype = CMDNORMAL;
12669                         entry->u.index = -2 - applet_no;
12670                         return;
12671                 }
12672         }
12673 #endif
12674
12675         /* We have to search path. */
12676         prev = -1;              /* where to start */
12677         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12678                 if (cmdp->cmdtype == CMDBUILTIN)
12679                         prev = builtinloc;
12680                 else
12681                         prev = cmdp->param.index;
12682         }
12683
12684         e = ENOENT;
12685         idx = -1;
12686  loop:
12687         while ((fullname = path_advance(&path, name)) != NULL) {
12688                 stunalloc(fullname);
12689                 /* NB: code below will still use fullname
12690                  * despite it being "unallocated" */
12691                 idx++;
12692                 if (pathopt) {
12693                         if (prefix(pathopt, "builtin")) {
12694                                 if (bcmd)
12695                                         goto builtin_success;
12696                                 continue;
12697                         }
12698                         if ((act & DO_NOFUNC)
12699                          || !prefix(pathopt, "func")
12700                         ) {     /* ignore unimplemented options */
12701                                 continue;
12702                         }
12703                 }
12704                 /* if rehash, don't redo absolute path names */
12705                 if (fullname[0] == '/' && idx <= prev) {
12706                         if (idx < prev)
12707                                 continue;
12708                         TRACE(("searchexec \"%s\": no change\n", name));
12709                         goto success;
12710                 }
12711                 while (stat(fullname, &statb) < 0) {
12712 #ifdef SYSV
12713                         if (errno == EINTR)
12714                                 continue;
12715 #endif
12716                         if (errno != ENOENT && errno != ENOTDIR)
12717                                 e = errno;
12718                         goto loop;
12719                 }
12720                 e = EACCES;     /* if we fail, this will be the error */
12721                 if (!S_ISREG(statb.st_mode))
12722                         continue;
12723                 if (pathopt) {          /* this is a %func directory */
12724                         stalloc(strlen(fullname) + 1);
12725                         /* NB: stalloc will return space pointed by fullname
12726                          * (because we don't have any intervening allocations
12727                          * between stunalloc above and this stalloc) */
12728                         readcmdfile(fullname);
12729                         cmdp = cmdlookup(name, 0);
12730                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12731                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12732                         stunalloc(fullname);
12733                         goto success;
12734                 }
12735                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12736                 if (!updatetbl) {
12737                         entry->cmdtype = CMDNORMAL;
12738                         entry->u.index = idx;
12739                         return;
12740                 }
12741                 INT_OFF;
12742                 cmdp = cmdlookup(name, 1);
12743                 cmdp->cmdtype = CMDNORMAL;
12744                 cmdp->param.index = idx;
12745                 INT_ON;
12746                 goto success;
12747         }
12748
12749         /* We failed.  If there was an entry for this command, delete it */
12750         if (cmdp && updatetbl)
12751                 delete_cmd_entry();
12752         if (act & DO_ERR)
12753                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12754         entry->cmdtype = CMDUNKNOWN;
12755         return;
12756
12757  builtin_success:
12758         if (!updatetbl) {
12759                 entry->cmdtype = CMDBUILTIN;
12760                 entry->u.cmd = bcmd;
12761                 return;
12762         }
12763         INT_OFF;
12764         cmdp = cmdlookup(name, 1);
12765         cmdp->cmdtype = CMDBUILTIN;
12766         cmdp->param.cmd = bcmd;
12767         INT_ON;
12768  success:
12769         cmdp->rehash = 0;
12770         entry->cmdtype = cmdp->cmdtype;
12771         entry->u = cmdp->param;
12772 }
12773
12774
12775 /*
12776  * The trap builtin.
12777  */
12778 static int FAST_FUNC
12779 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12780 {
12781         char *action;
12782         char **ap;
12783         int signo, exitcode;
12784
12785         nextopt(nullstr);
12786         ap = argptr;
12787         if (!*ap) {
12788                 for (signo = 0; signo < NSIG; signo++) {
12789                         char *tr = trap_ptr[signo];
12790                         if (tr) {
12791                                 /* note: bash adds "SIG", but only if invoked
12792                                  * as "bash". If called as "sh", or if set -o posix,
12793                                  * then it prints short signal names.
12794                                  * We are printing short names: */
12795                                 out1fmt("trap -- %s %s\n",
12796                                                 single_quote(tr),
12797                                                 get_signame(signo));
12798                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12799                  * In this case, we will exit very soon, no need to free(). */
12800                                 /* if (trap_ptr != trap && tp[0]) */
12801                                 /*      free(tr); */
12802                         }
12803                 }
12804                 /*
12805                 if (trap_ptr != trap) {
12806                         free(trap_ptr);
12807                         trap_ptr = trap;
12808                 }
12809                 */
12810                 return 0;
12811         }
12812
12813         action = NULL;
12814         if (ap[1])
12815                 action = *ap++;
12816         exitcode = 0;
12817         while (*ap) {
12818                 signo = get_signum(*ap);
12819                 if (signo < 0) {
12820                         /* Mimic bash message exactly */
12821                         ash_msg("%s: invalid signal specification", *ap);
12822                         exitcode = 1;
12823                         goto next;
12824                 }
12825                 INT_OFF;
12826                 if (action) {
12827                         if (LONE_DASH(action))
12828                                 action = NULL;
12829                         else {
12830                                 if (action[0]) /* not NULL and not "" and not "-" */
12831                                         may_have_traps = 1;
12832                                 action = ckstrdup(action);
12833                         }
12834                 }
12835                 free(trap[signo]);
12836                 trap[signo] = action;
12837                 if (signo != 0)
12838                         setsignal(signo);
12839                 INT_ON;
12840  next:
12841                 ap++;
12842         }
12843         return exitcode;
12844 }
12845
12846
12847 /* ============ Builtins */
12848
12849 #if ENABLE_ASH_HELP
12850 static int FAST_FUNC
12851 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12852 {
12853         unsigned col;
12854         unsigned i;
12855
12856         out1fmt(
12857                 "Built-in commands:\n"
12858                 "------------------\n");
12859         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12860                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12861                                         builtintab[i].name + 1);
12862                 if (col > 60) {
12863                         out1fmt("\n");
12864                         col = 0;
12865                 }
12866         }
12867 # if ENABLE_FEATURE_SH_STANDALONE
12868         {
12869                 const char *a = applet_names;
12870                 while (*a) {
12871                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12872                         if (col > 60) {
12873                                 out1fmt("\n");
12874                                 col = 0;
12875                         }
12876                         while (*a++ != '\0')
12877                                 continue;
12878                 }
12879         }
12880 # endif
12881         newline_and_flush(stdout);
12882         return EXIT_SUCCESS;
12883 }
12884 #endif
12885
12886 #if MAX_HISTORY
12887 static int FAST_FUNC
12888 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12889 {
12890         show_history(line_input_state);
12891         return EXIT_SUCCESS;
12892 }
12893 #endif
12894
12895 /*
12896  * The export and readonly commands.
12897  */
12898 static int FAST_FUNC
12899 exportcmd(int argc UNUSED_PARAM, char **argv)
12900 {
12901         struct var *vp;
12902         char *name;
12903         const char *p;
12904         char **aptr;
12905         char opt;
12906         int flag;
12907         int flag_off;
12908
12909         /* "readonly" in bash accepts, but ignores -n.
12910          * We do the same: it saves a conditional in nextopt's param.
12911          */
12912         flag_off = 0;
12913         while ((opt = nextopt("np")) != '\0') {
12914                 if (opt == 'n')
12915                         flag_off = VEXPORT;
12916         }
12917         flag = VEXPORT;
12918         if (argv[0][0] == 'r') {
12919                 flag = VREADONLY;
12920                 flag_off = 0; /* readonly ignores -n */
12921         }
12922         flag_off = ~flag_off;
12923
12924         /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
12925         {
12926                 aptr = argptr;
12927                 name = *aptr;
12928                 if (name) {
12929                         do {
12930                                 p = strchr(name, '=');
12931                                 if (p != NULL) {
12932                                         p++;
12933                                 } else {
12934                                         vp = *findvar(hashvar(name), name);
12935                                         if (vp) {
12936                                                 vp->flags = ((vp->flags | flag) & flag_off);
12937                                                 continue;
12938                                         }
12939                                 }
12940                                 setvar(name, p, (flag & flag_off));
12941                         } while ((name = *++aptr) != NULL);
12942                         return 0;
12943                 }
12944         }
12945
12946         /* No arguments. Show the list of exported or readonly vars.
12947          * -n is ignored.
12948          */
12949         showvars(argv[0], flag, 0);
12950         return 0;
12951 }
12952
12953 /*
12954  * Delete a function if it exists.
12955  */
12956 static void
12957 unsetfunc(const char *name)
12958 {
12959         struct tblentry *cmdp;
12960
12961         cmdp = cmdlookup(name, 0);
12962         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
12963                 delete_cmd_entry();
12964 }
12965
12966 /*
12967  * The unset builtin command.  We unset the function before we unset the
12968  * variable to allow a function to be unset when there is a readonly variable
12969  * with the same name.
12970  */
12971 static int FAST_FUNC
12972 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12973 {
12974         char **ap;
12975         int i;
12976         int flag = 0;
12977         int ret = 0;
12978
12979         while ((i = nextopt("vf")) != 0) {
12980                 flag = i;
12981         }
12982
12983         for (ap = argptr; *ap; ap++) {
12984                 if (flag != 'f') {
12985                         i = unsetvar(*ap);
12986                         ret |= i;
12987                         if (!(i & 2))
12988                                 continue;
12989                 }
12990                 if (flag != 'v')
12991                         unsetfunc(*ap);
12992         }
12993         return ret & 1;
12994 }
12995
12996 static const unsigned char timescmd_str[] ALIGN1 = {
12997         ' ',  offsetof(struct tms, tms_utime),
12998         '\n', offsetof(struct tms, tms_stime),
12999         ' ',  offsetof(struct tms, tms_cutime),
13000         '\n', offsetof(struct tms, tms_cstime),
13001         0
13002 };
13003 static int FAST_FUNC
13004 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13005 {
13006         unsigned long clk_tck, s, t;
13007         const unsigned char *p;
13008         struct tms buf;
13009
13010         clk_tck = bb_clk_tck();
13011         times(&buf);
13012
13013         p = timescmd_str;
13014         do {
13015                 t = *(clock_t *)(((char *) &buf) + p[1]);
13016                 s = t / clk_tck;
13017                 t = t % clk_tck;
13018                 out1fmt("%lum%lu.%03lus%c",
13019                         s / 60, s % 60,
13020                         (t * 1000) / clk_tck,
13021                         p[0]);
13022                 p += 2;
13023         } while (*p);
13024
13025         return 0;
13026 }
13027
13028 #if ENABLE_SH_MATH_SUPPORT
13029 /*
13030  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13031  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13032  *
13033  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13034  */
13035 static int FAST_FUNC
13036 letcmd(int argc UNUSED_PARAM, char **argv)
13037 {
13038         arith_t i;
13039
13040         argv++;
13041         if (!*argv)
13042                 ash_msg_and_raise_error("expression expected");
13043         do {
13044                 i = ash_arith(*argv);
13045         } while (*++argv);
13046
13047         return !i;
13048 }
13049 #endif
13050
13051 /*
13052  * The read builtin. Options:
13053  *      -r              Do not interpret '\' specially
13054  *      -s              Turn off echo (tty only)
13055  *      -n NCHARS       Read NCHARS max
13056  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13057  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13058  *      -u FD           Read from given FD instead of fd 0
13059  * This uses unbuffered input, which may be avoidable in some cases.
13060  * TODO: bash also has:
13061  *      -a ARRAY        Read into array[0],[1],etc
13062  *      -d DELIM        End on DELIM char, not newline
13063  *      -e              Use line editing (tty only)
13064  */
13065 static int FAST_FUNC
13066 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13067 {
13068         char *opt_n = NULL;
13069         char *opt_p = NULL;
13070         char *opt_t = NULL;
13071         char *opt_u = NULL;
13072         int read_flags = 0;
13073         const char *r;
13074         int i;
13075
13076         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13077                 switch (i) {
13078                 case 'p':
13079                         opt_p = optionarg;
13080                         break;
13081                 case 'n':
13082                         opt_n = optionarg;
13083                         break;
13084                 case 's':
13085                         read_flags |= BUILTIN_READ_SILENT;
13086                         break;
13087                 case 't':
13088                         opt_t = optionarg;
13089                         break;
13090                 case 'r':
13091                         read_flags |= BUILTIN_READ_RAW;
13092                         break;
13093                 case 'u':
13094                         opt_u = optionarg;
13095                         break;
13096                 default:
13097                         break;
13098                 }
13099         }
13100
13101         /* "read -s" needs to save/restore termios, can't allow ^C
13102          * to jump out of it.
13103          */
13104         INT_OFF;
13105         r = shell_builtin_read(setvar0,
13106                 argptr,
13107                 bltinlookup("IFS"), /* can be NULL */
13108                 read_flags,
13109                 opt_n,
13110                 opt_p,
13111                 opt_t,
13112                 opt_u
13113         );
13114         INT_ON;
13115
13116         if ((uintptr_t)r > 1)
13117                 ash_msg_and_raise_error(r);
13118
13119         return (uintptr_t)r;
13120 }
13121
13122 static int FAST_FUNC
13123 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13124 {
13125         static const char permuser[3] ALIGN1 = "ogu";
13126
13127         mode_t mask;
13128         int symbolic_mode = 0;
13129
13130         while (nextopt("S") != '\0') {
13131                 symbolic_mode = 1;
13132         }
13133
13134         INT_OFF;
13135         mask = umask(0);
13136         umask(mask);
13137         INT_ON;
13138
13139         if (*argptr == NULL) {
13140                 if (symbolic_mode) {
13141                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13142                         char *p = buf;
13143                         int i;
13144
13145                         i = 2;
13146                         for (;;) {
13147                                 *p++ = ',';
13148                                 *p++ = permuser[i];
13149                                 *p++ = '=';
13150                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13151                                 if (!(mask & 0400)) *p++ = 'r';
13152                                 if (!(mask & 0200)) *p++ = 'w';
13153                                 if (!(mask & 0100)) *p++ = 'x';
13154                                 mask <<= 3;
13155                                 if (--i < 0)
13156                                         break;
13157                         }
13158                         *p = '\0';
13159                         puts(buf + 1);
13160                 } else {
13161                         out1fmt("%04o\n", mask);
13162                 }
13163         } else {
13164                 char *modestr = *argptr;
13165                 /* numeric umasks are taken as-is */
13166                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13167                 if (!isdigit(modestr[0]))
13168                         mask ^= 0777;
13169                 mask = bb_parse_mode(modestr, mask);
13170                 if ((unsigned)mask > 0777) {
13171                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13172                 }
13173                 if (!isdigit(modestr[0]))
13174                         mask ^= 0777;
13175                 umask(mask);
13176         }
13177         return 0;
13178 }
13179
13180 static int FAST_FUNC
13181 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13182 {
13183         return shell_builtin_ulimit(argv);
13184 }
13185
13186 /* ============ main() and helpers */
13187
13188 /*
13189  * Called to exit the shell.
13190  */
13191 static void
13192 exitshell(void)
13193 {
13194         struct jmploc loc;
13195         char *p;
13196         int status;
13197
13198 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13199         save_history(line_input_state);
13200 #endif
13201         status = exitstatus;
13202         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13203         if (setjmp(loc.loc)) {
13204                 if (exception_type == EXEXIT)
13205                         status = exitstatus;
13206                 goto out;
13207         }
13208         exception_handler = &loc;
13209         p = trap[0];
13210         if (p) {
13211                 trap[0] = NULL;
13212                 evalskip = 0;
13213                 evalstring(p, 0);
13214                 /*free(p); - we'll exit soon */
13215         }
13216  out:
13217         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13218          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13219          */
13220         setjobctl(0);
13221         flush_stdout_stderr();
13222         _exit(status);
13223         /* NOTREACHED */
13224 }
13225
13226 static void
13227 init(void)
13228 {
13229         /* we will never free this */
13230         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13231
13232         sigmode[SIGCHLD - 1] = S_DFL;
13233         setsignal(SIGCHLD);
13234
13235         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13236          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13237          */
13238         signal(SIGHUP, SIG_DFL);
13239
13240         {
13241                 char **envp;
13242                 const char *p;
13243                 struct stat st1, st2;
13244
13245                 initvar();
13246                 for (envp = environ; envp && *envp; envp++) {
13247                         p = endofname(*envp);
13248                         if (p != *envp && *p == '=') {
13249                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13250                         }
13251                 }
13252
13253                 setvareq((char*)defoptindvar, VTEXTFIXED);
13254
13255                 setvar0("PPID", utoa(getppid()));
13256 #if ENABLE_ASH_BASH_COMPAT
13257                 p = lookupvar("SHLVL");
13258                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13259                 if (!lookupvar("HOSTNAME")) {
13260                         struct utsname uts;
13261                         uname(&uts);
13262                         setvar0("HOSTNAME", uts.nodename);
13263                 }
13264 #endif
13265                 p = lookupvar("PWD");
13266                 if (p) {
13267                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13268                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13269                         ) {
13270                                 p = NULL;
13271                         }
13272                 }
13273                 setpwd(p, 0);
13274         }
13275 }
13276
13277
13278 //usage:#define ash_trivial_usage
13279 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13280 //usage:#define ash_full_usage "\n\n"
13281 //usage:        "Unix shell interpreter"
13282
13283 //usage:#if ENABLE_FEATURE_SH_IS_ASH
13284 //usage:# define sh_trivial_usage ash_trivial_usage
13285 //usage:# define sh_full_usage    ash_full_usage
13286 //usage:#endif
13287 //usage:#if ENABLE_FEATURE_BASH_IS_ASH
13288 //usage:# define bash_trivial_usage ash_trivial_usage
13289 //usage:# define bash_full_usage    ash_full_usage
13290 //usage:#endif
13291
13292 /*
13293  * Process the shell command line arguments.
13294  */
13295 static void
13296 procargs(char **argv)
13297 {
13298         int i;
13299         const char *xminusc;
13300         char **xargv;
13301
13302         xargv = argv;
13303         arg0 = xargv[0];
13304         /* if (xargv[0]) - mmm, this is always true! */
13305                 xargv++;
13306         for (i = 0; i < NOPTS; i++)
13307                 optlist[i] = 2;
13308         argptr = xargv;
13309         if (options(/*cmdline:*/ 1)) {
13310                 /* it already printed err message */
13311                 raise_exception(EXERROR);
13312         }
13313         xargv = argptr;
13314         xminusc = minusc;
13315         if (*xargv == NULL) {
13316                 if (xminusc)
13317                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13318                 sflag = 1;
13319         }
13320         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13321                 iflag = 1;
13322         if (mflag == 2)
13323                 mflag = iflag;
13324         for (i = 0; i < NOPTS; i++)
13325                 if (optlist[i] == 2)
13326                         optlist[i] = 0;
13327 #if DEBUG == 2
13328         debug = 1;
13329 #endif
13330         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13331         if (xminusc) {
13332                 minusc = *xargv++;
13333                 if (*xargv)
13334                         goto setarg0;
13335         } else if (!sflag) {
13336                 setinputfile(*xargv, 0);
13337  setarg0:
13338                 arg0 = *xargv++;
13339                 commandname = arg0;
13340         }
13341
13342         shellparam.p = xargv;
13343 #if ENABLE_ASH_GETOPTS
13344         shellparam.optind = 1;
13345         shellparam.optoff = -1;
13346 #endif
13347         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13348         while (*xargv) {
13349                 shellparam.nparam++;
13350                 xargv++;
13351         }
13352         optschanged();
13353 }
13354
13355 /*
13356  * Read /etc/profile, ~/.profile, $ENV.
13357  */
13358 static void
13359 read_profile(const char *name)
13360 {
13361         name = expandstr(name);
13362         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13363                 return;
13364         cmdloop(0);
13365         popfile();
13366 }
13367
13368 /*
13369  * This routine is called when an error or an interrupt occurs in an
13370  * interactive shell and control is returned to the main command loop.
13371  * (In dash, this function is auto-generated by build machinery).
13372  */
13373 static void
13374 reset(void)
13375 {
13376         /* from eval.c: */
13377         evalskip = 0;
13378         loopnest = 0;
13379
13380         /* from expand.c: */
13381         ifsfree();
13382
13383         /* from input.c: */
13384         g_parsefile->left_in_buffer = 0;
13385         g_parsefile->left_in_line = 0;      /* clear input buffer */
13386         popallfiles();
13387
13388         /* from redir.c: */
13389         while (redirlist)
13390                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13391 }
13392
13393 #if PROFILE
13394 static short profile_buf[16384];
13395 extern int etext();
13396 #endif
13397
13398 /*
13399  * Main routine.  We initialize things, parse the arguments, execute
13400  * profiles if we're a login shell, and then call cmdloop to execute
13401  * commands.  The setjmp call sets up the location to jump to when an
13402  * exception occurs.  When an exception occurs the variable "state"
13403  * is used to figure out how far we had gotten.
13404  */
13405 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13406 int ash_main(int argc UNUSED_PARAM, char **argv)
13407 {
13408         volatile smallint state;
13409         struct jmploc jmploc;
13410         struct stackmark smark;
13411
13412         /* Initialize global data */
13413         INIT_G_misc();
13414         INIT_G_memstack();
13415         INIT_G_var();
13416 #if ENABLE_ASH_ALIAS
13417         INIT_G_alias();
13418 #endif
13419         INIT_G_cmdtable();
13420
13421 #if PROFILE
13422         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13423 #endif
13424
13425 #if ENABLE_FEATURE_EDITING
13426         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13427 #endif
13428         state = 0;
13429         if (setjmp(jmploc.loc)) {
13430                 smallint e;
13431                 smallint s;
13432
13433                 reset();
13434
13435                 e = exception_type;
13436                 s = state;
13437                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13438                         exitshell();
13439                 }
13440                 if (e == EXINT) {
13441                         newline_and_flush(stderr);
13442                 }
13443
13444                 popstackmark(&smark);
13445                 FORCE_INT_ON; /* enable interrupts */
13446                 if (s == 1)
13447                         goto state1;
13448                 if (s == 2)
13449                         goto state2;
13450                 if (s == 3)
13451                         goto state3;
13452                 goto state4;
13453         }
13454         exception_handler = &jmploc;
13455         rootpid = getpid();
13456
13457         init();
13458         setstackmark(&smark);
13459         procargs(argv);
13460 #if DEBUG
13461         TRACE(("Shell args: "));
13462         trace_puts_args(argv);
13463 #endif
13464
13465         if (argv[0] && argv[0][0] == '-')
13466                 isloginsh = 1;
13467         if (isloginsh) {
13468                 const char *hp;
13469
13470                 state = 1;
13471                 read_profile("/etc/profile");
13472  state1:
13473                 state = 2;
13474                 hp = lookupvar("HOME");
13475                 if (hp)
13476                         read_profile("$HOME/.profile");
13477         }
13478  state2:
13479         state = 3;
13480         if (
13481 #ifndef linux
13482          getuid() == geteuid() && getgid() == getegid() &&
13483 #endif
13484          iflag
13485         ) {
13486                 const char *shinit = lookupvar("ENV");
13487                 if (shinit != NULL && *shinit != '\0')
13488                         read_profile(shinit);
13489         }
13490         popstackmark(&smark);
13491  state3:
13492         state = 4;
13493         if (minusc) {
13494                 /* evalstring pushes parsefile stack.
13495                  * Ensure we don't falsely claim that 0 (stdin)
13496                  * is one of stacked source fds.
13497                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13498                 // if (!sflag) g_parsefile->pf_fd = -1;
13499                 // ^^ not necessary since now we special-case fd 0
13500                 // in is_hidden_fd() to not be considered "hidden fd"
13501                 evalstring(minusc, 0);
13502         }
13503
13504         if (sflag || minusc == NULL) {
13505 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13506                 if (iflag) {
13507                         const char *hp = lookupvar("HISTFILE");
13508                         if (!hp) {
13509                                 hp = lookupvar("HOME");
13510                                 if (hp) {
13511                                         hp = concat_path_file(hp, ".ash_history");
13512                                         setvar0("HISTFILE", hp);
13513                                         free((char*)hp);
13514                                         hp = lookupvar("HISTFILE");
13515                                 }
13516                         }
13517                         if (hp)
13518                                 line_input_state->hist_file = hp;
13519 # if ENABLE_FEATURE_SH_HISTFILESIZE
13520                         hp = lookupvar("HISTFILESIZE");
13521                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13522 # endif
13523                 }
13524 #endif
13525  state4: /* XXX ??? - why isn't this before the "if" statement */
13526                 cmdloop(1);
13527         }
13528 #if PROFILE
13529         monitor(0);
13530 #endif
13531 #ifdef GPROF
13532         {
13533                 extern void _mcleanup(void);
13534                 _mcleanup();
13535         }
13536 #endif
13537         TRACE(("End of main reached\n"));
13538         exitshell();
13539         /* NOTREACHED */
13540 }
13541
13542
13543 /*-
13544  * Copyright (c) 1989, 1991, 1993, 1994
13545  *      The Regents of the University of California.  All rights reserved.
13546  *
13547  * This code is derived from software contributed to Berkeley by
13548  * Kenneth Almquist.
13549  *
13550  * Redistribution and use in source and binary forms, with or without
13551  * modification, are permitted provided that the following conditions
13552  * are met:
13553  * 1. Redistributions of source code must retain the above copyright
13554  *    notice, this list of conditions and the following disclaimer.
13555  * 2. Redistributions in binary form must reproduce the above copyright
13556  *    notice, this list of conditions and the following disclaimer in the
13557  *    documentation and/or other materials provided with the distribution.
13558  * 3. Neither the name of the University nor the names of its contributors
13559  *    may be used to endorse or promote products derived from this software
13560  *    without specific prior written permission.
13561  *
13562  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13563  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13564  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13565  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13566  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13567  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13568  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13569  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13570  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13571  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13572  * SUCH DAMAGE.
13573  */