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