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