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