ash: move ifsbreakup() and ifsfree() up
[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 WNOHANG
3516 #define DOWAIT_BLOCK    0
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 wait_flags, struct job *job)
3939 {
3940         int pid;
3941         int status;
3942         struct job *jp;
3943         struct job *thisjob;
3944
3945         TRACE(("dowait(0x%x) called\n", wait_flags));
3946
3947         /* Do a wait system call. If job control is compiled in, we accept
3948          * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3949          * NB: _not_ safe_waitpid, we need to detect EINTR */
3950         if (doing_jobctl)
3951                 wait_flags |= WUNTRACED;
3952         pid = waitpid(-1, &status, wait_flags);
3953         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
3954                                 pid, status, errno, strerror(errno)));
3955         if (pid <= 0)
3956                 return pid;
3957
3958         INT_OFF;
3959         thisjob = NULL;
3960         for (jp = curjob; jp; jp = jp->prev_job) {
3961                 int jobstate;
3962                 struct procstat *ps;
3963                 struct procstat *psend;
3964                 if (jp->state == JOBDONE)
3965                         continue;
3966                 jobstate = JOBDONE;
3967                 ps = jp->ps;
3968                 psend = ps + jp->nprocs;
3969                 do {
3970                         if (ps->ps_pid == pid) {
3971                                 TRACE(("Job %d: changing status of proc %d "
3972                                         "from 0x%x to 0x%x\n",
3973                                         jobno(jp), pid, ps->ps_status, status));
3974                                 ps->ps_status = status;
3975                                 thisjob = jp;
3976                         }
3977                         if (ps->ps_status == -1)
3978                                 jobstate = JOBRUNNING;
3979 #if JOBS
3980                         if (jobstate == JOBRUNNING)
3981                                 continue;
3982                         if (WIFSTOPPED(ps->ps_status)) {
3983                                 jp->stopstatus = ps->ps_status;
3984                                 jobstate = JOBSTOPPED;
3985                         }
3986 #endif
3987                 } while (++ps < psend);
3988                 if (!thisjob)
3989                         continue;
3990
3991                 /* Found the job where one of its processes changed its state.
3992                  * Is there at least one live and running process in this job? */
3993                 if (jobstate != JOBRUNNING) {
3994                         /* No. All live processes in the job are stopped
3995                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
3996                          */
3997                         thisjob->changed = 1;
3998                         if (thisjob->state != jobstate) {
3999                                 TRACE(("Job %d: changing state from %d to %d\n",
4000                                         jobno(thisjob), thisjob->state, jobstate));
4001                                 thisjob->state = jobstate;
4002 #if JOBS
4003                                 if (jobstate == JOBSTOPPED)
4004                                         set_curjob(thisjob, CUR_STOPPED);
4005 #endif
4006                         }
4007                 }
4008                 goto out;
4009         }
4010         /* The process wasn't found in job list */
4011         if (JOBS && !WIFSTOPPED(status))
4012                 jobless--;
4013  out:
4014         INT_ON;
4015
4016         if (thisjob && thisjob == job) {
4017                 char s[48 + 1];
4018                 int len;
4019
4020                 len = sprint_status48(s, status, 1);
4021                 if (len) {
4022                         s[len] = '\n';
4023                         s[len + 1] = '\0';
4024                         out2str(s);
4025                 }
4026         }
4027         return pid;
4028 }
4029
4030 static int
4031 blocking_wait_with_raise_on_sig(void)
4032 {
4033         pid_t pid = dowait(DOWAIT_BLOCK, NULL);
4034         if (pid <= 0 && pending_sig)
4035                 raise_exception(EXSIG);
4036         return pid;
4037 }
4038
4039 #if JOBS
4040 static void
4041 showjob(struct job *jp, int mode)
4042 {
4043         struct procstat *ps;
4044         struct procstat *psend;
4045         int col;
4046         int indent_col;
4047         char s[16 + 16 + 48];
4048         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4049
4050         ps = jp->ps;
4051
4052         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4053                 /* just output process (group) id of pipeline */
4054                 fprintf(out, "%d\n", ps->ps_pid);
4055                 return;
4056         }
4057
4058         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4059         indent_col = col;
4060
4061         if (jp == curjob)
4062                 s[col - 3] = '+';
4063         else if (curjob && jp == curjob->prev_job)
4064                 s[col - 3] = '-';
4065
4066         if (mode & SHOW_PIDS)
4067                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4068
4069         psend = ps + jp->nprocs;
4070
4071         if (jp->state == JOBRUNNING) {
4072                 strcpy(s + col, "Running");
4073                 col += sizeof("Running") - 1;
4074         } else {
4075                 int status = psend[-1].ps_status;
4076                 if (jp->state == JOBSTOPPED)
4077                         status = jp->stopstatus;
4078                 col += sprint_status48(s + col, status, 0);
4079         }
4080         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4081
4082         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4083          * or prints several "PID             | <cmdN>" lines,
4084          * depending on SHOW_PIDS bit.
4085          * We do not print status of individual processes
4086          * between PID and <cmdN>. bash does it, but not very well:
4087          * first line shows overall job status, not process status,
4088          * making it impossible to know 1st process status.
4089          */
4090         goto start;
4091         do {
4092                 /* for each process */
4093                 s[0] = '\0';
4094                 col = 33;
4095                 if (mode & SHOW_PIDS)
4096                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4097  start:
4098                 fprintf(out, "%s%*c%s%s",
4099                                 s,
4100                                 33 - col >= 0 ? 33 - col : 0, ' ',
4101                                 ps == jp->ps ? "" : "| ",
4102                                 ps->ps_cmd
4103                 );
4104         } while (++ps != psend);
4105         newline_and_flush(out);
4106
4107         jp->changed = 0;
4108
4109         if (jp->state == JOBDONE) {
4110                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4111                 freejob(jp);
4112         }
4113 }
4114
4115 /*
4116  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4117  * statuses have changed since the last call to showjobs.
4118  */
4119 static void
4120 showjobs(int mode)
4121 {
4122         struct job *jp;
4123
4124         TRACE(("showjobs(0x%x) called\n", mode));
4125
4126         /* Handle all finished jobs */
4127         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4128                 continue;
4129
4130         for (jp = curjob; jp; jp = jp->prev_job) {
4131                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4132                         showjob(jp, mode);
4133                 }
4134         }
4135 }
4136
4137 static int FAST_FUNC
4138 jobscmd(int argc UNUSED_PARAM, char **argv)
4139 {
4140         int mode, m;
4141
4142         mode = 0;
4143         while ((m = nextopt("lp")) != '\0') {
4144                 if (m == 'l')
4145                         mode |= SHOW_PIDS;
4146                 else
4147                         mode |= SHOW_ONLY_PGID;
4148         }
4149
4150         argv = argptr;
4151         if (*argv) {
4152                 do
4153                         showjob(getjob(*argv, 0), mode);
4154                 while (*++argv);
4155         } else {
4156                 showjobs(mode);
4157         }
4158
4159         return 0;
4160 }
4161 #endif /* JOBS */
4162
4163 /* Called only on finished or stopped jobs (no members are running) */
4164 static int
4165 getstatus(struct job *job)
4166 {
4167         int status;
4168         int retval;
4169         struct procstat *ps;
4170
4171         /* Fetch last member's status */
4172         ps = job->ps + job->nprocs - 1;
4173         status = ps->ps_status;
4174         if (pipefail) {
4175                 /* "set -o pipefail" mode: use last _nonzero_ status */
4176                 while (status == 0 && --ps >= job->ps)
4177                         status = ps->ps_status;
4178         }
4179
4180         retval = WEXITSTATUS(status);
4181         if (!WIFEXITED(status)) {
4182 #if JOBS
4183                 retval = WSTOPSIG(status);
4184                 if (!WIFSTOPPED(status))
4185 #endif
4186                 {
4187                         /* XXX: limits number of signals */
4188                         retval = WTERMSIG(status);
4189 #if JOBS
4190                         if (retval == SIGINT)
4191                                 job->sigint = 1;
4192 #endif
4193                 }
4194                 retval += 128;
4195         }
4196         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4197                 jobno(job), job->nprocs, status, retval));
4198         return retval;
4199 }
4200
4201 static int FAST_FUNC
4202 waitcmd(int argc UNUSED_PARAM, char **argv)
4203 {
4204         struct job *job;
4205         int retval;
4206         struct job *jp;
4207
4208         if (pending_sig)
4209                 raise_exception(EXSIG);
4210
4211         nextopt(nullstr);
4212         retval = 0;
4213
4214         argv = argptr;
4215         if (!*argv) {
4216                 /* wait for all jobs */
4217                 for (;;) {
4218                         jp = curjob;
4219                         while (1) {
4220                                 if (!jp) /* no running procs */
4221                                         goto ret;
4222                                 if (jp->state == JOBRUNNING)
4223                                         break;
4224                                 jp->waited = 1;
4225                                 jp = jp->prev_job;
4226                         }
4227                         blocking_wait_with_raise_on_sig();
4228         /* man bash:
4229          * "When bash is waiting for an asynchronous command via
4230          * the wait builtin, the reception of a signal for which a trap
4231          * has been set will cause the wait builtin to return immediately
4232          * with an exit status greater than 128, immediately after which
4233          * the trap is executed."
4234          *
4235          * blocking_wait_with_raise_on_sig raises signal handlers
4236          * if it gets no pid (pid < 0). However,
4237          * if child sends us a signal *and immediately exits*,
4238          * blocking_wait_with_raise_on_sig gets pid > 0
4239          * and does not handle pending_sig. Check this case: */
4240                         if (pending_sig)
4241                                 raise_exception(EXSIG);
4242                 }
4243         }
4244
4245         retval = 127;
4246         do {
4247                 if (**argv != '%') {
4248                         pid_t pid = number(*argv);
4249                         job = curjob;
4250                         while (1) {
4251                                 if (!job)
4252                                         goto repeat;
4253                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4254                                         break;
4255                                 job = job->prev_job;
4256                         }
4257                 } else {
4258                         job = getjob(*argv, 0);
4259                 }
4260                 /* loop until process terminated or stopped */
4261                 while (job->state == JOBRUNNING)
4262                         blocking_wait_with_raise_on_sig();
4263                 job->waited = 1;
4264                 retval = getstatus(job);
4265  repeat: ;
4266         } while (*++argv);
4267
4268  ret:
4269         return retval;
4270 }
4271
4272 static struct job *
4273 growjobtab(void)
4274 {
4275         size_t len;
4276         ptrdiff_t offset;
4277         struct job *jp, *jq;
4278
4279         len = njobs * sizeof(*jp);
4280         jq = jobtab;
4281         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4282
4283         offset = (char *)jp - (char *)jq;
4284         if (offset) {
4285                 /* Relocate pointers */
4286                 size_t l = len;
4287
4288                 jq = (struct job *)((char *)jq + l);
4289                 while (l) {
4290                         l -= sizeof(*jp);
4291                         jq--;
4292 #define joff(p) ((struct job *)((char *)(p) + l))
4293 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4294                         if (joff(jp)->ps == &jq->ps0)
4295                                 jmove(joff(jp)->ps);
4296                         if (joff(jp)->prev_job)
4297                                 jmove(joff(jp)->prev_job);
4298                 }
4299                 if (curjob)
4300                         jmove(curjob);
4301 #undef joff
4302 #undef jmove
4303         }
4304
4305         njobs += 4;
4306         jobtab = jp;
4307         jp = (struct job *)((char *)jp + len);
4308         jq = jp + 3;
4309         do {
4310                 jq->used = 0;
4311         } while (--jq >= jp);
4312         return jp;
4313 }
4314
4315 /*
4316  * Return a new job structure.
4317  * Called with interrupts off.
4318  */
4319 static struct job *
4320 makejob(/*union node *node,*/ int nprocs)
4321 {
4322         int i;
4323         struct job *jp;
4324
4325         for (i = njobs, jp = jobtab; ; jp++) {
4326                 if (--i < 0) {
4327                         jp = growjobtab();
4328                         break;
4329                 }
4330                 if (jp->used == 0)
4331                         break;
4332                 if (jp->state != JOBDONE || !jp->waited)
4333                         continue;
4334 #if JOBS
4335                 if (doing_jobctl)
4336                         continue;
4337 #endif
4338                 freejob(jp);
4339                 break;
4340         }
4341         memset(jp, 0, sizeof(*jp));
4342 #if JOBS
4343         /* jp->jobctl is a bitfield.
4344          * "jp->jobctl |= jobctl" likely to give awful code */
4345         if (doing_jobctl)
4346                 jp->jobctl = 1;
4347 #endif
4348         jp->prev_job = curjob;
4349         curjob = jp;
4350         jp->used = 1;
4351         jp->ps = &jp->ps0;
4352         if (nprocs > 1) {
4353                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4354         }
4355         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4356                                 jobno(jp)));
4357         return jp;
4358 }
4359
4360 #if JOBS
4361 /*
4362  * Return a string identifying a command (to be printed by the
4363  * jobs command).
4364  */
4365 static char *cmdnextc;
4366
4367 static void
4368 cmdputs(const char *s)
4369 {
4370         static const char vstype[VSTYPE + 1][3] = {
4371                 "", "}", "-", "+", "?", "=",
4372                 "%", "%%", "#", "##"
4373                 IF_ASH_BASH_COMPAT(, ":", "/", "//")
4374         };
4375
4376         const char *p, *str;
4377         char cc[2];
4378         char *nextc;
4379         unsigned char c;
4380         unsigned char subtype = 0;
4381         int quoted = 0;
4382
4383         cc[1] = '\0';
4384         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4385         p = s;
4386         while ((c = *p++) != '\0') {
4387                 str = NULL;
4388                 switch (c) {
4389                 case CTLESC:
4390                         c = *p++;
4391                         break;
4392                 case CTLVAR:
4393                         subtype = *p++;
4394                         if ((subtype & VSTYPE) == VSLENGTH)
4395                                 str = "${#";
4396                         else
4397                                 str = "${";
4398                         goto dostr;
4399                 case CTLENDVAR:
4400                         str = "\"}" + !(quoted & 1);
4401                         quoted >>= 1;
4402                         subtype = 0;
4403                         goto dostr;
4404                 case CTLBACKQ:
4405                         str = "$(...)";
4406                         goto dostr;
4407 #if ENABLE_SH_MATH_SUPPORT
4408                 case CTLARI:
4409                         str = "$((";
4410                         goto dostr;
4411                 case CTLENDARI:
4412                         str = "))";
4413                         goto dostr;
4414 #endif
4415                 case CTLQUOTEMARK:
4416                         quoted ^= 1;
4417                         c = '"';
4418                         break;
4419                 case '=':
4420                         if (subtype == 0)
4421                                 break;
4422                         if ((subtype & VSTYPE) != VSNORMAL)
4423                                 quoted <<= 1;
4424                         str = vstype[subtype & VSTYPE];
4425                         if (subtype & VSNUL)
4426                                 c = ':';
4427                         else
4428                                 goto checkstr;
4429                         break;
4430                 case '\'':
4431                 case '\\':
4432                 case '"':
4433                 case '$':
4434                         /* These can only happen inside quotes */
4435                         cc[0] = c;
4436                         str = cc;
4437                         c = '\\';
4438                         break;
4439                 default:
4440                         break;
4441                 }
4442                 USTPUTC(c, nextc);
4443  checkstr:
4444                 if (!str)
4445                         continue;
4446  dostr:
4447                 while ((c = *str++) != '\0') {
4448                         USTPUTC(c, nextc);
4449                 }
4450         } /* while *p++ not NUL */
4451
4452         if (quoted & 1) {
4453                 USTPUTC('"', nextc);
4454         }
4455         *nextc = 0;
4456         cmdnextc = nextc;
4457 }
4458
4459 /* cmdtxt() and cmdlist() call each other */
4460 static void cmdtxt(union node *n);
4461
4462 static void
4463 cmdlist(union node *np, int sep)
4464 {
4465         for (; np; np = np->narg.next) {
4466                 if (!sep)
4467                         cmdputs(" ");
4468                 cmdtxt(np);
4469                 if (sep && np->narg.next)
4470                         cmdputs(" ");
4471         }
4472 }
4473
4474 static void
4475 cmdtxt(union node *n)
4476 {
4477         union node *np;
4478         struct nodelist *lp;
4479         const char *p;
4480
4481         if (!n)
4482                 return;
4483         switch (n->type) {
4484         default:
4485 #if DEBUG
4486                 abort();
4487 #endif
4488         case NPIPE:
4489                 lp = n->npipe.cmdlist;
4490                 for (;;) {
4491                         cmdtxt(lp->n);
4492                         lp = lp->next;
4493                         if (!lp)
4494                                 break;
4495                         cmdputs(" | ");
4496                 }
4497                 break;
4498         case NSEMI:
4499                 p = "; ";
4500                 goto binop;
4501         case NAND:
4502                 p = " && ";
4503                 goto binop;
4504         case NOR:
4505                 p = " || ";
4506  binop:
4507                 cmdtxt(n->nbinary.ch1);
4508                 cmdputs(p);
4509                 n = n->nbinary.ch2;
4510                 goto donode;
4511         case NREDIR:
4512         case NBACKGND:
4513                 n = n->nredir.n;
4514                 goto donode;
4515         case NNOT:
4516                 cmdputs("!");
4517                 n = n->nnot.com;
4518  donode:
4519                 cmdtxt(n);
4520                 break;
4521         case NIF:
4522                 cmdputs("if ");
4523                 cmdtxt(n->nif.test);
4524                 cmdputs("; then ");
4525                 if (n->nif.elsepart) {
4526                         cmdtxt(n->nif.ifpart);
4527                         cmdputs("; else ");
4528                         n = n->nif.elsepart;
4529                 } else {
4530                         n = n->nif.ifpart;
4531                 }
4532                 p = "; fi";
4533                 goto dotail;
4534         case NSUBSHELL:
4535                 cmdputs("(");
4536                 n = n->nredir.n;
4537                 p = ")";
4538                 goto dotail;
4539         case NWHILE:
4540                 p = "while ";
4541                 goto until;
4542         case NUNTIL:
4543                 p = "until ";
4544  until:
4545                 cmdputs(p);
4546                 cmdtxt(n->nbinary.ch1);
4547                 n = n->nbinary.ch2;
4548                 p = "; done";
4549  dodo:
4550                 cmdputs("; do ");
4551  dotail:
4552                 cmdtxt(n);
4553                 goto dotail2;
4554         case NFOR:
4555                 cmdputs("for ");
4556                 cmdputs(n->nfor.var);
4557                 cmdputs(" in ");
4558                 cmdlist(n->nfor.args, 1);
4559                 n = n->nfor.body;
4560                 p = "; done";
4561                 goto dodo;
4562         case NDEFUN:
4563                 cmdputs(n->narg.text);
4564                 p = "() { ... }";
4565                 goto dotail2;
4566         case NCMD:
4567                 cmdlist(n->ncmd.args, 1);
4568                 cmdlist(n->ncmd.redirect, 0);
4569                 break;
4570         case NARG:
4571                 p = n->narg.text;
4572  dotail2:
4573                 cmdputs(p);
4574                 break;
4575         case NHERE:
4576         case NXHERE:
4577                 p = "<<...";
4578                 goto dotail2;
4579         case NCASE:
4580                 cmdputs("case ");
4581                 cmdputs(n->ncase.expr->narg.text);
4582                 cmdputs(" in ");
4583                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4584                         cmdtxt(np->nclist.pattern);
4585                         cmdputs(") ");
4586                         cmdtxt(np->nclist.body);
4587                         cmdputs(";; ");
4588                 }
4589                 p = "esac";
4590                 goto dotail2;
4591         case NTO:
4592                 p = ">";
4593                 goto redir;
4594         case NCLOBBER:
4595                 p = ">|";
4596                 goto redir;
4597         case NAPPEND:
4598                 p = ">>";
4599                 goto redir;
4600 #if ENABLE_ASH_BASH_COMPAT
4601         case NTO2:
4602 #endif
4603         case NTOFD:
4604                 p = ">&";
4605                 goto redir;
4606         case NFROM:
4607                 p = "<";
4608                 goto redir;
4609         case NFROMFD:
4610                 p = "<&";
4611                 goto redir;
4612         case NFROMTO:
4613                 p = "<>";
4614  redir:
4615                 cmdputs(utoa(n->nfile.fd));
4616                 cmdputs(p);
4617                 if (n->type == NTOFD || n->type == NFROMFD) {
4618                         cmdputs(utoa(n->ndup.dupfd));
4619                         break;
4620                 }
4621                 n = n->nfile.fname;
4622                 goto donode;
4623         }
4624 }
4625
4626 static char *
4627 commandtext(union node *n)
4628 {
4629         char *name;
4630
4631         STARTSTACKSTR(cmdnextc);
4632         cmdtxt(n);
4633         name = stackblock();
4634         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4635         return ckstrdup(name);
4636 }
4637 #endif /* JOBS */
4638
4639 /*
4640  * Fork off a subshell.  If we are doing job control, give the subshell its
4641  * own process group.  Jp is a job structure that the job is to be added to.
4642  * N is the command that will be evaluated by the child.  Both jp and n may
4643  * be NULL.  The mode parameter can be one of the following:
4644  *      FORK_FG - Fork off a foreground process.
4645  *      FORK_BG - Fork off a background process.
4646  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4647  *                   process group even if job control is on.
4648  *
4649  * When job control is turned off, background processes have their standard
4650  * input redirected to /dev/null (except for the second and later processes
4651  * in a pipeline).
4652  *
4653  * Called with interrupts off.
4654  */
4655 /*
4656  * Clear traps on a fork.
4657  */
4658 static void
4659 clear_traps(void)
4660 {
4661         char **tp;
4662
4663         INT_OFF;
4664         for (tp = trap; tp < &trap[NSIG]; tp++) {
4665                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4666                         if (trap_ptr == trap)
4667                                 free(*tp);
4668                         /* else: it "belongs" to trap_ptr vector, don't free */
4669                         *tp = NULL;
4670                         if ((tp - trap) != 0)
4671                                 setsignal(tp - trap);
4672                 }
4673         }
4674         may_have_traps = 0;
4675         INT_ON;
4676 }
4677
4678 /* Lives far away from here, needed for forkchild */
4679 static void closescript(void);
4680
4681 /* Called after fork(), in child */
4682 /* jp and n are NULL when called by openhere() for heredoc support */
4683 static NOINLINE void
4684 forkchild(struct job *jp, union node *n, int mode)
4685 {
4686         int oldlvl;
4687
4688         TRACE(("Child shell %d\n", getpid()));
4689         oldlvl = shlvl;
4690         shlvl++;
4691
4692         /* man bash: "Non-builtin commands run by bash have signal handlers
4693          * set to the values inherited by the shell from its parent".
4694          * Do we do it correctly? */
4695
4696         closescript();
4697
4698         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4699          && n && n->type == NCMD        /* is it single cmd? */
4700         /* && n->ncmd.args->type == NARG - always true? */
4701          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4702          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4703         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4704         ) {
4705                 TRACE(("Trap hack\n"));
4706                 /* Awful hack for `trap` or $(trap).
4707                  *
4708                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4709                  * contains an example where "trap" is executed in a subshell:
4710                  *
4711                  * save_traps=$(trap)
4712                  * ...
4713                  * eval "$save_traps"
4714                  *
4715                  * Standard does not say that "trap" in subshell shall print
4716                  * parent shell's traps. It only says that its output
4717                  * must have suitable form, but then, in the above example
4718                  * (which is not supposed to be normative), it implies that.
4719                  *
4720                  * bash (and probably other shell) does implement it
4721                  * (traps are reset to defaults, but "trap" still shows them),
4722                  * but as a result, "trap" logic is hopelessly messed up:
4723                  *
4724                  * # trap
4725                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4726                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4727                  * # true | trap   <--- trap is in subshell - no output (ditto)
4728                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4729                  * trap -- 'echo Ho' SIGWINCH
4730                  * # echo `(trap)`         <--- in subshell in subshell - output
4731                  * trap -- 'echo Ho' SIGWINCH
4732                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4733                  * trap -- 'echo Ho' SIGWINCH
4734                  *
4735                  * The rules when to forget and when to not forget traps
4736                  * get really complex and nonsensical.
4737                  *
4738                  * Our solution: ONLY bare $(trap) or `trap` is special.
4739                  */
4740                 /* Save trap handler strings for trap builtin to print */
4741                 trap_ptr = xmemdup(trap, sizeof(trap));
4742                 /* Fall through into clearing traps */
4743         }
4744         clear_traps();
4745 #if JOBS
4746         /* do job control only in root shell */
4747         doing_jobctl = 0;
4748         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4749                 pid_t pgrp;
4750
4751                 if (jp->nprocs == 0)
4752                         pgrp = getpid();
4753                 else
4754                         pgrp = jp->ps[0].ps_pid;
4755                 /* this can fail because we are doing it in the parent also */
4756                 setpgid(0, pgrp);
4757                 if (mode == FORK_FG)
4758                         xtcsetpgrp(ttyfd, pgrp);
4759                 setsignal(SIGTSTP);
4760                 setsignal(SIGTTOU);
4761         } else
4762 #endif
4763         if (mode == FORK_BG) {
4764                 /* man bash: "When job control is not in effect,
4765                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4766                 ignoresig(SIGINT);
4767                 ignoresig(SIGQUIT);
4768                 if (jp->nprocs == 0) {
4769                         close(0);
4770                         if (open(bb_dev_null, O_RDONLY) != 0)
4771                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4772                 }
4773         }
4774         if (oldlvl == 0) {
4775                 if (iflag) { /* why if iflag only? */
4776                         setsignal(SIGINT);
4777                         setsignal(SIGTERM);
4778                 }
4779                 /* man bash:
4780                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4781                  * commands run by bash have signal handlers
4782                  * set to the values inherited by the shell
4783                  * from its parent".
4784                  * Take care of the second rule: */
4785                 setsignal(SIGQUIT);
4786         }
4787 #if JOBS
4788         if (n && n->type == NCMD
4789          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4790         ) {
4791                 TRACE(("Job hack\n"));
4792                 /* "jobs": we do not want to clear job list for it,
4793                  * instead we remove only _its_ own_ job from job list.
4794                  * This makes "jobs .... | cat" more useful.
4795                  */
4796                 freejob(curjob);
4797                 return;
4798         }
4799 #endif
4800         for (jp = curjob; jp; jp = jp->prev_job)
4801                 freejob(jp);
4802         jobless = 0;
4803 }
4804
4805 /* Called after fork(), in parent */
4806 #if !JOBS
4807 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4808 #endif
4809 static void
4810 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4811 {
4812         TRACE(("In parent shell: child = %d\n", pid));
4813         if (!jp) {
4814                 /* jp is NULL when called by openhere() for heredoc support */
4815                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4816                         continue;
4817                 jobless++;
4818                 return;
4819         }
4820 #if JOBS
4821         if (mode != FORK_NOJOB && jp->jobctl) {
4822                 int pgrp;
4823
4824                 if (jp->nprocs == 0)
4825                         pgrp = pid;
4826                 else
4827                         pgrp = jp->ps[0].ps_pid;
4828                 /* This can fail because we are doing it in the child also */
4829                 setpgid(pid, pgrp);
4830         }
4831 #endif
4832         if (mode == FORK_BG) {
4833                 backgndpid = pid;               /* set $! */
4834                 set_curjob(jp, CUR_RUNNING);
4835         }
4836         if (jp) {
4837                 struct procstat *ps = &jp->ps[jp->nprocs++];
4838                 ps->ps_pid = pid;
4839                 ps->ps_status = -1;
4840                 ps->ps_cmd = nullstr;
4841 #if JOBS
4842                 if (doing_jobctl && n)
4843                         ps->ps_cmd = commandtext(n);
4844 #endif
4845         }
4846 }
4847
4848 /* jp and n are NULL when called by openhere() for heredoc support */
4849 static int
4850 forkshell(struct job *jp, union node *n, int mode)
4851 {
4852         int pid;
4853
4854         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4855         pid = fork();
4856         if (pid < 0) {
4857                 TRACE(("Fork failed, errno=%d", errno));
4858                 if (jp)
4859                         freejob(jp);
4860                 ash_msg_and_raise_error("can't fork");
4861         }
4862         if (pid == 0) {
4863                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
4864                 forkchild(jp, n, mode);
4865         } else {
4866                 forkparent(jp, n, mode, pid);
4867         }
4868         return pid;
4869 }
4870
4871 /*
4872  * Wait for job to finish.
4873  *
4874  * Under job control we have the problem that while a child process
4875  * is running interrupts generated by the user are sent to the child
4876  * but not to the shell.  This means that an infinite loop started by
4877  * an interactive user may be hard to kill.  With job control turned off,
4878  * an interactive user may place an interactive program inside a loop.
4879  * If the interactive program catches interrupts, the user doesn't want
4880  * these interrupts to also abort the loop.  The approach we take here
4881  * is to have the shell ignore interrupt signals while waiting for a
4882  * foreground process to terminate, and then send itself an interrupt
4883  * signal if the child process was terminated by an interrupt signal.
4884  * Unfortunately, some programs want to do a bit of cleanup and then
4885  * exit on interrupt; unless these processes terminate themselves by
4886  * sending a signal to themselves (instead of calling exit) they will
4887  * confuse this approach.
4888  *
4889  * Called with interrupts off.
4890  */
4891 static int
4892 waitforjob(struct job *jp)
4893 {
4894         int st;
4895
4896         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4897
4898         INT_OFF;
4899         while (jp->state == JOBRUNNING) {
4900                 /* In non-interactive shells, we _can_ get
4901                  * a keyboard signal here and be EINTRed,
4902                  * but we just loop back, waiting for command to complete.
4903                  *
4904                  * man bash:
4905                  * "If bash is waiting for a command to complete and receives
4906                  * a signal for which a trap has been set, the trap
4907                  * will not be executed until the command completes."
4908                  *
4909                  * Reality is that even if trap is not set, bash
4910                  * will not act on the signal until command completes.
4911                  * Try this. sleep5intoff.c:
4912                  * #include <signal.h>
4913                  * #include <unistd.h>
4914                  * int main() {
4915                  *         sigset_t set;
4916                  *         sigemptyset(&set);
4917                  *         sigaddset(&set, SIGINT);
4918                  *         sigaddset(&set, SIGQUIT);
4919                  *         sigprocmask(SIG_BLOCK, &set, NULL);
4920                  *         sleep(5);
4921                  *         return 0;
4922                  * }
4923                  * $ bash -c './sleep5intoff; echo hi'
4924                  * ^C^C^C^C <--- pressing ^C once a second
4925                  * $ _
4926                  * $ bash -c './sleep5intoff; echo hi'
4927                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4928                  * $ _
4929                  */
4930                 dowait(DOWAIT_BLOCK, jp);
4931         }
4932         INT_ON;
4933
4934         st = getstatus(jp);
4935 #if JOBS
4936         if (jp->jobctl) {
4937                 xtcsetpgrp(ttyfd, rootpid);
4938                 /*
4939                  * This is truly gross.
4940                  * If we're doing job control, then we did a TIOCSPGRP which
4941                  * caused us (the shell) to no longer be in the controlling
4942                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
4943                  * intuit from the subprocess exit status whether a SIGINT
4944                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
4945                  */
4946                 if (jp->sigint) /* TODO: do the same with all signals */
4947                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
4948         }
4949         if (jp->state == JOBDONE)
4950 #endif
4951                 freejob(jp);
4952         return st;
4953 }
4954
4955 /*
4956  * return 1 if there are stopped jobs, otherwise 0
4957  */
4958 static int
4959 stoppedjobs(void)
4960 {
4961         struct job *jp;
4962         int retval;
4963
4964         retval = 0;
4965         if (job_warning)
4966                 goto out;
4967         jp = curjob;
4968         if (jp && jp->state == JOBSTOPPED) {
4969                 out2str("You have stopped jobs.\n");
4970                 job_warning = 2;
4971                 retval++;
4972         }
4973  out:
4974         return retval;
4975 }
4976
4977
4978 /*
4979  * Code for dealing with input/output redirection.
4980  */
4981
4982 #undef EMPTY
4983 #undef CLOSED
4984 #define EMPTY -2                /* marks an unused slot in redirtab */
4985 #define CLOSED -3               /* marks a slot of previously-closed fd */
4986
4987 /*
4988  * Open a file in noclobber mode.
4989  * The code was copied from bash.
4990  */
4991 static int
4992 noclobberopen(const char *fname)
4993 {
4994         int r, fd;
4995         struct stat finfo, finfo2;
4996
4997         /*
4998          * If the file exists and is a regular file, return an error
4999          * immediately.
5000          */
5001         r = stat(fname, &finfo);
5002         if (r == 0 && S_ISREG(finfo.st_mode)) {
5003                 errno = EEXIST;
5004                 return -1;
5005         }
5006
5007         /*
5008          * If the file was not present (r != 0), make sure we open it
5009          * exclusively so that if it is created before we open it, our open
5010          * will fail.  Make sure that we do not truncate an existing file.
5011          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5012          * file was not a regular file, we leave O_EXCL off.
5013          */
5014         if (r != 0)
5015                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5016         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5017
5018         /* If the open failed, return the file descriptor right away. */
5019         if (fd < 0)
5020                 return fd;
5021
5022         /*
5023          * OK, the open succeeded, but the file may have been changed from a
5024          * non-regular file to a regular file between the stat and the open.
5025          * We are assuming that the O_EXCL open handles the case where FILENAME
5026          * did not exist and is symlinked to an existing file between the stat
5027          * and open.
5028          */
5029
5030         /*
5031          * If we can open it and fstat the file descriptor, and neither check
5032          * revealed that it was a regular file, and the file has not been
5033          * replaced, return the file descriptor.
5034          */
5035         if (fstat(fd, &finfo2) == 0
5036          && !S_ISREG(finfo2.st_mode)
5037          && finfo.st_dev == finfo2.st_dev
5038          && finfo.st_ino == finfo2.st_ino
5039         ) {
5040                 return fd;
5041         }
5042
5043         /* The file has been replaced.  badness. */
5044         close(fd);
5045         errno = EEXIST;
5046         return -1;
5047 }
5048
5049 /*
5050  * Handle here documents.  Normally we fork off a process to write the
5051  * data to a pipe.  If the document is short, we can stuff the data in
5052  * the pipe without forking.
5053  */
5054 /* openhere needs this forward reference */
5055 static void expandhere(union node *arg, int fd);
5056 static int
5057 openhere(union node *redir)
5058 {
5059         int pip[2];
5060         size_t len = 0;
5061
5062         if (pipe(pip) < 0)
5063                 ash_msg_and_raise_error("pipe call failed");
5064         if (redir->type == NHERE) {
5065                 len = strlen(redir->nhere.doc->narg.text);
5066                 if (len <= PIPE_BUF) {
5067                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5068                         goto out;
5069                 }
5070         }
5071         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5072                 /* child */
5073                 close(pip[0]);
5074                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5075                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5076                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5077                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5078                 signal(SIGPIPE, SIG_DFL);
5079                 if (redir->type == NHERE)
5080                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5081                 else /* NXHERE */
5082                         expandhere(redir->nhere.doc, pip[1]);
5083                 _exit(EXIT_SUCCESS);
5084         }
5085  out:
5086         close(pip[1]);
5087         return pip[0];
5088 }
5089
5090 static int
5091 openredirect(union node *redir)
5092 {
5093         char *fname;
5094         int f;
5095
5096         switch (redir->nfile.type) {
5097 /* Can't happen, our single caller does this itself */
5098 //      case NTOFD:
5099 //      case NFROMFD:
5100 //              return -1;
5101         case NHERE:
5102         case NXHERE:
5103                 return openhere(redir);
5104         }
5105
5106         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5107          * allocated space. Do it only when we know it is safe.
5108          */
5109         fname = redir->nfile.expfname;
5110
5111         switch (redir->nfile.type) {
5112         default:
5113 #if DEBUG
5114                 abort();
5115 #endif
5116         case NFROM:
5117                 f = open(fname, O_RDONLY);
5118                 if (f < 0)
5119                         goto eopen;
5120                 break;
5121         case NFROMTO:
5122                 f = open(fname, O_RDWR|O_CREAT, 0666);
5123                 if (f < 0)
5124                         goto ecreate;
5125                 break;
5126         case NTO:
5127 #if ENABLE_ASH_BASH_COMPAT
5128         case NTO2:
5129 #endif
5130                 /* Take care of noclobber mode. */
5131                 if (Cflag) {
5132                         f = noclobberopen(fname);
5133                         if (f < 0)
5134                                 goto ecreate;
5135                         break;
5136                 }
5137                 /* FALLTHROUGH */
5138         case NCLOBBER:
5139                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5140                 if (f < 0)
5141                         goto ecreate;
5142                 break;
5143         case NAPPEND:
5144                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5145                 if (f < 0)
5146                         goto ecreate;
5147                 break;
5148         }
5149
5150         return f;
5151  ecreate:
5152         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5153  eopen:
5154         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5155 }
5156
5157 /*
5158  * Copy a file descriptor to be >= 10. Throws exception on error.
5159  */
5160 static int
5161 savefd(int from)
5162 {
5163         int newfd;
5164         int err;
5165
5166         newfd = fcntl(from, F_DUPFD, 10);
5167         err = newfd < 0 ? errno : 0;
5168         if (err != EBADF) {
5169                 if (err)
5170                         ash_msg_and_raise_error("%d: %m", from);
5171                 close(from);
5172                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5173         }
5174
5175         return newfd;
5176 }
5177 static int
5178 dup2_or_raise(int from, int to)
5179 {
5180         int newfd;
5181
5182         newfd = (from != to) ? dup2(from, to) : to;
5183         if (newfd < 0) {
5184                 /* Happens when source fd is not open: try "echo >&99" */
5185                 ash_msg_and_raise_error("%d: %m", from);
5186         }
5187         return newfd;
5188 }
5189
5190 /* Struct def and variable are moved down to the first usage site */
5191 struct two_fd_t {
5192         int orig, copy;
5193 };
5194 struct redirtab {
5195         struct redirtab *next;
5196         int pair_count;
5197         struct two_fd_t two_fd[];
5198 };
5199 #define redirlist (G_var.redirlist)
5200 enum {
5201         COPYFD_RESTORE = (int)~(INT_MAX),
5202 };
5203
5204 static int
5205 need_to_remember(struct redirtab *rp, int fd)
5206 {
5207         int i;
5208
5209         if (!rp) /* remembering was not requested */
5210                 return 0;
5211
5212         for (i = 0; i < rp->pair_count; i++) {
5213                 if (rp->two_fd[i].orig == fd) {
5214                         /* already remembered */
5215                         return 0;
5216                 }
5217         }
5218         return 1;
5219 }
5220
5221 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5222 static int
5223 is_hidden_fd(struct redirtab *rp, int fd)
5224 {
5225         int i;
5226         struct parsefile *pf;
5227
5228         if (fd == -1)
5229                 return 0;
5230         /* Check open scripts' fds */
5231         pf = g_parsefile;
5232         while (pf) {
5233                 /* We skip pf_fd == 0 case because of the following case:
5234                  * $ ash  # running ash interactively
5235                  * $ . ./script.sh
5236                  * and in script.sh: "exec 9>&0".
5237                  * Even though top-level pf_fd _is_ 0,
5238                  * it's still ok to use it: "read" builtin uses it,
5239                  * why should we cripple "exec" builtin?
5240                  */
5241                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5242                         return 1;
5243                 }
5244                 pf = pf->prev;
5245         }
5246
5247         if (!rp)
5248                 return 0;
5249         /* Check saved fds of redirects */
5250         fd |= COPYFD_RESTORE;
5251         for (i = 0; i < rp->pair_count; i++) {
5252                 if (rp->two_fd[i].copy == fd) {
5253                         return 1;
5254                 }
5255         }
5256         return 0;
5257 }
5258
5259 /*
5260  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5261  * old file descriptors are stashed away so that the redirection can be
5262  * undone by calling popredir.
5263  */
5264 /* flags passed to redirect */
5265 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5266 #define REDIR_SAVEFD2 03        /* set preverrout */
5267 static void
5268 redirect(union node *redir, int flags)
5269 {
5270         struct redirtab *sv;
5271         int sv_pos;
5272         int i;
5273         int fd;
5274         int newfd;
5275         int copied_fd2 = -1;
5276
5277         if (!redir) {
5278                 return;
5279         }
5280
5281         sv = NULL;
5282         sv_pos = 0;
5283         INT_OFF;
5284         if (flags & REDIR_PUSH) {
5285                 union node *tmp = redir;
5286                 do {
5287                         sv_pos++;
5288 #if ENABLE_ASH_BASH_COMPAT
5289                         if (tmp->nfile.type == NTO2)
5290                                 sv_pos++;
5291 #endif
5292                         tmp = tmp->nfile.next;
5293                 } while (tmp);
5294                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5295                 sv->next = redirlist;
5296                 sv->pair_count = sv_pos;
5297                 redirlist = sv;
5298                 while (sv_pos > 0) {
5299                         sv_pos--;
5300                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5301                 }
5302         }
5303
5304         do {
5305                 int right_fd = -1;
5306                 fd = redir->nfile.fd;
5307                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5308                         right_fd = redir->ndup.dupfd;
5309                         //bb_error_msg("doing %d > %d", fd, right_fd);
5310                         /* redirect from/to same file descriptor? */
5311                         if (right_fd == fd)
5312                                 continue;
5313                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5314                         if (is_hidden_fd(sv, right_fd)) {
5315                                 errno = EBADF; /* as if it is closed */
5316                                 ash_msg_and_raise_error("%d: %m", right_fd);
5317                         }
5318                         newfd = -1;
5319                 } else {
5320                         newfd = openredirect(redir); /* always >= 0 */
5321                         if (fd == newfd) {
5322                                 /* Descriptor wasn't open before redirect.
5323                                  * Mark it for close in the future */
5324                                 if (need_to_remember(sv, fd)) {
5325                                         goto remember_to_close;
5326                                 }
5327                                 continue;
5328                         }
5329                 }
5330 #if ENABLE_ASH_BASH_COMPAT
5331  redirect_more:
5332 #endif
5333                 if (need_to_remember(sv, fd)) {
5334                         /* Copy old descriptor */
5335                         /* Careful to not accidentally "save"
5336                          * to the same fd as right side fd in N>&M */
5337                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5338                         i = fcntl(fd, F_DUPFD, minfd);
5339 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5340  * are closed in popredir() in the child, preventing them from leaking
5341  * into child. (popredir() also cleans up the mess in case of failures)
5342  */
5343                         if (i == -1) {
5344                                 i = errno;
5345                                 if (i != EBADF) {
5346                                         /* Strange error (e.g. "too many files" EMFILE?) */
5347                                         if (newfd >= 0)
5348                                                 close(newfd);
5349                                         errno = i;
5350                                         ash_msg_and_raise_error("%d: %m", fd);
5351                                         /* NOTREACHED */
5352                                 }
5353                                 /* EBADF: it is not open - good, remember to close it */
5354  remember_to_close:
5355                                 i = CLOSED;
5356                         } else { /* fd is open, save its copy */
5357                                 /* "exec fd>&-" should not close fds
5358                                  * which point to script file(s).
5359                                  * Force them to be restored afterwards */
5360                                 if (is_hidden_fd(sv, fd))
5361                                         i |= COPYFD_RESTORE;
5362                         }
5363                         if (fd == 2)
5364                                 copied_fd2 = i;
5365                         sv->two_fd[sv_pos].orig = fd;
5366                         sv->two_fd[sv_pos].copy = i;
5367                         sv_pos++;
5368                 }
5369                 if (newfd < 0) {
5370                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5371                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5372                                 /* Don't want to trigger debugging */
5373                                 if (fd != -1)
5374                                         close(fd);
5375                         } else {
5376                                 dup2_or_raise(redir->ndup.dupfd, fd);
5377                         }
5378                 } else if (fd != newfd) { /* move newfd to fd */
5379                         dup2_or_raise(newfd, fd);
5380 #if ENABLE_ASH_BASH_COMPAT
5381                         if (!(redir->nfile.type == NTO2 && fd == 2))
5382 #endif
5383                                 close(newfd);
5384                 }
5385 #if ENABLE_ASH_BASH_COMPAT
5386                 if (redir->nfile.type == NTO2 && fd == 1) {
5387                         /* We already redirected it to fd 1, now copy it to 2 */
5388                         newfd = 1;
5389                         fd = 2;
5390                         goto redirect_more;
5391                 }
5392 #endif
5393         } while ((redir = redir->nfile.next) != NULL);
5394
5395         INT_ON;
5396         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5397                 preverrout_fd = copied_fd2;
5398 }
5399
5400 /*
5401  * Undo the effects of the last redirection.
5402  */
5403 static void
5404 popredir(int drop, int restore)
5405 {
5406         struct redirtab *rp;
5407         int i;
5408
5409         if (redirlist == NULL)
5410                 return;
5411         INT_OFF;
5412         rp = redirlist;
5413         for (i = 0; i < rp->pair_count; i++) {
5414                 int fd = rp->two_fd[i].orig;
5415                 int copy = rp->two_fd[i].copy;
5416                 if (copy == CLOSED) {
5417                         if (!drop)
5418                                 close(fd);
5419                         continue;
5420                 }
5421                 if (copy != EMPTY) {
5422                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5423                                 copy &= ~COPYFD_RESTORE;
5424                                 /*close(fd);*/
5425                                 dup2_or_raise(copy, fd);
5426                         }
5427                         close(copy & ~COPYFD_RESTORE);
5428                 }
5429         }
5430         redirlist = rp->next;
5431         free(rp);
5432         INT_ON;
5433 }
5434
5435 /*
5436  * Undo all redirections.  Called on error or interrupt.
5437  */
5438
5439 static int
5440 redirectsafe(union node *redir, int flags)
5441 {
5442         int err;
5443         volatile int saveint;
5444         struct jmploc *volatile savehandler = exception_handler;
5445         struct jmploc jmploc;
5446
5447         SAVE_INT(saveint);
5448         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5449         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5450         if (!err) {
5451                 exception_handler = &jmploc;
5452                 redirect(redir, flags);
5453         }
5454         exception_handler = savehandler;
5455         if (err && exception_type != EXERROR)
5456                 longjmp(exception_handler->loc, 1);
5457         RESTORE_INT(saveint);
5458         return err;
5459 }
5460
5461
5462 /* ============ Routines to expand arguments to commands
5463  *
5464  * We have to deal with backquotes, shell variables, and file metacharacters.
5465  */
5466
5467 #if ENABLE_SH_MATH_SUPPORT
5468 static arith_t
5469 ash_arith(const char *s)
5470 {
5471         arith_state_t math_state;
5472         arith_t result;
5473
5474         math_state.lookupvar = lookupvar;
5475         math_state.setvar    = setvar0;
5476         //math_state.endofname = endofname;
5477
5478         INT_OFF;
5479         result = arith(&math_state, s);
5480         if (math_state.errmsg)
5481                 ash_msg_and_raise_error(math_state.errmsg);
5482         INT_ON;
5483
5484         return result;
5485 }
5486 #endif
5487
5488 /*
5489  * expandarg flags
5490  */
5491 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5492 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5493 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5494 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5495 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5496  * POSIX says for this case:
5497  *  Pathname expansion shall not be performed on the word by a
5498  *  non-interactive shell; an interactive shell may perform it, but shall
5499  *  do so only when the expansion would result in one word.
5500  * Currently, our code complies to the above rule by never globbing
5501  * redirection filenames.
5502  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5503  * (this means that on a typical Linux distro, bash almost always
5504  * performs globbing, and thus diverges from what we do).
5505  */
5506 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5507 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5508 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5509 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5510 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5511 /*
5512  * rmescape() flags
5513  */
5514 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5515 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5516 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5517 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5518 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5519
5520 /* Add CTLESC when necessary. */
5521 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5522 /* Do not skip NUL characters. */
5523 #define QUOTES_KEEPNUL EXP_TILDE
5524
5525 /*
5526  * Structure specifying which parts of the string should be searched
5527  * for IFS characters.
5528  */
5529 struct ifsregion {
5530         struct ifsregion *next; /* next region in list */
5531         int begoff;             /* offset of start of region */
5532         int endoff;             /* offset of end of region */
5533         int nulonly;            /* search for nul bytes only */
5534 };
5535
5536 struct arglist {
5537         struct strlist *list;
5538         struct strlist **lastp;
5539 };
5540
5541 /* output of current string */
5542 static char *expdest;
5543 /* list of back quote expressions */
5544 static struct nodelist *argbackq;
5545 /* first struct in list of ifs regions */
5546 static struct ifsregion ifsfirst;
5547 /* last struct in list */
5548 static struct ifsregion *ifslastp;
5549 /* holds expanded arg list */
5550 static struct arglist exparg;
5551
5552 /*
5553  * Our own itoa().
5554  */
5555 #if !ENABLE_SH_MATH_SUPPORT
5556 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5557 typedef long arith_t;
5558 # define ARITH_FMT "%ld"
5559 #endif
5560 static int
5561 cvtnum(arith_t num)
5562 {
5563         int len;
5564
5565         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5566         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5567         STADJUST(len, expdest);
5568         return len;
5569 }
5570
5571 /*
5572  * Break the argument string into pieces based upon IFS and add the
5573  * strings to the argument list.  The regions of the string to be
5574  * searched for IFS characters have been stored by recordregion.
5575  */
5576 static void
5577 ifsbreakup(char *string, struct arglist *arglist)
5578 {
5579         struct ifsregion *ifsp;
5580         struct strlist *sp;
5581         char *start;
5582         char *p;
5583         char *q;
5584         const char *ifs, *realifs;
5585         int ifsspc;
5586         int nulonly;
5587
5588         start = string;
5589         if (ifslastp != NULL) {
5590                 ifsspc = 0;
5591                 nulonly = 0;
5592                 realifs = ifsset() ? ifsval() : defifs;
5593                 ifsp = &ifsfirst;
5594                 do {
5595                         p = string + ifsp->begoff;
5596                         nulonly = ifsp->nulonly;
5597                         ifs = nulonly ? nullstr : realifs;
5598                         ifsspc = 0;
5599                         while (p < string + ifsp->endoff) {
5600                                 q = p;
5601                                 if ((unsigned char)*p == CTLESC)
5602                                         p++;
5603                                 if (!strchr(ifs, *p)) {
5604                                         p++;
5605                                         continue;
5606                                 }
5607                                 if (!nulonly)
5608                                         ifsspc = (strchr(defifs, *p) != NULL);
5609                                 /* Ignore IFS whitespace at start */
5610                                 if (q == start && ifsspc) {
5611                                         p++;
5612                                         start = p;
5613                                         continue;
5614                                 }
5615                                 *q = '\0';
5616                                 sp = stzalloc(sizeof(*sp));
5617                                 sp->text = start;
5618                                 *arglist->lastp = sp;
5619                                 arglist->lastp = &sp->next;
5620                                 p++;
5621                                 if (!nulonly) {
5622                                         for (;;) {
5623                                                 if (p >= string + ifsp->endoff) {
5624                                                         break;
5625                                                 }
5626                                                 q = p;
5627                                                 if ((unsigned char)*p == CTLESC)
5628                                                         p++;
5629                                                 if (strchr(ifs, *p) == NULL) {
5630                                                         p = q;
5631                                                         break;
5632                                                 }
5633                                                 if (strchr(defifs, *p) == NULL) {
5634                                                         if (ifsspc) {
5635                                                                 p++;
5636                                                                 ifsspc = 0;
5637                                                         } else {
5638                                                                 p = q;
5639                                                                 break;
5640                                                         }
5641                                                 } else
5642                                                         p++;
5643                                         }
5644                                 }
5645                                 start = p;
5646                         } /* while */
5647                         ifsp = ifsp->next;
5648                 } while (ifsp != NULL);
5649                 if (nulonly)
5650                         goto add;
5651         }
5652
5653         if (!*start)
5654                 return;
5655
5656  add:
5657         sp = stzalloc(sizeof(*sp));
5658         sp->text = start;
5659         *arglist->lastp = sp;
5660         arglist->lastp = &sp->next;
5661 }
5662
5663 static void
5664 ifsfree(void)
5665 {
5666         struct ifsregion *p;
5667
5668         INT_OFF;
5669         p = ifsfirst.next;
5670         do {
5671                 struct ifsregion *ifsp;
5672                 ifsp = p->next;
5673                 free(p);
5674                 p = ifsp;
5675         } while (p);
5676         ifslastp = NULL;
5677         ifsfirst.next = NULL;
5678         INT_ON;
5679 }
5680
5681 static size_t
5682 esclen(const char *start, const char *p)
5683 {
5684         size_t esc = 0;
5685
5686         while (p > start && (unsigned char)*--p == CTLESC) {
5687                 esc++;
5688         }
5689         return esc;
5690 }
5691
5692 /*
5693  * Remove any CTLESC characters from a string.
5694  */
5695 static char *
5696 rmescapes(char *str, int flag)
5697 {
5698         static const char qchars[] ALIGN1 = {
5699                 IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' };
5700
5701         char *p, *q, *r;
5702         unsigned inquotes;
5703         unsigned protect_against_glob;
5704         unsigned globbing;
5705         IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;)
5706
5707         p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash));
5708         if (!p)
5709                 return str;
5710
5711         q = p;
5712         r = str;
5713         if (flag & RMESCAPE_ALLOC) {
5714                 size_t len = p - str;
5715                 size_t fulllen = len + strlen(p) + 1;
5716
5717                 if (flag & RMESCAPE_GROW) {
5718                         int strloc = str - (char *)stackblock();
5719                         r = makestrspace(fulllen, expdest);
5720                         /* p and str may be invalidated by makestrspace */
5721                         str = (char *)stackblock() + strloc;
5722                         p = str + len;
5723                 } else if (flag & RMESCAPE_HEAP) {
5724                         r = ckmalloc(fulllen);
5725                 } else {
5726                         r = stalloc(fulllen);
5727                 }
5728                 q = r;
5729                 if (len > 0) {
5730                         q = (char *)memcpy(q, str, len) + len;
5731                 }
5732         }
5733
5734         inquotes = 0;
5735         globbing = flag & RMESCAPE_GLOB;
5736         protect_against_glob = globbing;
5737         while (*p) {
5738                 if ((unsigned char)*p == CTLQUOTEMARK) {
5739 // Note: both inquotes and protect_against_glob only affect whether
5740                         inquotes = ~inquotes;
5741                         p++;
5742                         protect_against_glob = globbing;
5743                         continue;
5744                 }
5745                 if ((unsigned char)*p == CTLESC) {
5746                         p++;
5747 #if DEBUG
5748                         if (*p == '\0')
5749                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5750 #endif
5751                         if (protect_against_glob) {
5752                                 *q++ = '\\';
5753                         }
5754                 } else if (*p == '\\' && !inquotes) {
5755                         /* naked back slash */
5756                         protect_against_glob = 0;
5757                         goto copy;
5758                 }
5759 #if ENABLE_ASH_BASH_COMPAT
5760                 else if (*p == '/' && slash) {
5761                         /* stop handling globbing and mark location of slash */
5762                         globbing = slash = 0;
5763                         *p = CTLESC;
5764                 }
5765 #endif
5766                 protect_against_glob = globbing;
5767  copy:
5768                 *q++ = *p++;
5769         }
5770         *q = '\0';
5771         if (flag & RMESCAPE_GROW) {
5772                 expdest = r;
5773                 STADJUST(q - r + 1, expdest);
5774         }
5775         return r;
5776 }
5777 #define pmatch(a, b) !fnmatch((a), (b), 0)
5778
5779 /*
5780  * Prepare a pattern for a expmeta (internal glob(3)) call.
5781  *
5782  * Returns an stalloced string.
5783  */
5784 static char *
5785 preglob(const char *pattern, int flag)
5786 {
5787         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5788 }
5789
5790 /*
5791  * Put a string on the stack.
5792  */
5793 static void
5794 memtodest(const char *p, size_t len, int syntax, int quotes)
5795 {
5796         char *q;
5797
5798         if (!len)
5799                 return;
5800
5801         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5802
5803         do {
5804                 unsigned char c = *p++;
5805                 if (c) {
5806                         int n = SIT(c, syntax);
5807                         if ((quotes & QUOTES_ESC)
5808                          && ((n == CCTL)
5809                             ||  (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5810                                 && n == CBACK)
5811                                 )
5812                         ) {
5813                                 USTPUTC(CTLESC, q);
5814                         }
5815                 } else if (!(quotes & QUOTES_KEEPNUL))
5816                         continue;
5817                 USTPUTC(c, q);
5818         } while (--len);
5819
5820         expdest = q;
5821 }
5822
5823 static size_t
5824 strtodest(const char *p, int syntax, int quotes)
5825 {
5826         size_t len = strlen(p);
5827         memtodest(p, len, syntax, quotes);
5828         return len;
5829 }
5830
5831 /*
5832  * Record the fact that we have to scan this region of the
5833  * string for IFS characters.
5834  */
5835 static void
5836 recordregion(int start, int end, int nulonly)
5837 {
5838         struct ifsregion *ifsp;
5839
5840         if (ifslastp == NULL) {
5841                 ifsp = &ifsfirst;
5842         } else {
5843                 INT_OFF;
5844                 ifsp = ckzalloc(sizeof(*ifsp));
5845                 /*ifsp->next = NULL; - ckzalloc did it */
5846                 ifslastp->next = ifsp;
5847                 INT_ON;
5848         }
5849         ifslastp = ifsp;
5850         ifslastp->begoff = start;
5851         ifslastp->endoff = end;
5852         ifslastp->nulonly = nulonly;
5853 }
5854
5855 static void
5856 removerecordregions(int endoff)
5857 {
5858         if (ifslastp == NULL)
5859                 return;
5860
5861         if (ifsfirst.endoff > endoff) {
5862                 while (ifsfirst.next) {
5863                         struct ifsregion *ifsp;
5864                         INT_OFF;
5865                         ifsp = ifsfirst.next->next;
5866                         free(ifsfirst.next);
5867                         ifsfirst.next = ifsp;
5868                         INT_ON;
5869                 }
5870                 if (ifsfirst.begoff > endoff) {
5871                         ifslastp = NULL;
5872                 } else {
5873                         ifslastp = &ifsfirst;
5874                         ifsfirst.endoff = endoff;
5875                 }
5876                 return;
5877         }
5878
5879         ifslastp = &ifsfirst;
5880         while (ifslastp->next && ifslastp->next->begoff < endoff)
5881                 ifslastp = ifslastp->next;
5882         while (ifslastp->next) {
5883                 struct ifsregion *ifsp;
5884                 INT_OFF;
5885                 ifsp = ifslastp->next->next;
5886                 free(ifslastp->next);
5887                 ifslastp->next = ifsp;
5888                 INT_ON;
5889         }
5890         if (ifslastp->endoff > endoff)
5891                 ifslastp->endoff = endoff;
5892 }
5893
5894 static char *
5895 exptilde(char *startp, char *p, int flags)
5896 {
5897         unsigned char c;
5898         char *name;
5899         struct passwd *pw;
5900         const char *home;
5901         int quotes = flags & QUOTES_ESC;
5902
5903         name = p + 1;
5904
5905         while ((c = *++p) != '\0') {
5906                 switch (c) {
5907                 case CTLESC:
5908                         return startp;
5909                 case CTLQUOTEMARK:
5910                         return startp;
5911                 case ':':
5912                         if (flags & EXP_VARTILDE)
5913                                 goto done;
5914                         break;
5915                 case '/':
5916                 case CTLENDVAR:
5917                         goto done;
5918                 }
5919         }
5920  done:
5921         *p = '\0';
5922         if (*name == '\0') {
5923                 home = lookupvar("HOME");
5924         } else {
5925                 pw = getpwnam(name);
5926                 if (pw == NULL)
5927                         goto lose;
5928                 home = pw->pw_dir;
5929         }
5930         if (!home || !*home)
5931                 goto lose;
5932         *p = c;
5933         strtodest(home, SQSYNTAX, quotes);
5934         return p;
5935  lose:
5936         *p = c;
5937         return startp;
5938 }
5939
5940 /*
5941  * Execute a command inside back quotes.  If it's a builtin command, we
5942  * want to save its output in a block obtained from malloc.  Otherwise
5943  * we fork off a subprocess and get the output of the command via a pipe.
5944  * Should be called with interrupts off.
5945  */
5946 struct backcmd {                /* result of evalbackcmd */
5947         int fd;                 /* file descriptor to read from */
5948         int nleft;              /* number of chars in buffer */
5949         char *buf;              /* buffer */
5950         struct job *jp;         /* job structure for command */
5951 };
5952
5953 /* These forward decls are needed to use "eval" code for backticks handling: */
5954 #define EV_EXIT 01              /* exit after evaluating tree */
5955 static int evaltree(union node *, int);
5956
5957 static void FAST_FUNC
5958 evalbackcmd(union node *n, struct backcmd *result)
5959 {
5960         int pip[2];
5961         struct job *jp;
5962
5963         result->fd = -1;
5964         result->buf = NULL;
5965         result->nleft = 0;
5966         result->jp = NULL;
5967         if (n == NULL) {
5968                 goto out;
5969         }
5970
5971         if (pipe(pip) < 0)
5972                 ash_msg_and_raise_error("pipe call failed");
5973         jp = makejob(/*n,*/ 1);
5974         if (forkshell(jp, n, FORK_NOJOB) == 0) {
5975                 /* child */
5976                 FORCE_INT_ON;
5977                 close(pip[0]);
5978                 if (pip[1] != 1) {
5979                         /*close(1);*/
5980                         dup2_or_raise(pip[1], 1);
5981                         close(pip[1]);
5982                 }
5983 /* TODO: eflag clearing makes the following not abort:
5984  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
5985  * which is what bash does (unless it is in POSIX mode).
5986  * dash deleted "eflag = 0" line in the commit
5987  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
5988  *  [EVAL] Don't clear eflag in evalbackcmd
5989  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
5990  */
5991                 eflag = 0;
5992                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5993                 /* NOTREACHED */
5994         }
5995         /* parent */
5996         close(pip[1]);
5997         result->fd = pip[0];
5998         result->jp = jp;
5999
6000  out:
6001         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6002                 result->fd, result->buf, result->nleft, result->jp));
6003 }
6004
6005 /*
6006  * Expand stuff in backwards quotes.
6007  */
6008 static void
6009 expbackq(union node *cmd, int flag)
6010 {
6011         struct backcmd in;
6012         int i;
6013         char buf[128];
6014         char *p;
6015         char *dest;
6016         int startloc;
6017         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6018         struct stackmark smark;
6019
6020         INT_OFF;
6021         startloc = expdest - (char *)stackblock();
6022         pushstackmark(&smark, startloc);
6023         evalbackcmd(cmd, &in);
6024         popstackmark(&smark);
6025
6026         p = in.buf;
6027         i = in.nleft;
6028         if (i == 0)
6029                 goto read;
6030         for (;;) {
6031                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6032  read:
6033                 if (in.fd < 0)
6034                         break;
6035                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6036                 TRACE(("expbackq: read returns %d\n", i));
6037                 if (i <= 0)
6038                         break;
6039                 p = buf;
6040         }
6041
6042         free(in.buf);
6043         if (in.fd >= 0) {
6044                 close(in.fd);
6045                 back_exitstatus = waitforjob(in.jp);
6046         }
6047         INT_ON;
6048
6049         /* Eat all trailing newlines */
6050         dest = expdest;
6051         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6052                 STUNPUTC(dest);
6053         expdest = dest;
6054
6055         if (!(flag & EXP_QUOTED))
6056                 recordregion(startloc, dest - (char *)stackblock(), 0);
6057         TRACE(("evalbackq: size:%d:'%.*s'\n",
6058                 (int)((dest - (char *)stackblock()) - startloc),
6059                 (int)((dest - (char *)stackblock()) - startloc),
6060                 stackblock() + startloc));
6061 }
6062
6063 #if ENABLE_SH_MATH_SUPPORT
6064 /*
6065  * Expand arithmetic expression.  Backup to start of expression,
6066  * evaluate, place result in (backed up) result, adjust string position.
6067  */
6068 static void
6069 expari(int flag)
6070 {
6071         char *p, *start;
6072         int begoff;
6073         int len;
6074
6075         /* ifsfree(); */
6076
6077         /*
6078          * This routine is slightly over-complicated for
6079          * efficiency.  Next we scan backwards looking for the
6080          * start of arithmetic.
6081          */
6082         start = stackblock();
6083         p = expdest - 1;
6084         *p = '\0';
6085         p--;
6086         while (1) {
6087                 int esc;
6088
6089                 while ((unsigned char)*p != CTLARI) {
6090                         p--;
6091 #if DEBUG
6092                         if (p < start) {
6093                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6094                         }
6095 #endif
6096                 }
6097
6098                 esc = esclen(start, p);
6099                 if (!(esc % 2)) {
6100                         break;
6101                 }
6102
6103                 p -= esc + 1;
6104         }
6105
6106         begoff = p - start;
6107
6108         removerecordregions(begoff);
6109
6110         expdest = p;
6111
6112         if (flag & QUOTES_ESC)
6113                 rmescapes(p + 1, 0);
6114
6115         len = cvtnum(ash_arith(p + 1));
6116
6117         if (!(flag & EXP_QUOTED))
6118                 recordregion(begoff, begoff + len, 0);
6119 }
6120 #endif
6121
6122 /* argstr needs it */
6123 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6124
6125 /*
6126  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6127  * characters to allow for further processing.  Otherwise treat
6128  * $@ like $* since no splitting will be performed.
6129  *
6130  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6131  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
6132  * for correct expansion of "B=$A" word.
6133  */
6134 static void
6135 argstr(char *p, int flags, struct strlist *var_str_list)
6136 {
6137         static const char spclchars[] ALIGN1 = {
6138                 '=',
6139                 ':',
6140                 CTLQUOTEMARK,
6141                 CTLENDVAR,
6142                 CTLESC,
6143                 CTLVAR,
6144                 CTLBACKQ,
6145 #if ENABLE_SH_MATH_SUPPORT
6146                 CTLENDARI,
6147 #endif
6148                 '\0'
6149         };
6150         const char *reject = spclchars;
6151         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6152         int inquotes;
6153         size_t length;
6154         int startloc;
6155
6156         if (!(flags & EXP_VARTILDE)) {
6157                 reject += 2;
6158         } else if (flags & EXP_VARTILDE2) {
6159                 reject++;
6160         }
6161         inquotes = 0;
6162         length = 0;
6163         if (flags & EXP_TILDE) {
6164                 char *q;
6165
6166                 flags &= ~EXP_TILDE;
6167  tilde:
6168                 q = p;
6169                 if (*q == '~')
6170                         p = exptilde(p, q, flags);
6171         }
6172  start:
6173         startloc = expdest - (char *)stackblock();
6174         for (;;) {
6175                 unsigned char c;
6176
6177                 length += strcspn(p + length, reject);
6178                 c = p[length];
6179                 if (c) {
6180                         if (!(c & 0x80)
6181                         IF_SH_MATH_SUPPORT(|| c == CTLENDARI)
6182                         ) {
6183                                 /* c == '=' || c == ':' || c == CTLENDARI */
6184                                 length++;
6185                         }
6186                 }
6187                 if (length > 0) {
6188                         int newloc;
6189                         expdest = stack_nputstr(p, length, expdest);
6190                         newloc = expdest - (char *)stackblock();
6191                         if (breakall && !inquotes && newloc > startloc) {
6192                                 recordregion(startloc, newloc, 0);
6193                         }
6194                         startloc = newloc;
6195                 }
6196                 p += length + 1;
6197                 length = 0;
6198
6199                 switch (c) {
6200                 case '\0':
6201                         goto breakloop;
6202                 case '=':
6203                         if (flags & EXP_VARTILDE2) {
6204                                 p--;
6205                                 continue;
6206                         }
6207                         flags |= EXP_VARTILDE2;
6208                         reject++;
6209                         /* fall through */
6210                 case ':':
6211                         /*
6212                          * sort of a hack - expand tildes in variable
6213                          * assignments (after the first '=' and after ':'s).
6214                          */
6215                         if (*--p == '~') {
6216                                 goto tilde;
6217                         }
6218                         continue;
6219                 }
6220
6221                 switch (c) {
6222                 case CTLENDVAR: /* ??? */
6223                         goto breakloop;
6224                 case CTLQUOTEMARK:
6225                         inquotes ^= EXP_QUOTED;
6226                         /* "$@" syntax adherence hack */
6227                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6228                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6229                                 goto start;
6230                         }
6231  addquote:
6232                         if (flags & QUOTES_ESC) {
6233                                 p--;
6234                                 length++;
6235                                 startloc++;
6236                         }
6237                         break;
6238                 case CTLESC:
6239                         startloc++;
6240                         length++;
6241
6242                         /*
6243                          * Quoted parameter expansion pattern: remove quote
6244                          * unless inside inner quotes or we have a literal
6245                          * backslash.
6246                          */
6247                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6248                             EXP_QPAT && *p != '\\')
6249                                 break;
6250
6251                         goto addquote;
6252                 case CTLVAR:
6253                         TRACE(("argstr: evalvar('%s')\n", p));
6254                         p = evalvar(p, flags | inquotes, var_str_list);
6255                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6256                         goto start;
6257                 case CTLBACKQ:
6258                         expbackq(argbackq->n, flags | inquotes);
6259                         argbackq = argbackq->next;
6260                         goto start;
6261 #if ENABLE_SH_MATH_SUPPORT
6262                 case CTLENDARI:
6263                         p--;
6264                         expari(flags | inquotes);
6265                         goto start;
6266 #endif
6267                 }
6268         }
6269  breakloop: ;
6270 }
6271
6272 static char *
6273 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6274                 char *pattern, int quotes, int zero)
6275 {
6276         char *loc, *loc2;
6277         char c;
6278
6279         loc = startp;
6280         loc2 = rmesc;
6281         do {
6282                 int match;
6283                 const char *s = loc2;
6284
6285                 c = *loc2;
6286                 if (zero) {
6287                         *loc2 = '\0';
6288                         s = rmesc;
6289                 }
6290                 match = pmatch(pattern, s);
6291
6292                 *loc2 = c;
6293                 if (match)
6294                         return loc;
6295                 if (quotes && (unsigned char)*loc == CTLESC)
6296                         loc++;
6297                 loc++;
6298                 loc2++;
6299         } while (c);
6300         return NULL;
6301 }
6302
6303 static char *
6304 scanright(char *startp, char *rmesc, char *rmescend,
6305                 char *pattern, int quotes, int match_at_start)
6306 {
6307 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6308         int try2optimize = match_at_start;
6309 #endif
6310         int esc = 0;
6311         char *loc;
6312         char *loc2;
6313
6314         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6315          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6316          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6317          * Logic:
6318          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6319          * and on each iteration they go back two/one char until they reach the beginning.
6320          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6321          */
6322         /* TODO: document in what other circumstances we are called. */
6323
6324         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6325                 int match;
6326                 char c = *loc2;
6327                 const char *s = loc2;
6328                 if (match_at_start) {
6329                         *loc2 = '\0';
6330                         s = rmesc;
6331                 }
6332                 match = pmatch(pattern, s);
6333                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6334                 *loc2 = c;
6335                 if (match)
6336                         return loc;
6337 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6338                 if (try2optimize) {
6339                         /* Maybe we can optimize this:
6340                          * if pattern ends with unescaped *, we can avoid checking
6341                          * shorter strings: if "foo*" doesnt match "raw_value_of_v",
6342                          * it wont match truncated "raw_value_of_" strings too.
6343                          */
6344                         unsigned plen = strlen(pattern);
6345                         /* Does it end with "*"? */
6346                         if (plen != 0 && pattern[--plen] == '*') {
6347                                 /* "xxxx*" is not escaped */
6348                                 /* "xxx\*" is escaped */
6349                                 /* "xx\\*" is not escaped */
6350                                 /* "x\\\*" is escaped */
6351                                 int slashes = 0;
6352                                 while (plen != 0 && pattern[--plen] == '\\')
6353                                         slashes++;
6354                                 if (!(slashes & 1))
6355                                         break; /* ends with unescaped "*" */
6356                         }
6357                         try2optimize = 0;
6358                 }
6359 #endif
6360                 loc--;
6361                 if (quotes) {
6362                         if (--esc < 0) {
6363                                 esc = esclen(startp, loc);
6364                         }
6365                         if (esc % 2) {
6366                                 esc--;
6367                                 loc--;
6368                         }
6369                 }
6370         }
6371         return NULL;
6372 }
6373
6374 static void varunset(const char *, const char *, const char *, int) NORETURN;
6375 static void
6376 varunset(const char *end, const char *var, const char *umsg, int varflags)
6377 {
6378         const char *msg;
6379         const char *tail;
6380
6381         tail = nullstr;
6382         msg = "parameter not set";
6383         if (umsg) {
6384                 if ((unsigned char)*end == CTLENDVAR) {
6385                         if (varflags & VSNUL)
6386                                 tail = " or null";
6387                 } else {
6388                         msg = umsg;
6389                 }
6390         }
6391         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6392 }
6393
6394 static const char *
6395 subevalvar(char *p, char *varname, int strloc, int subtype,
6396                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6397 {
6398         struct nodelist *saveargbackq = argbackq;
6399         int quotes = flag & QUOTES_ESC;
6400         char *startp;
6401         char *loc;
6402         char *rmesc, *rmescend;
6403         char *str;
6404         IF_ASH_BASH_COMPAT(char *repl = NULL;)
6405         IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
6406         int amount, resetloc;
6407         IF_ASH_BASH_COMPAT(int workloc;)
6408         int zero;
6409         char *(*scan)(char*, char*, char*, char*, int, int);
6410
6411         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6412         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6413
6414         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6415                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6416                         var_str_list);
6417         STPUTC('\0', expdest);
6418         argbackq = saveargbackq;
6419         startp = (char *)stackblock() + startloc;
6420
6421         switch (subtype) {
6422         case VSASSIGN:
6423                 setvar0(varname, startp);
6424                 amount = startp - expdest;
6425                 STADJUST(amount, expdest);
6426                 return startp;
6427
6428         case VSQUESTION:
6429                 varunset(p, varname, startp, varflags);
6430                 /* NOTREACHED */
6431
6432 #if ENABLE_ASH_BASH_COMPAT
6433         case VSSUBSTR:
6434 //TODO: support more general format ${v:EXPR:EXPR},
6435 // where EXPR follows $(()) rules
6436                 loc = str = stackblock() + strloc;
6437                 /* Read POS in ${var:POS:LEN} */
6438                 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6439                 len = str - startp - 1;
6440
6441                 /* *loc != '\0', guaranteed by parser */
6442                 if (quotes) {
6443                         char *ptr;
6444
6445                         /* Adjust the length by the number of escapes */
6446                         for (ptr = startp; ptr < (str - 1); ptr++) {
6447                                 if ((unsigned char)*ptr == CTLESC) {
6448                                         len--;
6449                                         ptr++;
6450                                 }
6451                         }
6452                 }
6453                 orig_len = len;
6454
6455                 if (*loc++ == ':') {
6456                         /* ${var::LEN} */
6457                         len = number(loc);
6458                 } else {
6459                         /* Skip POS in ${var:POS:LEN} */
6460                         len = orig_len;
6461                         while (*loc && *loc != ':') {
6462                                 /* TODO?
6463                                  * bash complains on: var=qwe; echo ${var:1a:123}
6464                                 if (!isdigit(*loc))
6465                                         ash_msg_and_raise_error(msg_illnum, str);
6466                                  */
6467                                 loc++;
6468                         }
6469                         if (*loc++ == ':') {
6470                                 len = number(loc);
6471                         }
6472                 }
6473                 if (pos < 0) {
6474                         /* ${VAR:$((-n)):l} starts n chars from the end */
6475                         pos = orig_len + pos;
6476                 }
6477                 if ((unsigned)pos >= orig_len) {
6478                         /* apart from obvious ${VAR:999999:l},
6479                          * covers ${VAR:$((-9999999)):l} - result is ""
6480                          * (bash-compat)
6481                          */
6482                         pos = 0;
6483                         len = 0;
6484                 }
6485                 if (len > (orig_len - pos))
6486                         len = orig_len - pos;
6487
6488                 for (str = startp; pos; str++, pos--) {
6489                         if (quotes && (unsigned char)*str == CTLESC)
6490                                 str++;
6491                 }
6492                 for (loc = startp; len; len--) {
6493                         if (quotes && (unsigned char)*str == CTLESC)
6494                                 *loc++ = *str++;
6495                         *loc++ = *str++;
6496                 }
6497                 *loc = '\0';
6498                 amount = loc - expdest;
6499                 STADJUST(amount, expdest);
6500                 return loc;
6501 #endif
6502         }
6503
6504         resetloc = expdest - (char *)stackblock();
6505
6506         /* We'll comeback here if we grow the stack while handling
6507          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6508          * stack will need rebasing, and we'll need to remove our work
6509          * areas each time
6510          */
6511  IF_ASH_BASH_COMPAT(restart:)
6512
6513         amount = expdest - ((char *)stackblock() + resetloc);
6514         STADJUST(-amount, expdest);
6515         startp = (char *)stackblock() + startloc;
6516
6517         rmesc = startp;
6518         rmescend = (char *)stackblock() + strloc;
6519         if (quotes) {
6520                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6521                 if (rmesc != startp) {
6522                         rmescend = expdest;
6523                         startp = (char *)stackblock() + startloc;
6524                 }
6525         }
6526         rmescend--;
6527         str = (char *)stackblock() + strloc;
6528         /*
6529          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6530          * The result is a_\_z_c (not a\_\_z_c)!
6531          *
6532          * The search pattern and replace string treat backslashes differently!
6533          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6534          * and string.  It's only used on the first call.
6535          */
6536         preglob(str, IF_ASH_BASH_COMPAT(
6537                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6538                         RMESCAPE_SLASH :) 0);
6539
6540 #if ENABLE_ASH_BASH_COMPAT
6541         workloc = expdest - (char *)stackblock();
6542         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6543                 char *idx, *end;
6544
6545                 if (!repl) {
6546                         repl = strchr(str, CTLESC);
6547                         if (repl)
6548                                 *repl++ = '\0';
6549                         else
6550                                 repl = nullstr;
6551                 }
6552                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6553
6554                 /* If there's no pattern to match, return the expansion unmolested */
6555                 if (str[0] == '\0')
6556                         return NULL;
6557
6558                 len = 0;
6559                 idx = startp;
6560                 end = str - 1;
6561                 while (idx < end) {
6562  try_to_match:
6563                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6564                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6565                         if (!loc) {
6566                                 /* No match, advance */
6567                                 char *restart_detect = stackblock();
6568  skip_matching:
6569                                 STPUTC(*idx, expdest);
6570                                 if (quotes && (unsigned char)*idx == CTLESC) {
6571                                         idx++;
6572                                         len++;
6573                                         STPUTC(*idx, expdest);
6574                                 }
6575                                 if (stackblock() != restart_detect)
6576                                         goto restart;
6577                                 idx++;
6578                                 len++;
6579                                 rmesc++;
6580                                 /* continue; - prone to quadratic behavior, smarter code: */
6581                                 if (idx >= end)
6582                                         break;
6583                                 if (str[0] == '*') {
6584                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6585                                          * it would never match "ong_string" etc, no point in trying.
6586                                          */
6587                                         goto skip_matching;
6588                                 }
6589                                 goto try_to_match;
6590                         }
6591
6592                         if (subtype == VSREPLACEALL) {
6593                                 while (idx < loc) {
6594                                         if (quotes && (unsigned char)*idx == CTLESC)
6595                                                 idx++;
6596                                         idx++;
6597                                         rmesc++;
6598                                 }
6599                         } else {
6600                                 idx = loc;
6601                         }
6602
6603                         //bb_error_msg("repl:'%s'", repl);
6604                         for (loc = (char*)repl; *loc; loc++) {
6605                                 char *restart_detect = stackblock();
6606                                 if (quotes && *loc == '\\') {
6607                                         STPUTC(CTLESC, expdest);
6608                                         len++;
6609                                 }
6610                                 STPUTC(*loc, expdest);
6611                                 if (stackblock() != restart_detect)
6612                                         goto restart;
6613                                 len++;
6614                         }
6615
6616                         if (subtype == VSREPLACE) {
6617                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6618                                 while (*idx) {
6619                                         char *restart_detect = stackblock();
6620                                         STPUTC(*idx, expdest);
6621                                         if (stackblock() != restart_detect)
6622                                                 goto restart;
6623                                         len++;
6624                                         idx++;
6625                                 }
6626                                 break;
6627                         }
6628                 }
6629
6630                 /* We've put the replaced text into a buffer at workloc, now
6631                  * move it to the right place and adjust the stack.
6632                  */
6633                 STPUTC('\0', expdest);
6634                 startp = (char *)stackblock() + startloc;
6635                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6636                 //bb_error_msg("startp:'%s'", startp);
6637                 amount = expdest - (startp + len);
6638                 STADJUST(-amount, expdest);
6639                 return startp;
6640         }
6641 #endif /* ENABLE_ASH_BASH_COMPAT */
6642
6643         subtype -= VSTRIMRIGHT;
6644 #if DEBUG
6645         if (subtype < 0 || subtype > 7)
6646                 abort();
6647 #endif
6648         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6649         zero = subtype >> 1;
6650         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6651         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6652
6653         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6654         if (loc) {
6655                 if (zero) {
6656                         memmove(startp, loc, str - loc);
6657                         loc = startp + (str - loc) - 1;
6658                 }
6659                 *loc = '\0';
6660                 amount = loc - expdest;
6661                 STADJUST(amount, expdest);
6662         }
6663         return loc;
6664 }
6665
6666 /*
6667  * Add the value of a specialized variable to the stack string.
6668  * name parameter (examples):
6669  * ash -c 'echo $1'      name:'1='
6670  * ash -c 'echo $qwe'    name:'qwe='
6671  * ash -c 'echo $$'      name:'$='
6672  * ash -c 'echo ${$}'    name:'$='
6673  * ash -c 'echo ${$##q}' name:'$=q'
6674  * ash -c 'echo ${#$}'   name:'$='
6675  * note: examples with bad shell syntax:
6676  * ash -c 'echo ${#$1}'  name:'$=1'
6677  * ash -c 'echo ${#1#}'  name:'1=#'
6678  */
6679 static NOINLINE ssize_t
6680 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6681 {
6682         const char *p;
6683         int num;
6684         int i;
6685         ssize_t len = 0;
6686         int sep;
6687         int quoted = *quotedp;
6688         int subtype = varflags & VSTYPE;
6689         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6690         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6691         int syntax;
6692
6693         sep = (flags & EXP_FULL) << CHAR_BIT;
6694         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6695
6696         switch (*name) {
6697         case '$':
6698                 num = rootpid;
6699                 goto numvar;
6700         case '?':
6701                 num = exitstatus;
6702                 goto numvar;
6703         case '#':
6704                 num = shellparam.nparam;
6705                 goto numvar;
6706         case '!':
6707                 num = backgndpid;
6708                 if (num == 0)
6709                         return -1;
6710  numvar:
6711                 len = cvtnum(num);
6712                 goto check_1char_name;
6713         case '-':
6714                 expdest = makestrspace(NOPTS, expdest);
6715                 for (i = NOPTS - 1; i >= 0; i--) {
6716                         if (optlist[i]) {
6717                                 USTPUTC(optletters(i), expdest);
6718                                 len++;
6719                         }
6720                 }
6721  check_1char_name:
6722 #if 0
6723                 /* handles cases similar to ${#$1} */
6724                 if (name[2] != '\0')
6725                         raise_error_syntax("bad substitution");
6726 #endif
6727                 break;
6728         case '@':
6729                 if (quoted && sep)
6730                         goto param;
6731                 /* fall through */
6732         case '*': {
6733                 char **ap;
6734                 char sepc;
6735
6736                 if (quoted)
6737                         sep = 0;
6738                 sep |= ifsset() ? ifsval()[0] : ' ';
6739  param:
6740                 sepc = sep;
6741                 *quotedp = !sepc;
6742                 ap = shellparam.p;
6743                 if (!ap)
6744                         return -1;
6745                 while ((p = *ap++) != NULL) {
6746                         len += strtodest(p, syntax, quotes);
6747
6748                         if (*ap && sep) {
6749                                 len++;
6750                                 memtodest(&sepc, 1, syntax, quotes);
6751                         }
6752                 }
6753                 break;
6754         } /* case '*' */
6755         case '0':
6756         case '1':
6757         case '2':
6758         case '3':
6759         case '4':
6760         case '5':
6761         case '6':
6762         case '7':
6763         case '8':
6764         case '9':
6765                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6766                 if (num < 0 || num > shellparam.nparam)
6767                         return -1;
6768                 p = num ? shellparam.p[num - 1] : arg0;
6769                 goto value;
6770         default:
6771                 /* NB: name has form "VAR=..." */
6772
6773                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6774                  * which should be considered before we check variables. */
6775                 if (var_str_list) {
6776                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6777                         p = NULL;
6778                         do {
6779                                 char *str, *eq;
6780                                 str = var_str_list->text;
6781                                 eq = strchr(str, '=');
6782                                 if (!eq) /* stop at first non-assignment */
6783                                         break;
6784                                 eq++;
6785                                 if (name_len == (unsigned)(eq - str)
6786                                  && strncmp(str, name, name_len) == 0
6787                                 ) {
6788                                         p = eq;
6789                                         /* goto value; - WRONG! */
6790                                         /* think "A=1 A=2 B=$A" */
6791                                 }
6792                                 var_str_list = var_str_list->next;
6793                         } while (var_str_list);
6794                         if (p)
6795                                 goto value;
6796                 }
6797                 p = lookupvar(name);
6798  value:
6799                 if (!p)
6800                         return -1;
6801
6802                 len = strtodest(p, syntax, quotes);
6803 #if ENABLE_UNICODE_SUPPORT
6804                 if (subtype == VSLENGTH && len > 0) {
6805                         reinit_unicode_for_ash();
6806                         if (unicode_status == UNICODE_ON) {
6807                                 STADJUST(-len, expdest);
6808                                 discard = 0;
6809                                 len = unicode_strlen(p);
6810                         }
6811                 }
6812 #endif
6813                 break;
6814         }
6815
6816         if (discard)
6817                 STADJUST(-len, expdest);
6818         return len;
6819 }
6820
6821 /*
6822  * Expand a variable, and return a pointer to the next character in the
6823  * input string.
6824  */
6825 static char *
6826 evalvar(char *p, int flag, struct strlist *var_str_list)
6827 {
6828         char varflags;
6829         char subtype;
6830         int quoted;
6831         char easy;
6832         char *var;
6833         int patloc;
6834         int startloc;
6835         ssize_t varlen;
6836
6837         varflags = (unsigned char) *p++;
6838         subtype = varflags & VSTYPE;
6839
6840         if (!subtype)
6841                 raise_error_syntax("bad substitution");
6842
6843         quoted = flag & EXP_QUOTED;
6844         var = p;
6845         easy = (!quoted || (*var == '@' && shellparam.nparam));
6846         startloc = expdest - (char *)stackblock();
6847         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
6848
6849  again:
6850         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
6851         if (varflags & VSNUL)
6852                 varlen--;
6853
6854         if (subtype == VSPLUS) {
6855                 varlen = -1 - varlen;
6856                 goto vsplus;
6857         }
6858
6859         if (subtype == VSMINUS) {
6860  vsplus:
6861                 if (varlen < 0) {
6862                         argstr(
6863                                 p,
6864                                 flag | EXP_TILDE | EXP_WORD,
6865                                 var_str_list
6866                         );
6867                         goto end;
6868                 }
6869                 goto record;
6870         }
6871
6872         if (subtype == VSASSIGN || subtype == VSQUESTION) {
6873                 if (varlen >= 0)
6874                         goto record;
6875
6876                 subevalvar(p, var, 0, subtype, startloc, varflags,
6877                            flag & ~QUOTES_ESC, var_str_list);
6878                 varflags &= ~VSNUL;
6879                 /*
6880                  * Remove any recorded regions beyond
6881                  * start of variable
6882                  */
6883                 removerecordregions(startloc);
6884                 goto again;
6885         }
6886
6887         if (varlen < 0 && uflag)
6888                 varunset(p, var, 0, 0);
6889
6890         if (subtype == VSLENGTH) {
6891                 cvtnum(varlen > 0 ? varlen : 0);
6892                 goto record;
6893         }
6894
6895         if (subtype == VSNORMAL) {
6896  record:
6897                 if (!easy)
6898                         goto end;
6899                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6900                 goto end;
6901         }
6902
6903 #if DEBUG
6904         switch (subtype) {
6905         case VSTRIMLEFT:
6906         case VSTRIMLEFTMAX:
6907         case VSTRIMRIGHT:
6908         case VSTRIMRIGHTMAX:
6909 #if ENABLE_ASH_BASH_COMPAT
6910         case VSSUBSTR:
6911         case VSREPLACE:
6912         case VSREPLACEALL:
6913 #endif
6914                 break;
6915         default:
6916                 abort();
6917         }
6918 #endif
6919
6920         if (varlen >= 0) {
6921                 /*
6922                  * Terminate the string and start recording the pattern
6923                  * right after it
6924                  */
6925                 STPUTC('\0', expdest);
6926                 patloc = expdest - (char *)stackblock();
6927                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
6928                                 startloc, varflags, flag, var_str_list)) {
6929                         int amount = expdest - (
6930                                 (char *)stackblock() + patloc - 1
6931                         );
6932                         STADJUST(-amount, expdest);
6933                 }
6934                 /* Remove any recorded regions beyond start of variable */
6935                 removerecordregions(startloc);
6936                 goto record;
6937         }
6938
6939  end:
6940         if (subtype != VSNORMAL) {      /* skip to end of alternative */
6941                 int nesting = 1;
6942                 for (;;) {
6943                         unsigned char c = *p++;
6944                         if (c == CTLESC)
6945                                 p++;
6946                         else if (c == CTLBACKQ) {
6947                                 if (varlen >= 0)
6948                                         argbackq = argbackq->next;
6949                         } else if (c == CTLVAR) {
6950                                 if ((*p++ & VSTYPE) != VSNORMAL)
6951                                         nesting++;
6952                         } else if (c == CTLENDVAR) {
6953                                 if (--nesting == 0)
6954                                         break;
6955                         }
6956                 }
6957         }
6958         return p;
6959 }
6960
6961 /*
6962  * Add a file name to the list.
6963  */
6964 static void
6965 addfname(const char *name)
6966 {
6967         struct strlist *sp;
6968
6969         sp = stzalloc(sizeof(*sp));
6970         sp->text = sstrdup(name);
6971         *exparg.lastp = sp;
6972         exparg.lastp = &sp->next;
6973 }
6974
6975 /* If we want to use glob() from libc... */
6976 #if !ENABLE_ASH_INTERNAL_GLOB
6977
6978 /* Add the result of glob() to the list */
6979 static void
6980 addglob(const glob_t *pglob)
6981 {
6982         char **p = pglob->gl_pathv;
6983
6984         do {
6985                 addfname(*p);
6986         } while (*++p);
6987 }
6988 static void
6989 expandmeta(struct strlist *str /*, int flag*/)
6990 {
6991         /* TODO - EXP_REDIR */
6992
6993         while (str) {
6994                 char *p;
6995                 glob_t pglob;
6996                 int i;
6997
6998                 if (fflag)
6999                         goto nometa;
7000                 INT_OFF;
7001                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7002 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7003 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7004 //
7005 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7006 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7007 // Which means you need to unescape the string, right? Not so fast:
7008 // if there _is_ a file named "file\?" (with backslash), it is returned
7009 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7010 // You DONT KNOW by looking at the result whether you need to unescape it.
7011 //
7012 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7013 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7014 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7015 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7016 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7017 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7018                 i = glob(p, 0, NULL, &pglob);
7019                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7020                 if (p != str->text)
7021                         free(p);
7022                 switch (i) {
7023                 case 0:
7024 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7025                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7026                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7027                                 goto nometa2;
7028 #endif
7029                         addglob(&pglob);
7030                         globfree(&pglob);
7031                         INT_ON;
7032                         break;
7033                 case GLOB_NOMATCH:
7034  //nometa2:
7035                         globfree(&pglob);
7036                         INT_ON;
7037  nometa:
7038                         *exparg.lastp = str;
7039                         rmescapes(str->text, 0);
7040                         exparg.lastp = &str->next;
7041                         break;
7042                 default:        /* GLOB_NOSPACE */
7043                         globfree(&pglob);
7044                         INT_ON;
7045                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7046                 }
7047                 str = str->next;
7048         }
7049 }
7050
7051 #else
7052 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7053
7054 /*
7055  * Do metacharacter (i.e. *, ?, [...]) expansion.
7056  */
7057 static void
7058 expmeta(char *expdir, char *enddir, char *name)
7059 {
7060         char *p;
7061         const char *cp;
7062         char *start;
7063         char *endname;
7064         int metaflag;
7065         struct stat statb;
7066         DIR *dirp;
7067         struct dirent *dp;
7068         int atend;
7069         int matchdot;
7070         int esc;
7071
7072         metaflag = 0;
7073         start = name;
7074         for (p = name; esc = 0, *p; p += esc + 1) {
7075                 if (*p == '*' || *p == '?')
7076                         metaflag = 1;
7077                 else if (*p == '[') {
7078                         char *q = p + 1;
7079                         if (*q == '!')
7080                                 q++;
7081                         for (;;) {
7082                                 if (*q == '\\')
7083                                         q++;
7084                                 if (*q == '/' || *q == '\0')
7085                                         break;
7086                                 if (*++q == ']') {
7087                                         metaflag = 1;
7088                                         break;
7089                                 }
7090                         }
7091                 } else {
7092                         if (*p == '\\')
7093                                 esc++;
7094                         if (p[esc] == '/') {
7095                                 if (metaflag)
7096                                         break;
7097                                 start = p + esc + 1;
7098                         }
7099                 }
7100         }
7101         if (metaflag == 0) {    /* we've reached the end of the file name */
7102                 if (enddir != expdir)
7103                         metaflag++;
7104                 p = name;
7105                 do {
7106                         if (*p == '\\')
7107                                 p++;
7108                         *enddir++ = *p;
7109                 } while (*p++);
7110                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7111                         addfname(expdir);
7112                 return;
7113         }
7114         endname = p;
7115         if (name < start) {
7116                 p = name;
7117                 do {
7118                         if (*p == '\\')
7119                                 p++;
7120                         *enddir++ = *p++;
7121                 } while (p < start);
7122         }
7123         if (enddir == expdir) {
7124                 cp = ".";
7125         } else if (enddir == expdir + 1 && *expdir == '/') {
7126                 cp = "/";
7127         } else {
7128                 cp = expdir;
7129                 enddir[-1] = '\0';
7130         }
7131         dirp = opendir(cp);
7132         if (dirp == NULL)
7133                 return;
7134         if (enddir != expdir)
7135                 enddir[-1] = '/';
7136         if (*endname == 0) {
7137                 atend = 1;
7138         } else {
7139                 atend = 0;
7140                 *endname = '\0';
7141                 endname += esc + 1;
7142         }
7143         matchdot = 0;
7144         p = start;
7145         if (*p == '\\')
7146                 p++;
7147         if (*p == '.')
7148                 matchdot++;
7149         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7150                 if (dp->d_name[0] == '.' && !matchdot)
7151                         continue;
7152                 if (pmatch(start, dp->d_name)) {
7153                         if (atend) {
7154                                 strcpy(enddir, dp->d_name);
7155                                 addfname(expdir);
7156                         } else {
7157                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7158                                         continue;
7159                                 p[-1] = '/';
7160                                 expmeta(expdir, p, endname);
7161                         }
7162                 }
7163         }
7164         closedir(dirp);
7165         if (!atend)
7166                 endname[-esc - 1] = esc ? '\\' : '/';
7167 }
7168
7169 static struct strlist *
7170 msort(struct strlist *list, int len)
7171 {
7172         struct strlist *p, *q = NULL;
7173         struct strlist **lpp;
7174         int half;
7175         int n;
7176
7177         if (len <= 1)
7178                 return list;
7179         half = len >> 1;
7180         p = list;
7181         for (n = half; --n >= 0;) {
7182                 q = p;
7183                 p = p->next;
7184         }
7185         q->next = NULL;                 /* terminate first half of list */
7186         q = msort(list, half);          /* sort first half of list */
7187         p = msort(p, len - half);               /* sort second half */
7188         lpp = &list;
7189         for (;;) {
7190 #if ENABLE_LOCALE_SUPPORT
7191                 if (strcoll(p->text, q->text) < 0)
7192 #else
7193                 if (strcmp(p->text, q->text) < 0)
7194 #endif
7195                                                 {
7196                         *lpp = p;
7197                         lpp = &p->next;
7198                         p = *lpp;
7199                         if (p == NULL) {
7200                                 *lpp = q;
7201                                 break;
7202                         }
7203                 } else {
7204                         *lpp = q;
7205                         lpp = &q->next;
7206                         q = *lpp;
7207                         if (q == NULL) {
7208                                 *lpp = p;
7209                                 break;
7210                         }
7211                 }
7212         }
7213         return list;
7214 }
7215
7216 /*
7217  * Sort the results of file name expansion.  It calculates the number of
7218  * strings to sort and then calls msort (short for merge sort) to do the
7219  * work.
7220  */
7221 static struct strlist *
7222 expsort(struct strlist *str)
7223 {
7224         int len;
7225         struct strlist *sp;
7226
7227         len = 0;
7228         for (sp = str; sp; sp = sp->next)
7229                 len++;
7230         return msort(str, len);
7231 }
7232
7233 static void
7234 expandmeta(struct strlist *str /*, int flag*/)
7235 {
7236         static const char metachars[] ALIGN1 = {
7237                 '*', '?', '[', 0
7238         };
7239         /* TODO - EXP_REDIR */
7240
7241         while (str) {
7242                 char *expdir;
7243                 struct strlist **savelastp;
7244                 struct strlist *sp;
7245                 char *p;
7246
7247                 if (fflag)
7248                         goto nometa;
7249                 if (!strpbrk(str->text, metachars))
7250                         goto nometa;
7251                 savelastp = exparg.lastp;
7252
7253                 INT_OFF;
7254                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7255                 {
7256                         int i = strlen(str->text);
7257 //BUGGY estimation of how long expanded name can be
7258                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7259                 }
7260                 expmeta(expdir, expdir, p);
7261                 free(expdir);
7262                 if (p != str->text)
7263                         free(p);
7264                 INT_ON;
7265                 if (exparg.lastp == savelastp) {
7266                         /*
7267                          * no matches
7268                          */
7269  nometa:
7270                         *exparg.lastp = str;
7271                         rmescapes(str->text, 0);
7272                         exparg.lastp = &str->next;
7273                 } else {
7274                         *exparg.lastp = NULL;
7275                         *savelastp = sp = expsort(*savelastp);
7276                         while (sp->next != NULL)
7277                                 sp = sp->next;
7278                         exparg.lastp = &sp->next;
7279                 }
7280                 str = str->next;
7281         }
7282 }
7283 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7284
7285 /*
7286  * Perform variable substitution and command substitution on an argument,
7287  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7288  * perform splitting and file name expansion.  When arglist is NULL, perform
7289  * here document expansion.
7290  */
7291 static void
7292 expandarg(union node *arg, struct arglist *arglist, int flag)
7293 {
7294         struct strlist *sp;
7295         char *p;
7296
7297         argbackq = arg->narg.backquote;
7298         STARTSTACKSTR(expdest);
7299         ifsfirst.next = NULL;
7300         ifslastp = NULL;
7301         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7302         argstr(arg->narg.text, flag,
7303                         /* var_str_list: */ arglist ? arglist->list : NULL);
7304         p = _STPUTC('\0', expdest);
7305         expdest = p - 1;
7306         if (arglist == NULL) {
7307                 return;                 /* here document expanded */
7308         }
7309         p = grabstackstr(p);
7310         TRACE(("expandarg: p:'%s'\n", p));
7311         exparg.lastp = &exparg.list;
7312         /*
7313          * TODO - EXP_REDIR
7314          */
7315         if (flag & EXP_FULL) {
7316                 ifsbreakup(p, &exparg);
7317                 *exparg.lastp = NULL;
7318                 exparg.lastp = &exparg.list;
7319                 expandmeta(exparg.list /*, flag*/);
7320         } else {
7321                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7322                         rmescapes(p, 0);
7323                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7324                 }
7325                 sp = stzalloc(sizeof(*sp));
7326                 sp->text = p;
7327                 *exparg.lastp = sp;
7328                 exparg.lastp = &sp->next;
7329         }
7330         if (ifsfirst.next)
7331                 ifsfree();
7332         *exparg.lastp = NULL;
7333         if (exparg.list) {
7334                 *arglist->lastp = exparg.list;
7335                 arglist->lastp = exparg.lastp;
7336         }
7337 }
7338
7339 /*
7340  * Expand shell variables and backquotes inside a here document.
7341  */
7342 static void
7343 expandhere(union node *arg, int fd)
7344 {
7345         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7346         full_write(fd, stackblock(), expdest - (char *)stackblock());
7347 }
7348
7349 /*
7350  * Returns true if the pattern matches the string.
7351  */
7352 static int
7353 patmatch(char *pattern, const char *string)
7354 {
7355         return pmatch(preglob(pattern, 0), string);
7356 }
7357
7358 /*
7359  * See if a pattern matches in a case statement.
7360  */
7361 static int
7362 casematch(union node *pattern, char *val)
7363 {
7364         struct stackmark smark;
7365         int result;
7366
7367         setstackmark(&smark);
7368         argbackq = pattern->narg.backquote;
7369         STARTSTACKSTR(expdest);
7370         ifslastp = NULL;
7371         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7372                         /* var_str_list: */ NULL);
7373         STACKSTRNUL(expdest);
7374         result = patmatch(stackblock(), val);
7375         popstackmark(&smark);
7376         return result;
7377 }
7378
7379
7380 /* ============ find_command */
7381
7382 struct builtincmd {
7383         const char *name;
7384         int (*builtin)(int, char **) FAST_FUNC;
7385         /* unsigned flags; */
7386 };
7387 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7388 /* "regular" builtins always take precedence over commands,
7389  * regardless of PATH=....%builtin... position */
7390 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7391 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7392
7393 struct cmdentry {
7394         smallint cmdtype;       /* CMDxxx */
7395         union param {
7396                 int index;
7397                 /* index >= 0 for commands without path (slashes) */
7398                 /* (TODO: what exactly does the value mean? PATH position?) */
7399                 /* index == -1 for commands with slashes */
7400                 /* index == (-2 - applet_no) for NOFORK applets */
7401                 const struct builtincmd *cmd;
7402                 struct funcnode *func;
7403         } u;
7404 };
7405 /* values of cmdtype */
7406 #define CMDUNKNOWN      -1      /* no entry in table for command */
7407 #define CMDNORMAL       0       /* command is an executable program */
7408 #define CMDFUNCTION     1       /* command is a shell function */
7409 #define CMDBUILTIN      2       /* command is a shell builtin */
7410
7411 /* action to find_command() */
7412 #define DO_ERR          0x01    /* prints errors */
7413 #define DO_ABS          0x02    /* checks absolute paths */
7414 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7415 #define DO_ALTPATH      0x08    /* using alternate path */
7416 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7417
7418 static void find_command(char *, struct cmdentry *, int, const char *);
7419
7420
7421 /* ============ Hashing commands */
7422
7423 /*
7424  * When commands are first encountered, they are entered in a hash table.
7425  * This ensures that a full path search will not have to be done for them
7426  * on each invocation.
7427  *
7428  * We should investigate converting to a linear search, even though that
7429  * would make the command name "hash" a misnomer.
7430  */
7431
7432 struct tblentry {
7433         struct tblentry *next;  /* next entry in hash chain */
7434         union param param;      /* definition of builtin function */
7435         smallint cmdtype;       /* CMDxxx */
7436         char rehash;            /* if set, cd done since entry created */
7437         char cmdname[1];        /* name of command */
7438 };
7439
7440 static struct tblentry **cmdtable;
7441 #define INIT_G_cmdtable() do { \
7442         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7443 } while (0)
7444
7445 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7446
7447
7448 static void
7449 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7450 {
7451 #if ENABLE_FEATURE_SH_STANDALONE
7452         if (applet_no >= 0) {
7453                 if (APPLET_IS_NOEXEC(applet_no)) {
7454                         clearenv();
7455                         while (*envp)
7456                                 putenv(*envp++);
7457                         run_applet_no_and_exit(applet_no, argv);
7458                 }
7459                 /* re-exec ourselves with the new arguments */
7460                 execve(bb_busybox_exec_path, argv, envp);
7461                 /* If they called chroot or otherwise made the binary no longer
7462                  * executable, fall through */
7463         }
7464 #endif
7465
7466  repeat:
7467 #ifdef SYSV
7468         do {
7469                 execve(cmd, argv, envp);
7470         } while (errno == EINTR);
7471 #else
7472         execve(cmd, argv, envp);
7473 #endif
7474         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7475                 /* Run "cmd" as a shell script:
7476                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7477                  * "If the execve() function fails with ENOEXEC, the shell
7478                  * shall execute a command equivalent to having a shell invoked
7479                  * with the command name as its first operand,
7480                  * with any remaining arguments passed to the new shell"
7481                  *
7482                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7483                  * just call ourselves.
7484                  *
7485                  * Note that bash reads ~80 chars of the file, and if it sees
7486                  * a zero byte before it sees newline, it doesn't try to
7487                  * interpret it, but fails with "cannot execute binary file"
7488                  * message and exit code 126. For one, this prevents attempts
7489                  * to interpret foreign ELF binaries as shell scripts.
7490                  */
7491                 argv[0] = cmd;
7492                 cmd = (char*) bb_busybox_exec_path;
7493                 /* NB: this is only possible because all callers of shellexec()
7494                  * ensure that the argv[-1] slot exists!
7495                  */
7496                 argv--;
7497                 argv[0] = (char*) "ash";
7498                 goto repeat;
7499         }
7500 }
7501
7502 /*
7503  * Exec a program.  Never returns.  If you change this routine, you may
7504  * have to change the find_command routine as well.
7505  * argv[-1] must exist and be writable! See tryexec() for why.
7506  */
7507 static void shellexec(char **, const char *, int) NORETURN;
7508 static void
7509 shellexec(char **argv, const char *path, int idx)
7510 {
7511         char *cmdname;
7512         int e;
7513         char **envp;
7514         int exerrno;
7515         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7516
7517         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7518         if (strchr(argv[0], '/') != NULL
7519 #if ENABLE_FEATURE_SH_STANDALONE
7520          || (applet_no = find_applet_by_name(argv[0])) >= 0
7521 #endif
7522         ) {
7523                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7524                 if (applet_no >= 0) {
7525                         /* We tried execing ourself, but it didn't work.
7526                          * Maybe /proc/self/exe doesn't exist?
7527                          * Try $PATH search.
7528                          */
7529                         goto try_PATH;
7530                 }
7531                 e = errno;
7532         } else {
7533  try_PATH:
7534                 e = ENOENT;
7535                 while ((cmdname = path_advance(&path, argv[0])) != NULL) {
7536                         if (--idx < 0 && pathopt == NULL) {
7537                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7538                                 if (errno != ENOENT && errno != ENOTDIR)
7539                                         e = errno;
7540                         }
7541                         stunalloc(cmdname);
7542                 }
7543         }
7544
7545         /* Map to POSIX errors */
7546         switch (e) {
7547         case EACCES:
7548                 exerrno = 126;
7549                 break;
7550         case ENOENT:
7551                 exerrno = 127;
7552                 break;
7553         default:
7554                 exerrno = 2;
7555                 break;
7556         }
7557         exitstatus = exerrno;
7558         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7559                 argv[0], e, suppress_int));
7560         ash_msg_and_raise(EXEXIT, "%s: %s", argv[0], errmsg(e, "not found"));
7561         /* NOTREACHED */
7562 }
7563
7564 static void
7565 printentry(struct tblentry *cmdp)
7566 {
7567         int idx;
7568         const char *path;
7569         char *name;
7570
7571         idx = cmdp->param.index;
7572         path = pathval();
7573         do {
7574                 name = path_advance(&path, cmdp->cmdname);
7575                 stunalloc(name);
7576         } while (--idx >= 0);
7577         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7578 }
7579
7580 /*
7581  * Clear out command entries.  The argument specifies the first entry in
7582  * PATH which has changed.
7583  */
7584 static void
7585 clearcmdentry(int firstchange)
7586 {
7587         struct tblentry **tblp;
7588         struct tblentry **pp;
7589         struct tblentry *cmdp;
7590
7591         INT_OFF;
7592         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7593                 pp = tblp;
7594                 while ((cmdp = *pp) != NULL) {
7595                         if ((cmdp->cmdtype == CMDNORMAL &&
7596                              cmdp->param.index >= firstchange)
7597                          || (cmdp->cmdtype == CMDBUILTIN &&
7598                              builtinloc >= firstchange)
7599                         ) {
7600                                 *pp = cmdp->next;
7601                                 free(cmdp);
7602                         } else {
7603                                 pp = &cmdp->next;
7604                         }
7605                 }
7606         }
7607         INT_ON;
7608 }
7609
7610 /*
7611  * Locate a command in the command hash table.  If "add" is nonzero,
7612  * add the command to the table if it is not already present.  The
7613  * variable "lastcmdentry" is set to point to the address of the link
7614  * pointing to the entry, so that delete_cmd_entry can delete the
7615  * entry.
7616  *
7617  * Interrupts must be off if called with add != 0.
7618  */
7619 static struct tblentry **lastcmdentry;
7620
7621 static struct tblentry *
7622 cmdlookup(const char *name, int add)
7623 {
7624         unsigned int hashval;
7625         const char *p;
7626         struct tblentry *cmdp;
7627         struct tblentry **pp;
7628
7629         p = name;
7630         hashval = (unsigned char)*p << 4;
7631         while (*p)
7632                 hashval += (unsigned char)*p++;
7633         hashval &= 0x7FFF;
7634         pp = &cmdtable[hashval % CMDTABLESIZE];
7635         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7636                 if (strcmp(cmdp->cmdname, name) == 0)
7637                         break;
7638                 pp = &cmdp->next;
7639         }
7640         if (add && cmdp == NULL) {
7641                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7642                                 + strlen(name)
7643                                 /* + 1 - already done because
7644                                  * tblentry::cmdname is char[1] */);
7645                 /*cmdp->next = NULL; - ckzalloc did it */
7646                 cmdp->cmdtype = CMDUNKNOWN;
7647                 strcpy(cmdp->cmdname, name);
7648         }
7649         lastcmdentry = pp;
7650         return cmdp;
7651 }
7652
7653 /*
7654  * Delete the command entry returned on the last lookup.
7655  */
7656 static void
7657 delete_cmd_entry(void)
7658 {
7659         struct tblentry *cmdp;
7660
7661         INT_OFF;
7662         cmdp = *lastcmdentry;
7663         *lastcmdentry = cmdp->next;
7664         if (cmdp->cmdtype == CMDFUNCTION)
7665                 freefunc(cmdp->param.func);
7666         free(cmdp);
7667         INT_ON;
7668 }
7669
7670 /*
7671  * Add a new command entry, replacing any existing command entry for
7672  * the same name - except special builtins.
7673  */
7674 static void
7675 addcmdentry(char *name, struct cmdentry *entry)
7676 {
7677         struct tblentry *cmdp;
7678
7679         cmdp = cmdlookup(name, 1);
7680         if (cmdp->cmdtype == CMDFUNCTION) {
7681                 freefunc(cmdp->param.func);
7682         }
7683         cmdp->cmdtype = entry->cmdtype;
7684         cmdp->param = entry->u;
7685         cmdp->rehash = 0;
7686 }
7687
7688 static int FAST_FUNC
7689 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7690 {
7691         struct tblentry **pp;
7692         struct tblentry *cmdp;
7693         int c;
7694         struct cmdentry entry;
7695         char *name;
7696
7697         if (nextopt("r") != '\0') {
7698                 clearcmdentry(0);
7699                 return 0;
7700         }
7701
7702         if (*argptr == NULL) {
7703                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7704                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7705                                 if (cmdp->cmdtype == CMDNORMAL)
7706                                         printentry(cmdp);
7707                         }
7708                 }
7709                 return 0;
7710         }
7711
7712         c = 0;
7713         while ((name = *argptr) != NULL) {
7714                 cmdp = cmdlookup(name, 0);
7715                 if (cmdp != NULL
7716                  && (cmdp->cmdtype == CMDNORMAL
7717                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7718                 ) {
7719                         delete_cmd_entry();
7720                 }
7721                 find_command(name, &entry, DO_ERR, pathval());
7722                 if (entry.cmdtype == CMDUNKNOWN)
7723                         c = 1;
7724                 argptr++;
7725         }
7726         return c;
7727 }
7728
7729 /*
7730  * Called when a cd is done.  Marks all commands so the next time they
7731  * are executed they will be rehashed.
7732  */
7733 static void
7734 hashcd(void)
7735 {
7736         struct tblentry **pp;
7737         struct tblentry *cmdp;
7738
7739         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7740                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7741                         if (cmdp->cmdtype == CMDNORMAL
7742                          || (cmdp->cmdtype == CMDBUILTIN
7743                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7744                              && builtinloc > 0)
7745                         ) {
7746                                 cmdp->rehash = 1;
7747                         }
7748                 }
7749         }
7750 }
7751
7752 /*
7753  * Fix command hash table when PATH changed.
7754  * Called before PATH is changed.  The argument is the new value of PATH;
7755  * pathval() still returns the old value at this point.
7756  * Called with interrupts off.
7757  */
7758 static void FAST_FUNC
7759 changepath(const char *new)
7760 {
7761         const char *old;
7762         int firstchange;
7763         int idx;
7764         int idx_bltin;
7765
7766         old = pathval();
7767         firstchange = 9999;     /* assume no change */
7768         idx = 0;
7769         idx_bltin = -1;
7770         for (;;) {
7771                 if (*old != *new) {
7772                         firstchange = idx;
7773                         if ((*old == '\0' && *new == ':')
7774                          || (*old == ':' && *new == '\0')
7775                         ) {
7776                                 firstchange++;
7777                         }
7778                         old = new;      /* ignore subsequent differences */
7779                 }
7780                 if (*new == '\0')
7781                         break;
7782                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7783                         idx_bltin = idx;
7784                 if (*new == ':')
7785                         idx++;
7786                 new++;
7787                 old++;
7788         }
7789         if (builtinloc < 0 && idx_bltin >= 0)
7790                 builtinloc = idx_bltin;             /* zap builtins */
7791         if (builtinloc >= 0 && idx_bltin < 0)
7792                 firstchange = 0;
7793         clearcmdentry(firstchange);
7794         builtinloc = idx_bltin;
7795 }
7796 enum {
7797         TEOF,
7798         TNL,
7799         TREDIR,
7800         TWORD,
7801         TSEMI,
7802         TBACKGND,
7803         TAND,
7804         TOR,
7805         TPIPE,
7806         TLP,
7807         TRP,
7808         TENDCASE,
7809         TENDBQUOTE,
7810         TNOT,
7811         TCASE,
7812         TDO,
7813         TDONE,
7814         TELIF,
7815         TELSE,
7816         TESAC,
7817         TFI,
7818         TFOR,
7819 #if ENABLE_ASH_BASH_COMPAT
7820         TFUNCTION,
7821 #endif
7822         TIF,
7823         TIN,
7824         TTHEN,
7825         TUNTIL,
7826         TWHILE,
7827         TBEGIN,
7828         TEND
7829 };
7830 typedef smallint token_id_t;
7831
7832 /* Nth bit indicates if token marks the end of a list */
7833 enum {
7834         tokendlist = 0
7835         /*  0 */ | (1u << TEOF)
7836         /*  1 */ | (0u << TNL)
7837         /*  2 */ | (0u << TREDIR)
7838         /*  3 */ | (0u << TWORD)
7839         /*  4 */ | (0u << TSEMI)
7840         /*  5 */ | (0u << TBACKGND)
7841         /*  6 */ | (0u << TAND)
7842         /*  7 */ | (0u << TOR)
7843         /*  8 */ | (0u << TPIPE)
7844         /*  9 */ | (0u << TLP)
7845         /* 10 */ | (1u << TRP)
7846         /* 11 */ | (1u << TENDCASE)
7847         /* 12 */ | (1u << TENDBQUOTE)
7848         /* 13 */ | (0u << TNOT)
7849         /* 14 */ | (0u << TCASE)
7850         /* 15 */ | (1u << TDO)
7851         /* 16 */ | (1u << TDONE)
7852         /* 17 */ | (1u << TELIF)
7853         /* 18 */ | (1u << TELSE)
7854         /* 19 */ | (1u << TESAC)
7855         /* 20 */ | (1u << TFI)
7856         /* 21 */ | (0u << TFOR)
7857 #if ENABLE_ASH_BASH_COMPAT
7858         /* 22 */ | (0u << TFUNCTION)
7859 #endif
7860         /* 23 */ | (0u << TIF)
7861         /* 24 */ | (0u << TIN)
7862         /* 25 */ | (1u << TTHEN)
7863         /* 26 */ | (0u << TUNTIL)
7864         /* 27 */ | (0u << TWHILE)
7865         /* 28 */ | (0u << TBEGIN)
7866         /* 29 */ | (1u << TEND)
7867         , /* thus far 29 bits used */
7868 };
7869
7870 static const char *const tokname_array[] = {
7871         "end of file",
7872         "newline",
7873         "redirection",
7874         "word",
7875         ";",
7876         "&",
7877         "&&",
7878         "||",
7879         "|",
7880         "(",
7881         ")",
7882         ";;",
7883         "`",
7884 #define KWDOFFSET 13
7885         /* the following are keywords */
7886         "!",
7887         "case",
7888         "do",
7889         "done",
7890         "elif",
7891         "else",
7892         "esac",
7893         "fi",
7894         "for",
7895 #if ENABLE_ASH_BASH_COMPAT
7896         "function",
7897 #endif
7898         "if",
7899         "in",
7900         "then",
7901         "until",
7902         "while",
7903         "{",
7904         "}",
7905 };
7906
7907 /* Wrapper around strcmp for qsort/bsearch/... */
7908 static int
7909 pstrcmp(const void *a, const void *b)
7910 {
7911         return strcmp((char*)a, *(char**)b);
7912 }
7913
7914 static const char *const *
7915 findkwd(const char *s)
7916 {
7917         return bsearch(s, tokname_array + KWDOFFSET,
7918                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
7919                         sizeof(tokname_array[0]), pstrcmp);
7920 }
7921
7922 /*
7923  * Locate and print what a word is...
7924  */
7925 static int
7926 describe_command(char *command, const char *path, int describe_command_verbose)
7927 {
7928         struct cmdentry entry;
7929         struct tblentry *cmdp;
7930 #if ENABLE_ASH_ALIAS
7931         const struct alias *ap;
7932 #endif
7933
7934         path = path ? path : pathval();
7935
7936         if (describe_command_verbose) {
7937                 out1str(command);
7938         }
7939
7940         /* First look at the keywords */
7941         if (findkwd(command)) {
7942                 out1str(describe_command_verbose ? " is a shell keyword" : command);
7943                 goto out;
7944         }
7945
7946 #if ENABLE_ASH_ALIAS
7947         /* Then look at the aliases */
7948         ap = lookupalias(command, 0);
7949         if (ap != NULL) {
7950                 if (!describe_command_verbose) {
7951                         out1str("alias ");
7952                         printalias(ap);
7953                         return 0;
7954                 }
7955                 out1fmt(" is an alias for %s", ap->val);
7956                 goto out;
7957         }
7958 #endif
7959         /* Then check if it is a tracked alias */
7960         cmdp = cmdlookup(command, 0);
7961         if (cmdp != NULL) {
7962                 entry.cmdtype = cmdp->cmdtype;
7963                 entry.u = cmdp->param;
7964         } else {
7965                 /* Finally use brute force */
7966                 find_command(command, &entry, DO_ABS, path);
7967         }
7968
7969         switch (entry.cmdtype) {
7970         case CMDNORMAL: {
7971                 int j = entry.u.index;
7972                 char *p;
7973                 if (j < 0) {
7974                         p = command;
7975                 } else {
7976                         do {
7977                                 p = path_advance(&path, command);
7978                                 stunalloc(p);
7979                         } while (--j >= 0);
7980                 }
7981                 if (describe_command_verbose) {
7982                         out1fmt(" is%s %s",
7983                                 (cmdp ? " a tracked alias for" : nullstr), p
7984                         );
7985                 } else {
7986                         out1str(p);
7987                 }
7988                 break;
7989         }
7990
7991         case CMDFUNCTION:
7992                 if (describe_command_verbose) {
7993                         out1str(" is a shell function");
7994                 } else {
7995                         out1str(command);
7996                 }
7997                 break;
7998
7999         case CMDBUILTIN:
8000                 if (describe_command_verbose) {
8001                         out1fmt(" is a %sshell builtin",
8002                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8003                                         "special " : nullstr
8004                         );
8005                 } else {
8006                         out1str(command);
8007                 }
8008                 break;
8009
8010         default:
8011                 if (describe_command_verbose) {
8012                         out1str(": not found\n");
8013                 }
8014                 return 127;
8015         }
8016  out:
8017         out1str("\n");
8018         return 0;
8019 }
8020
8021 static int FAST_FUNC
8022 typecmd(int argc UNUSED_PARAM, char **argv)
8023 {
8024         int i = 1;
8025         int err = 0;
8026         int verbose = 1;
8027
8028         /* type -p ... ? (we don't bother checking for 'p') */
8029         if (argv[1] && argv[1][0] == '-') {
8030                 i++;
8031                 verbose = 0;
8032         }
8033         while (argv[i]) {
8034                 err |= describe_command(argv[i++], NULL, verbose);
8035         }
8036         return err;
8037 }
8038
8039 #if ENABLE_ASH_CMDCMD
8040 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8041 static char **
8042 parse_command_args(char **argv, const char **path)
8043 {
8044         char *cp, c;
8045
8046         for (;;) {
8047                 cp = *++argv;
8048                 if (!cp)
8049                         return NULL;
8050                 if (*cp++ != '-')
8051                         break;
8052                 c = *cp++;
8053                 if (!c)
8054                         break;
8055                 if (c == '-' && !*cp) {
8056                         if (!*++argv)
8057                                 return NULL;
8058                         break;
8059                 }
8060                 do {
8061                         switch (c) {
8062                         case 'p':
8063                                 *path = bb_default_path;
8064                                 break;
8065                         default:
8066                                 /* run 'typecmd' for other options */
8067                                 return NULL;
8068                         }
8069                         c = *cp++;
8070                 } while (c);
8071         }
8072         return argv;
8073 }
8074
8075 static int FAST_FUNC
8076 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8077 {
8078         char *cmd;
8079         int c;
8080         enum {
8081                 VERIFY_BRIEF = 1,
8082                 VERIFY_VERBOSE = 2,
8083         } verify = 0;
8084         const char *path = NULL;
8085
8086         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8087          * never reaches this function.
8088          */
8089
8090         while ((c = nextopt("pvV")) != '\0')
8091                 if (c == 'V')
8092                         verify |= VERIFY_VERBOSE;
8093                 else if (c == 'v')
8094                         /*verify |= VERIFY_BRIEF*/;
8095 #if DEBUG
8096                 else if (c != 'p')
8097                         abort();
8098 #endif
8099                 else
8100                         path = bb_default_path;
8101
8102         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8103         cmd = *argptr;
8104         if (/*verify && */ cmd)
8105                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8106
8107         return 0;
8108 }
8109 #endif
8110
8111
8112 /*static int funcblocksize;     // size of structures in function */
8113 /*static int funcstringsize;    // size of strings in node */
8114 static void *funcblock;         /* block to allocate function from */
8115 static char *funcstring_end;    /* end of block to allocate strings from */
8116
8117 /* flags in argument to evaltree */
8118 #define EV_EXIT    01           /* exit after evaluating tree */
8119 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8120
8121 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8122         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8123         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8124         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8125         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8126         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8127         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8128         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8129         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8130         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8131         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8132         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8133         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8134         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8135         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8136         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8137         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8138         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8139 #if ENABLE_ASH_BASH_COMPAT
8140         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8141 #endif
8142         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8143         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8144         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8145         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8146         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8147         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8148         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8149         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8150         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8151 };
8152
8153 static int calcsize(int funcblocksize, union node *n);
8154
8155 static int
8156 sizenodelist(int funcblocksize, struct nodelist *lp)
8157 {
8158         while (lp) {
8159                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8160                 funcblocksize = calcsize(funcblocksize, lp->n);
8161                 lp = lp->next;
8162         }
8163         return funcblocksize;
8164 }
8165
8166 static int
8167 calcsize(int funcblocksize, union node *n)
8168 {
8169         if (n == NULL)
8170                 return funcblocksize;
8171         funcblocksize += nodesize[n->type];
8172         switch (n->type) {
8173         case NCMD:
8174                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8175                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8176                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8177                 break;
8178         case NPIPE:
8179                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8180                 break;
8181         case NREDIR:
8182         case NBACKGND:
8183         case NSUBSHELL:
8184                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8185                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8186                 break;
8187         case NAND:
8188         case NOR:
8189         case NSEMI:
8190         case NWHILE:
8191         case NUNTIL:
8192                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8193                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8194                 break;
8195         case NIF:
8196                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8197                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8198                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8199                 break;
8200         case NFOR:
8201                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8202                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8203                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8204                 break;
8205         case NCASE:
8206                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8207                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8208                 break;
8209         case NCLIST:
8210                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8211                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8212                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8213                 break;
8214         case NDEFUN:
8215         case NARG:
8216                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8217                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8218                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8219                 break;
8220         case NTO:
8221 #if ENABLE_ASH_BASH_COMPAT
8222         case NTO2:
8223 #endif
8224         case NCLOBBER:
8225         case NFROM:
8226         case NFROMTO:
8227         case NAPPEND:
8228                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8229                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8230                 break;
8231         case NTOFD:
8232         case NFROMFD:
8233                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8234                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8235         break;
8236         case NHERE:
8237         case NXHERE:
8238                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8239                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8240                 break;
8241         case NNOT:
8242                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8243                 break;
8244         };
8245         return funcblocksize;
8246 }
8247
8248 static char *
8249 nodeckstrdup(char *s)
8250 {
8251         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8252         return strcpy(funcstring_end, s);
8253 }
8254
8255 static union node *copynode(union node *);
8256
8257 static struct nodelist *
8258 copynodelist(struct nodelist *lp)
8259 {
8260         struct nodelist *start;
8261         struct nodelist **lpp;
8262
8263         lpp = &start;
8264         while (lp) {
8265                 *lpp = funcblock;
8266                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8267                 (*lpp)->n = copynode(lp->n);
8268                 lp = lp->next;
8269                 lpp = &(*lpp)->next;
8270         }
8271         *lpp = NULL;
8272         return start;
8273 }
8274
8275 static union node *
8276 copynode(union node *n)
8277 {
8278         union node *new;
8279
8280         if (n == NULL)
8281                 return NULL;
8282         new = funcblock;
8283         funcblock = (char *) funcblock + nodesize[n->type];
8284
8285         switch (n->type) {
8286         case NCMD:
8287                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8288                 new->ncmd.args = copynode(n->ncmd.args);
8289                 new->ncmd.assign = copynode(n->ncmd.assign);
8290                 break;
8291         case NPIPE:
8292                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8293                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8294                 break;
8295         case NREDIR:
8296         case NBACKGND:
8297         case NSUBSHELL:
8298                 new->nredir.redirect = copynode(n->nredir.redirect);
8299                 new->nredir.n = copynode(n->nredir.n);
8300                 break;
8301         case NAND:
8302         case NOR:
8303         case NSEMI:
8304         case NWHILE:
8305         case NUNTIL:
8306                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8307                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8308                 break;
8309         case NIF:
8310                 new->nif.elsepart = copynode(n->nif.elsepart);
8311                 new->nif.ifpart = copynode(n->nif.ifpart);
8312                 new->nif.test = copynode(n->nif.test);
8313                 break;
8314         case NFOR:
8315                 new->nfor.var = nodeckstrdup(n->nfor.var);
8316                 new->nfor.body = copynode(n->nfor.body);
8317                 new->nfor.args = copynode(n->nfor.args);
8318                 break;
8319         case NCASE:
8320                 new->ncase.cases = copynode(n->ncase.cases);
8321                 new->ncase.expr = copynode(n->ncase.expr);
8322                 break;
8323         case NCLIST:
8324                 new->nclist.body = copynode(n->nclist.body);
8325                 new->nclist.pattern = copynode(n->nclist.pattern);
8326                 new->nclist.next = copynode(n->nclist.next);
8327                 break;
8328         case NDEFUN:
8329         case NARG:
8330                 new->narg.backquote = copynodelist(n->narg.backquote);
8331                 new->narg.text = nodeckstrdup(n->narg.text);
8332                 new->narg.next = copynode(n->narg.next);
8333                 break;
8334         case NTO:
8335 #if ENABLE_ASH_BASH_COMPAT
8336         case NTO2:
8337 #endif
8338         case NCLOBBER:
8339         case NFROM:
8340         case NFROMTO:
8341         case NAPPEND:
8342                 new->nfile.fname = copynode(n->nfile.fname);
8343                 new->nfile.fd = n->nfile.fd;
8344                 new->nfile.next = copynode(n->nfile.next);
8345                 break;
8346         case NTOFD:
8347         case NFROMFD:
8348                 new->ndup.vname = copynode(n->ndup.vname);
8349                 new->ndup.dupfd = n->ndup.dupfd;
8350                 new->ndup.fd = n->ndup.fd;
8351                 new->ndup.next = copynode(n->ndup.next);
8352                 break;
8353         case NHERE:
8354         case NXHERE:
8355                 new->nhere.doc = copynode(n->nhere.doc);
8356                 new->nhere.fd = n->nhere.fd;
8357                 new->nhere.next = copynode(n->nhere.next);
8358                 break;
8359         case NNOT:
8360                 new->nnot.com = copynode(n->nnot.com);
8361                 break;
8362         };
8363         new->type = n->type;
8364         return new;
8365 }
8366
8367 /*
8368  * Make a copy of a parse tree.
8369  */
8370 static struct funcnode *
8371 copyfunc(union node *n)
8372 {
8373         struct funcnode *f;
8374         size_t blocksize;
8375
8376         /*funcstringsize = 0;*/
8377         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8378         f = ckzalloc(blocksize /* + funcstringsize */);
8379         funcblock = (char *) f + offsetof(struct funcnode, n);
8380         funcstring_end = (char *) f + blocksize;
8381         copynode(n);
8382         /* f->count = 0; - ckzalloc did it */
8383         return f;
8384 }
8385
8386 /*
8387  * Define a shell function.
8388  */
8389 static void
8390 defun(union node *func)
8391 {
8392         struct cmdentry entry;
8393
8394         INT_OFF;
8395         entry.cmdtype = CMDFUNCTION;
8396         entry.u.func = copyfunc(func);
8397         addcmdentry(func->narg.text, &entry);
8398         INT_ON;
8399 }
8400
8401 /* Reasons for skipping commands (see comment on breakcmd routine) */
8402 #define SKIPBREAK      (1 << 0)
8403 #define SKIPCONT       (1 << 1)
8404 #define SKIPFUNC       (1 << 2)
8405 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8406 static int skipcount;           /* number of levels to skip */
8407 static int funcnest;            /* depth of function calls */
8408 static int loopnest;            /* current loop nesting level */
8409
8410 /* Forward decl way out to parsing code - dotrap needs it */
8411 static int evalstring(char *s, int flags);
8412
8413 /* Called to execute a trap.
8414  * Single callsite - at the end of evaltree().
8415  * If we return non-zero, evaltree raises EXEXIT exception.
8416  *
8417  * Perhaps we should avoid entering new trap handlers
8418  * while we are executing a trap handler. [is it a TODO?]
8419  */
8420 static void
8421 dotrap(void)
8422 {
8423         uint8_t *g;
8424         int sig;
8425         uint8_t last_status;
8426
8427         if (!pending_sig)
8428                 return;
8429
8430         last_status = exitstatus;
8431         pending_sig = 0;
8432         barrier();
8433
8434         TRACE(("dotrap entered\n"));
8435         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8436                 char *p;
8437
8438                 if (!*g)
8439                         continue;
8440
8441                 if (evalskip) {
8442                         pending_sig = sig;
8443                         break;
8444                 }
8445
8446                 p = trap[sig];
8447                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8448                  * don't upset it by resetting gotsig[SIGINT-1] */
8449                 if (sig == SIGINT && !p)
8450                         continue;
8451
8452                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8453                 *g = 0;
8454                 if (!p)
8455                         continue;
8456                 evalstring(p, 0);
8457         }
8458         exitstatus = last_status;
8459         TRACE(("dotrap returns\n"));
8460 }
8461
8462 /* forward declarations - evaluation is fairly recursive business... */
8463 static int evalloop(union node *, int);
8464 static int evalfor(union node *, int);
8465 static int evalcase(union node *, int);
8466 static int evalsubshell(union node *, int);
8467 static void expredir(union node *);
8468 static int evalpipe(union node *, int);
8469 static int evalcommand(union node *, int);
8470 static int evalbltin(const struct builtincmd *, int, char **, int);
8471 static void prehash(union node *);
8472
8473 /*
8474  * Evaluate a parse tree.  The value is left in the global variable
8475  * exitstatus.
8476  */
8477 static int
8478 evaltree(union node *n, int flags)
8479 {
8480         struct jmploc *volatile savehandler = exception_handler;
8481         struct jmploc jmploc;
8482         int checkexit = 0;
8483         int (*evalfn)(union node *, int);
8484         int status = 0;
8485         int int_level;
8486
8487         SAVE_INT(int_level);
8488
8489         if (n == NULL) {
8490                 TRACE(("evaltree(NULL) called\n"));
8491                 goto out1;
8492         }
8493         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8494
8495         dotrap();
8496
8497         exception_handler = &jmploc;
8498         {
8499                 int err = setjmp(jmploc.loc);
8500                 if (err) {
8501                         /* if it was a signal, check for trap handlers */
8502                         if (exception_type == EXSIG) {
8503                                 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8504                                                 exception_type, err));
8505                                 goto out;
8506                         }
8507                         /* continue on the way out */
8508                         TRACE(("exception %d in evaltree, propagating err=%d\n",
8509                                         exception_type, err));
8510                         exception_handler = savehandler;
8511                         longjmp(exception_handler->loc, err);
8512                 }
8513         }
8514
8515         switch (n->type) {
8516         default:
8517 #if DEBUG
8518                 out1fmt("Node type = %d\n", n->type);
8519                 fflush_all();
8520                 break;
8521 #endif
8522         case NNOT:
8523                 status = !evaltree(n->nnot.com, EV_TESTED);
8524                 goto setstatus;
8525         case NREDIR:
8526                 expredir(n->nredir.redirect);
8527                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8528                 if (!status) {
8529                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8530                 }
8531                 if (n->nredir.redirect)
8532                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8533                 goto setstatus;
8534         case NCMD:
8535                 evalfn = evalcommand;
8536  checkexit:
8537                 if (eflag && !(flags & EV_TESTED))
8538                         checkexit = ~0;
8539                 goto calleval;
8540         case NFOR:
8541                 evalfn = evalfor;
8542                 goto calleval;
8543         case NWHILE:
8544         case NUNTIL:
8545                 evalfn = evalloop;
8546                 goto calleval;
8547         case NSUBSHELL:
8548         case NBACKGND:
8549                 evalfn = evalsubshell;
8550                 goto checkexit;
8551         case NPIPE:
8552                 evalfn = evalpipe;
8553                 goto checkexit;
8554         case NCASE:
8555                 evalfn = evalcase;
8556                 goto calleval;
8557         case NAND:
8558         case NOR:
8559         case NSEMI: {
8560
8561 #if NAND + 1 != NOR
8562 #error NAND + 1 != NOR
8563 #endif
8564 #if NOR + 1 != NSEMI
8565 #error NOR + 1 != NSEMI
8566 #endif
8567                 unsigned is_or = n->type - NAND;
8568                 status = evaltree(
8569                         n->nbinary.ch1,
8570                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8571                 );
8572                 if ((!status) == is_or || evalskip)
8573                         break;
8574                 n = n->nbinary.ch2;
8575  evaln:
8576                 evalfn = evaltree;
8577  calleval:
8578                 status = evalfn(n, flags);
8579                 goto setstatus;
8580         }
8581         case NIF:
8582                 status = evaltree(n->nif.test, EV_TESTED);
8583                 if (evalskip)
8584                         break;
8585                 if (!status) {
8586                         n = n->nif.ifpart;
8587                         goto evaln;
8588                 }
8589                 if (n->nif.elsepart) {
8590                         n = n->nif.elsepart;
8591                         goto evaln;
8592                 }
8593                 status = 0;
8594                 goto setstatus;
8595         case NDEFUN:
8596                 defun(n);
8597                 /* Not necessary. To test it:
8598                  * "false; f() { qwerty; }; echo $?" should print 0.
8599                  */
8600                 /* status = 0; */
8601  setstatus:
8602                 exitstatus = status;
8603                 break;
8604         }
8605
8606  out:
8607         exception_handler = savehandler;
8608
8609  out1:
8610         /* Order of checks below is important:
8611          * signal handlers trigger before exit caused by "set -e".
8612          */
8613         dotrap();
8614
8615         if (checkexit & status)
8616                 raise_exception(EXEXIT);
8617         if (flags & EV_EXIT)
8618                 raise_exception(EXEXIT);
8619
8620         RESTORE_INT(int_level);
8621         TRACE(("leaving evaltree (no interrupts)\n"));
8622
8623         return exitstatus;
8624 }
8625
8626 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8627 static
8628 #endif
8629 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8630
8631 static int
8632 skiploop(void)
8633 {
8634         int skip = evalskip;
8635
8636         switch (skip) {
8637         case 0:
8638                 break;
8639         case SKIPBREAK:
8640         case SKIPCONT:
8641                 if (--skipcount <= 0) {
8642                         evalskip = 0;
8643                         break;
8644                 }
8645                 skip = SKIPBREAK;
8646                 break;
8647         }
8648         return skip;
8649 }
8650
8651 static int
8652 evalloop(union node *n, int flags)
8653 {
8654         int skip;
8655         int status;
8656
8657         loopnest++;
8658         status = 0;
8659         flags &= EV_TESTED;
8660         do {
8661                 int i;
8662
8663                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8664                 skip = skiploop();
8665                 if (skip == SKIPFUNC)
8666                         status = i;
8667                 if (skip)
8668                         continue;
8669                 if (n->type != NWHILE)
8670                         i = !i;
8671                 if (i != 0)
8672                         break;
8673                 status = evaltree(n->nbinary.ch2, flags);
8674                 skip = skiploop();
8675         } while (!(skip & ~SKIPCONT));
8676         loopnest--;
8677
8678         return status;
8679 }
8680
8681 static int
8682 evalfor(union node *n, int flags)
8683 {
8684         struct arglist arglist;
8685         union node *argp;
8686         struct strlist *sp;
8687         struct stackmark smark;
8688         int status = 0;
8689
8690         setstackmark(&smark);
8691         arglist.list = NULL;
8692         arglist.lastp = &arglist.list;
8693         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8694                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8695         }
8696         *arglist.lastp = NULL;
8697
8698         loopnest++;
8699         flags &= EV_TESTED;
8700         for (sp = arglist.list; sp; sp = sp->next) {
8701                 setvar0(n->nfor.var, sp->text);
8702                 status = evaltree(n->nfor.body, flags);
8703                 if (skiploop() & ~SKIPCONT)
8704                         break;
8705         }
8706         loopnest--;
8707         popstackmark(&smark);
8708
8709         return status;
8710 }
8711
8712 static int
8713 evalcase(union node *n, int flags)
8714 {
8715         union node *cp;
8716         union node *patp;
8717         struct arglist arglist;
8718         struct stackmark smark;
8719         int status = 0;
8720
8721         setstackmark(&smark);
8722         arglist.list = NULL;
8723         arglist.lastp = &arglist.list;
8724         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8725         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8726                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8727                         if (casematch(patp, arglist.list->text)) {
8728                                 /* Ensure body is non-empty as otherwise
8729                                  * EV_EXIT may prevent us from setting the
8730                                  * exit status.
8731                                  */
8732                                 if (evalskip == 0 && cp->nclist.body) {
8733                                         status = evaltree(cp->nclist.body, flags);
8734                                 }
8735                                 goto out;
8736                         }
8737                 }
8738         }
8739  out:
8740         popstackmark(&smark);
8741
8742         return status;
8743 }
8744
8745 /*
8746  * Kick off a subshell to evaluate a tree.
8747  */
8748 static int
8749 evalsubshell(union node *n, int flags)
8750 {
8751         struct job *jp;
8752         int backgnd = (n->type == NBACKGND);
8753         int status;
8754
8755         expredir(n->nredir.redirect);
8756         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8757                 goto nofork;
8758         INT_OFF;
8759         jp = makejob(/*n,*/ 1);
8760         if (forkshell(jp, n, backgnd) == 0) {
8761                 /* child */
8762                 INT_ON;
8763                 flags |= EV_EXIT;
8764                 if (backgnd)
8765                         flags &= ~EV_TESTED;
8766  nofork:
8767                 redirect(n->nredir.redirect, 0);
8768                 evaltreenr(n->nredir.n, flags);
8769                 /* never returns */
8770         }
8771         /* parent */
8772         status = 0;
8773         if (!backgnd)
8774                 status = waitforjob(jp);
8775         INT_ON;
8776         return status;
8777 }
8778
8779 /*
8780  * Compute the names of the files in a redirection list.
8781  */
8782 static void fixredir(union node *, const char *, int);
8783 static void
8784 expredir(union node *n)
8785 {
8786         union node *redir;
8787
8788         for (redir = n; redir; redir = redir->nfile.next) {
8789                 struct arglist fn;
8790
8791                 fn.list = NULL;
8792                 fn.lastp = &fn.list;
8793                 switch (redir->type) {
8794                 case NFROMTO:
8795                 case NFROM:
8796                 case NTO:
8797 #if ENABLE_ASH_BASH_COMPAT
8798                 case NTO2:
8799 #endif
8800                 case NCLOBBER:
8801                 case NAPPEND:
8802                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8803                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
8804 #if ENABLE_ASH_BASH_COMPAT
8805  store_expfname:
8806 #endif
8807 #if 0
8808 // By the design of stack allocator, the loop of this kind:
8809 //      while true; do while true; do break; done </dev/null; done
8810 // will look like a memory leak: ash plans to free expfname's
8811 // of "/dev/null" as soon as it finishes running the loop
8812 // (in this case, never).
8813 // This "fix" is wrong:
8814                         if (redir->nfile.expfname)
8815                                 stunalloc(redir->nfile.expfname);
8816 // It results in corrupted state of stacked allocations.
8817 #endif
8818                         redir->nfile.expfname = fn.list->text;
8819                         break;
8820                 case NFROMFD:
8821                 case NTOFD: /* >& */
8822                         if (redir->ndup.vname) {
8823                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8824                                 if (fn.list == NULL)
8825                                         ash_msg_and_raise_error("redir error");
8826 #if ENABLE_ASH_BASH_COMPAT
8827 //FIXME: we used expandarg with different args!
8828                                 if (!isdigit_str9(fn.list->text)) {
8829                                         /* >&file, not >&fd */
8830                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
8831                                                 ash_msg_and_raise_error("redir error");
8832                                         redir->type = NTO2;
8833                                         goto store_expfname;
8834                                 }
8835 #endif
8836                                 fixredir(redir, fn.list->text, 1);
8837                         }
8838                         break;
8839                 }
8840         }
8841 }
8842
8843 /*
8844  * Evaluate a pipeline.  All the processes in the pipeline are children
8845  * of the process creating the pipeline.  (This differs from some versions
8846  * of the shell, which make the last process in a pipeline the parent
8847  * of all the rest.)
8848  */
8849 static int
8850 evalpipe(union node *n, int flags)
8851 {
8852         struct job *jp;
8853         struct nodelist *lp;
8854         int pipelen;
8855         int prevfd;
8856         int pip[2];
8857         int status = 0;
8858
8859         TRACE(("evalpipe(0x%lx) called\n", (long)n));
8860         pipelen = 0;
8861         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8862                 pipelen++;
8863         flags |= EV_EXIT;
8864         INT_OFF;
8865         jp = makejob(/*n,*/ pipelen);
8866         prevfd = -1;
8867         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8868                 prehash(lp->n);
8869                 pip[1] = -1;
8870                 if (lp->next) {
8871                         if (pipe(pip) < 0) {
8872                                 close(prevfd);
8873                                 ash_msg_and_raise_error("pipe call failed");
8874                         }
8875                 }
8876                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8877                         /* child */
8878                         INT_ON;
8879                         if (pip[1] >= 0) {
8880                                 close(pip[0]);
8881                         }
8882                         if (prevfd > 0) {
8883                                 dup2(prevfd, 0);
8884                                 close(prevfd);
8885                         }
8886                         if (pip[1] > 1) {
8887                                 dup2(pip[1], 1);
8888                                 close(pip[1]);
8889                         }
8890                         evaltreenr(lp->n, flags);
8891                         /* never returns */
8892                 }
8893                 /* parent */
8894                 if (prevfd >= 0)
8895                         close(prevfd);
8896                 prevfd = pip[0];
8897                 /* Don't want to trigger debugging */
8898                 if (pip[1] != -1)
8899                         close(pip[1]);
8900         }
8901         if (n->npipe.pipe_backgnd == 0) {
8902                 status = waitforjob(jp);
8903                 TRACE(("evalpipe:  job done exit status %d\n", status));
8904         }
8905         INT_ON;
8906
8907         return status;
8908 }
8909
8910 /*
8911  * Controls whether the shell is interactive or not.
8912  */
8913 static void
8914 setinteractive(int on)
8915 {
8916         static smallint is_interactive;
8917
8918         if (++on == is_interactive)
8919                 return;
8920         is_interactive = on;
8921         setsignal(SIGINT);
8922         setsignal(SIGQUIT);
8923         setsignal(SIGTERM);
8924 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8925         if (is_interactive > 1) {
8926                 /* Looks like they want an interactive shell */
8927                 static smallint did_banner;
8928
8929                 if (!did_banner) {
8930                         /* note: ash and hush share this string */
8931                         out1fmt("\n\n%s %s\n"
8932                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
8933                                 "\n",
8934                                 bb_banner,
8935                                 "built-in shell (ash)"
8936                         );
8937                         did_banner = 1;
8938                 }
8939         }
8940 #endif
8941 }
8942
8943 static void
8944 optschanged(void)
8945 {
8946 #if DEBUG
8947         opentrace();
8948 #endif
8949         setinteractive(iflag);
8950         setjobctl(mflag);
8951 #if ENABLE_FEATURE_EDITING_VI
8952         if (viflag)
8953                 line_input_state->flags |= VI_MODE;
8954         else
8955                 line_input_state->flags &= ~VI_MODE;
8956 #else
8957         viflag = 0; /* forcibly keep the option off */
8958 #endif
8959 }
8960
8961 static struct localvar *localvars;
8962
8963 /*
8964  * Called after a function returns.
8965  * Interrupts must be off.
8966  */
8967 static void
8968 poplocalvars(void)
8969 {
8970         struct localvar *lvp;
8971         struct var *vp;
8972
8973         while ((lvp = localvars) != NULL) {
8974                 localvars = lvp->next;
8975                 vp = lvp->vp;
8976                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
8977                 if (vp == NULL) {       /* $- saved */
8978                         memcpy(optlist, lvp->text, sizeof(optlist));
8979                         free((char*)lvp->text);
8980                         optschanged();
8981                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8982                         unsetvar(vp->var_text);
8983                 } else {
8984                         if (vp->var_func)
8985                                 vp->var_func(var_end(lvp->text));
8986                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8987                                 free((char*)vp->var_text);
8988                         vp->flags = lvp->flags;
8989                         vp->var_text = lvp->text;
8990                 }
8991                 free(lvp);
8992         }
8993 }
8994
8995 static int
8996 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8997 {
8998         volatile struct shparam saveparam;
8999         struct localvar *volatile savelocalvars;
9000         struct jmploc *volatile savehandler;
9001         struct jmploc jmploc;
9002         int e;
9003
9004         saveparam = shellparam;
9005         savelocalvars = localvars;
9006         savehandler = exception_handler;
9007         e = setjmp(jmploc.loc);
9008         if (e) {
9009                 goto funcdone;
9010         }
9011         INT_OFF;
9012         exception_handler = &jmploc;
9013         localvars = NULL;
9014         shellparam.malloced = 0;
9015         func->count++;
9016         funcnest++;
9017         INT_ON;
9018         shellparam.nparam = argc - 1;
9019         shellparam.p = argv + 1;
9020 #if ENABLE_ASH_GETOPTS
9021         shellparam.optind = 1;
9022         shellparam.optoff = -1;
9023 #endif
9024         evaltree(func->n.narg.next, flags & EV_TESTED);
9025  funcdone:
9026         INT_OFF;
9027         funcnest--;
9028         freefunc(func);
9029         poplocalvars();
9030         localvars = savelocalvars;
9031         freeparam(&shellparam);
9032         shellparam = saveparam;
9033         exception_handler = savehandler;
9034         INT_ON;
9035         evalskip &= ~SKIPFUNC;
9036         return e;
9037 }
9038
9039 /*
9040  * Make a variable a local variable.  When a variable is made local, it's
9041  * value and flags are saved in a localvar structure.  The saved values
9042  * will be restored when the shell function returns.  We handle the name
9043  * "-" as a special case: it makes changes to "set +-options" local
9044  * (options will be restored on return from the function).
9045  */
9046 static void
9047 mklocal(char *name)
9048 {
9049         struct localvar *lvp;
9050         struct var **vpp;
9051         struct var *vp;
9052         char *eq = strchr(name, '=');
9053
9054         INT_OFF;
9055         /* Cater for duplicate "local". Examples:
9056          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9057          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9058          */
9059         lvp = localvars;
9060         while (lvp) {
9061                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9062                         if (eq)
9063                                 setvareq(name, 0);
9064                         /* else:
9065                          * it's a duplicate "local VAR" declaration, do nothing
9066                          */
9067                         return;
9068                 }
9069                 lvp = lvp->next;
9070         }
9071
9072         lvp = ckzalloc(sizeof(*lvp));
9073         if (LONE_DASH(name)) {
9074                 char *p;
9075                 p = ckmalloc(sizeof(optlist));
9076                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9077                 vp = NULL;
9078         } else {
9079                 vpp = hashvar(name);
9080                 vp = *findvar(vpp, name);
9081                 if (vp == NULL) {
9082                         /* variable did not exist yet */
9083                         if (eq)
9084                                 setvareq(name, VSTRFIXED);
9085                         else
9086                                 setvar(name, NULL, VSTRFIXED);
9087                         vp = *vpp;      /* the new variable */
9088                         lvp->flags = VUNSET;
9089                 } else {
9090                         lvp->text = vp->var_text;
9091                         lvp->flags = vp->flags;
9092                         /* make sure neither "struct var" nor string gets freed
9093                          * during (un)setting:
9094                          */
9095                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9096                         if (eq)
9097                                 setvareq(name, 0);
9098                         else
9099                                 /* "local VAR" unsets VAR: */
9100                                 setvar0(name, NULL);
9101                 }
9102         }
9103         lvp->vp = vp;
9104         lvp->next = localvars;
9105         localvars = lvp;
9106         INT_ON;
9107 }
9108
9109 /*
9110  * The "local" command.
9111  */
9112 static int FAST_FUNC
9113 localcmd(int argc UNUSED_PARAM, char **argv)
9114 {
9115         char *name;
9116
9117         if (!funcnest)
9118                 ash_msg_and_raise_error("not in a function");
9119
9120         argv = argptr;
9121         while ((name = *argv++) != NULL) {
9122                 mklocal(name);
9123         }
9124         return 0;
9125 }
9126
9127 static int FAST_FUNC
9128 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9129 {
9130         return 1;
9131 }
9132
9133 static int FAST_FUNC
9134 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9135 {
9136         return 0;
9137 }
9138
9139 static int FAST_FUNC
9140 execcmd(int argc UNUSED_PARAM, char **argv)
9141 {
9142         if (argv[1]) {
9143                 iflag = 0;              /* exit on error */
9144                 mflag = 0;
9145                 optschanged();
9146                 /* We should set up signals for "exec CMD"
9147                  * the same way as for "CMD" without "exec".
9148                  * But optschanged->setinteractive->setsignal
9149                  * still thought we are a root shell. Therefore, for example,
9150                  * SIGQUIT is still set to IGN. Fix it:
9151                  */
9152                 shlvl++;
9153                 setsignal(SIGQUIT);
9154                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9155                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9156                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9157
9158                 shellexec(argv + 1, pathval(), 0);
9159                 /* NOTREACHED */
9160         }
9161         return 0;
9162 }
9163
9164 /*
9165  * The return command.
9166  */
9167 static int FAST_FUNC
9168 returncmd(int argc UNUSED_PARAM, char **argv)
9169 {
9170         /*
9171          * If called outside a function, do what ksh does;
9172          * skip the rest of the file.
9173          */
9174         evalskip = SKIPFUNC;
9175         return argv[1] ? number(argv[1]) : exitstatus;
9176 }
9177
9178 /* Forward declarations for builtintab[] */
9179 static int breakcmd(int, char **) FAST_FUNC;
9180 static int dotcmd(int, char **) FAST_FUNC;
9181 static int evalcmd(int, char **, int) FAST_FUNC;
9182 static int exitcmd(int, char **) FAST_FUNC;
9183 static int exportcmd(int, char **) FAST_FUNC;
9184 #if ENABLE_ASH_GETOPTS
9185 static int getoptscmd(int, char **) FAST_FUNC;
9186 #endif
9187 #if ENABLE_ASH_HELP
9188 static int helpcmd(int, char **) FAST_FUNC;
9189 #endif
9190 #if MAX_HISTORY
9191 static int historycmd(int, char **) FAST_FUNC;
9192 #endif
9193 #if ENABLE_SH_MATH_SUPPORT
9194 static int letcmd(int, char **) FAST_FUNC;
9195 #endif
9196 static int readcmd(int, char **) FAST_FUNC;
9197 static int setcmd(int, char **) FAST_FUNC;
9198 static int shiftcmd(int, char **) FAST_FUNC;
9199 static int timescmd(int, char **) FAST_FUNC;
9200 static int trapcmd(int, char **) FAST_FUNC;
9201 static int umaskcmd(int, char **) FAST_FUNC;
9202 static int unsetcmd(int, char **) FAST_FUNC;
9203 static int ulimitcmd(int, char **) FAST_FUNC;
9204
9205 #define BUILTIN_NOSPEC          "0"
9206 #define BUILTIN_SPECIAL         "1"
9207 #define BUILTIN_REGULAR         "2"
9208 #define BUILTIN_SPEC_REG        "3"
9209 #define BUILTIN_ASSIGN          "4"
9210 #define BUILTIN_SPEC_ASSG       "5"
9211 #define BUILTIN_REG_ASSG        "6"
9212 #define BUILTIN_SPEC_REG_ASSG   "7"
9213
9214 /* Stubs for calling non-FAST_FUNC's */
9215 #if ENABLE_ASH_BUILTIN_ECHO
9216 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9217 #endif
9218 #if ENABLE_ASH_BUILTIN_PRINTF
9219 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9220 #endif
9221 #if ENABLE_ASH_BUILTIN_TEST
9222 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9223 #endif
9224
9225 /* Keep these in proper order since it is searched via bsearch() */
9226 static const struct builtincmd builtintab[] = {
9227         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9228         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9229 #if ENABLE_ASH_BUILTIN_TEST
9230         { BUILTIN_REGULAR       "["       , testcmd    },
9231 #if ENABLE_ASH_BASH_COMPAT
9232         { BUILTIN_REGULAR       "[["      , testcmd    },
9233 #endif
9234 #endif
9235 #if ENABLE_ASH_ALIAS
9236         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9237 #endif
9238 #if JOBS
9239         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9240 #endif
9241         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9242         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9243         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9244 #if ENABLE_ASH_CMDCMD
9245         { BUILTIN_REGULAR       "command" , commandcmd },
9246 #endif
9247         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9248 #if ENABLE_ASH_BUILTIN_ECHO
9249         { BUILTIN_REGULAR       "echo"    , echocmd    },
9250 #endif
9251         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9252         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9253         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9254         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9255         { BUILTIN_REGULAR       "false"   , falsecmd   },
9256 #if JOBS
9257         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9258 #endif
9259 #if ENABLE_ASH_GETOPTS
9260         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9261 #endif
9262         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9263 #if ENABLE_ASH_HELP
9264         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9265 #endif
9266 #if MAX_HISTORY
9267         { BUILTIN_NOSPEC        "history" , historycmd },
9268 #endif
9269 #if JOBS
9270         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9271         { BUILTIN_REGULAR       "kill"    , killcmd    },
9272 #endif
9273 #if ENABLE_SH_MATH_SUPPORT
9274         { BUILTIN_NOSPEC        "let"     , letcmd     },
9275 #endif
9276         { BUILTIN_ASSIGN        "local"   , localcmd   },
9277 #if ENABLE_ASH_BUILTIN_PRINTF
9278         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9279 #endif
9280         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9281         { BUILTIN_REGULAR       "read"    , readcmd    },
9282         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9283         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9284         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9285         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9286 #if ENABLE_ASH_BASH_COMPAT
9287         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9288 #endif
9289 #if ENABLE_ASH_BUILTIN_TEST
9290         { BUILTIN_REGULAR       "test"    , testcmd    },
9291 #endif
9292         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9293         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9294         { BUILTIN_REGULAR       "true"    , truecmd    },
9295         { BUILTIN_NOSPEC        "type"    , typecmd    },
9296         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9297         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9298 #if ENABLE_ASH_ALIAS
9299         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9300 #endif
9301         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9302         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9303 };
9304
9305 /* Should match the above table! */
9306 #define COMMANDCMD (builtintab + \
9307         /* . : */       2 + \
9308         /* [ */         1 * ENABLE_ASH_BUILTIN_TEST + \
9309         /* [[ */        1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
9310         /* alias */     1 * ENABLE_ASH_ALIAS + \
9311         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9312         /* break cd cddir  */   3)
9313 #define EVALCMD (COMMANDCMD + \
9314         /* command */   1 * ENABLE_ASH_CMDCMD + \
9315         /* continue */  1 + \
9316         /* echo */      1 * ENABLE_ASH_BUILTIN_ECHO + \
9317         0)
9318 #define EXECCMD (EVALCMD + \
9319         /* eval */      1)
9320
9321 /*
9322  * Search the table of builtin commands.
9323  */
9324 static int
9325 pstrcmp1(const void *a, const void *b)
9326 {
9327         return strcmp((char*)a, *(char**)b + 1);
9328 }
9329 static struct builtincmd *
9330 find_builtin(const char *name)
9331 {
9332         struct builtincmd *bp;
9333
9334         bp = bsearch(
9335                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9336                 pstrcmp1
9337         );
9338         return bp;
9339 }
9340
9341 /*
9342  * Execute a simple command.
9343  */
9344 static int
9345 isassignment(const char *p)
9346 {
9347         const char *q = endofname(p);
9348         if (p == q)
9349                 return 0;
9350         return *q == '=';
9351 }
9352 static int FAST_FUNC
9353 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9354 {
9355         /* Preserve exitstatus of a previous possible redirection
9356          * as POSIX mandates */
9357         return back_exitstatus;
9358 }
9359 static int
9360 evalcommand(union node *cmd, int flags)
9361 {
9362         static const struct builtincmd null_bltin = {
9363                 "\0\0", bltincmd /* why three NULs? */
9364         };
9365         struct stackmark smark;
9366         union node *argp;
9367         struct arglist arglist;
9368         struct arglist varlist;
9369         char **argv;
9370         int argc;
9371         const struct strlist *sp;
9372         struct cmdentry cmdentry;
9373         struct job *jp;
9374         char *lastarg;
9375         const char *path;
9376         int spclbltin;
9377         int status;
9378         char **nargv;
9379         struct builtincmd *bcmd;
9380         smallint cmd_is_exec;
9381         smallint pseudovarflag = 0;
9382
9383         /* First expand the arguments. */
9384         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9385         setstackmark(&smark);
9386         back_exitstatus = 0;
9387
9388         cmdentry.cmdtype = CMDBUILTIN;
9389         cmdentry.u.cmd = &null_bltin;
9390         varlist.lastp = &varlist.list;
9391         *varlist.lastp = NULL;
9392         arglist.lastp = &arglist.list;
9393         *arglist.lastp = NULL;
9394
9395         argc = 0;
9396         if (cmd->ncmd.args) {
9397                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9398                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9399         }
9400
9401         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9402                 struct strlist **spp;
9403
9404                 spp = arglist.lastp;
9405                 if (pseudovarflag && isassignment(argp->narg.text))
9406                         expandarg(argp, &arglist, EXP_VARTILDE);
9407                 else
9408                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9409
9410                 for (sp = *spp; sp; sp = sp->next)
9411                         argc++;
9412         }
9413
9414         /* Reserve one extra spot at the front for shellexec. */
9415         nargv = stalloc(sizeof(char *) * (argc + 2));
9416         argv = ++nargv;
9417         for (sp = arglist.list; sp; sp = sp->next) {
9418                 TRACE(("evalcommand arg: %s\n", sp->text));
9419                 *nargv++ = sp->text;
9420         }
9421         *nargv = NULL;
9422
9423         lastarg = NULL;
9424         if (iflag && funcnest == 0 && argc > 0)
9425                 lastarg = nargv[-1];
9426
9427         preverrout_fd = 2;
9428         expredir(cmd->ncmd.redirect);
9429         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9430
9431         path = vpath.var_text;
9432         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9433                 struct strlist **spp;
9434                 char *p;
9435
9436                 spp = varlist.lastp;
9437                 expandarg(argp, &varlist, EXP_VARTILDE);
9438
9439                 /*
9440                  * Modify the command lookup path, if a PATH= assignment
9441                  * is present
9442                  */
9443                 p = (*spp)->text;
9444                 if (varcmp(p, path) == 0)
9445                         path = p;
9446         }
9447
9448         /* Print the command if xflag is set. */
9449         if (xflag) {
9450                 int n;
9451                 const char *p = " %s" + 1;
9452
9453                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9454                 sp = varlist.list;
9455                 for (n = 0; n < 2; n++) {
9456                         while (sp) {
9457                                 fdprintf(preverrout_fd, p, sp->text);
9458                                 sp = sp->next;
9459                                 p = " %s";
9460                         }
9461                         sp = arglist.list;
9462                 }
9463                 safe_write(preverrout_fd, "\n", 1);
9464         }
9465
9466         cmd_is_exec = 0;
9467         spclbltin = -1;
9468
9469         /* Now locate the command. */
9470         if (argc) {
9471                 int cmd_flag = DO_ERR;
9472 #if ENABLE_ASH_CMDCMD
9473                 const char *oldpath = path + 5;
9474 #endif
9475                 path += 5;
9476                 for (;;) {
9477                         find_command(argv[0], &cmdentry, cmd_flag, path);
9478                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9479                                 flush_stdout_stderr();
9480                                 status = 127;
9481                                 goto bail;
9482                         }
9483
9484                         /* implement bltin and command here */
9485                         if (cmdentry.cmdtype != CMDBUILTIN)
9486                                 break;
9487                         if (spclbltin < 0)
9488                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9489                         if (cmdentry.u.cmd == EXECCMD)
9490                                 cmd_is_exec = 1;
9491 #if ENABLE_ASH_CMDCMD
9492                         if (cmdentry.u.cmd == COMMANDCMD) {
9493                                 path = oldpath;
9494                                 nargv = parse_command_args(argv, &path);
9495                                 if (!nargv)
9496                                         break;
9497                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9498                                  * nargv => "PROG". path is updated if -p.
9499                                  */
9500                                 argc -= nargv - argv;
9501                                 argv = nargv;
9502                                 cmd_flag |= DO_NOFUNC;
9503                         } else
9504 #endif
9505                                 break;
9506                 }
9507         }
9508
9509         if (status) {
9510                 /* We have a redirection error. */
9511                 if (spclbltin > 0)
9512                         raise_exception(EXERROR);
9513  bail:
9514                 exitstatus = status;
9515                 goto out;
9516         }
9517
9518         /* Execute the command. */
9519         switch (cmdentry.cmdtype) {
9520         default: {
9521
9522 #if ENABLE_FEATURE_SH_NOFORK
9523 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9524  *     around run_nofork_applet() call.
9525  * (2) Should this check also be done in forkshell()?
9526  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9527  */
9528                 /* find_command() encodes applet_no as (-2 - applet_no) */
9529                 int applet_no = (- cmdentry.u.index - 2);
9530                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9531                         listsetvar(varlist.list, VEXPORT|VSTACK);
9532                         /* run <applet>_main() */
9533                         status = run_nofork_applet(applet_no, argv);
9534                         break;
9535                 }
9536 #endif
9537                 /* Can we avoid forking off? For example, very last command
9538                  * in a script or a subshell does not need forking,
9539                  * we can just exec it.
9540                  */
9541                 if (!(flags & EV_EXIT) || may_have_traps) {
9542                         /* No, forking off a child is necessary */
9543                         INT_OFF;
9544                         jp = makejob(/*cmd,*/ 1);
9545                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9546                                 /* parent */
9547                                 status = waitforjob(jp);
9548                                 INT_ON;
9549                                 TRACE(("forked child exited with %d\n", status));
9550                                 break;
9551                         }
9552                         /* child */
9553                         FORCE_INT_ON;
9554                         /* fall through to exec'ing external program */
9555                 }
9556                 listsetvar(varlist.list, VEXPORT|VSTACK);
9557                 shellexec(argv, path, cmdentry.u.index);
9558                 /* NOTREACHED */
9559         } /* default */
9560         case CMDBUILTIN:
9561                 cmdenviron = varlist.list;
9562                 if (cmdenviron) {
9563                         struct strlist *list = cmdenviron;
9564                         int i = VNOSET;
9565                         if (spclbltin > 0 || argc == 0) {
9566                                 i = 0;
9567                                 if (cmd_is_exec && argc > 1)
9568                                         i = VEXPORT;
9569                         }
9570                         listsetvar(list, i);
9571                 }
9572                 /* Tight loop with builtins only:
9573                  * "while kill -0 $child; do true; done"
9574                  * will never exit even if $child died, unless we do this
9575                  * to reap the zombie and make kill detect that it's gone: */
9576                 dowait(DOWAIT_NONBLOCK, NULL);
9577
9578                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9579                         int exit_status;
9580                         int i = exception_type;
9581                         if (i == EXEXIT)
9582                                 goto raise;
9583                         exit_status = 2;
9584                         if (i == EXINT)
9585                                 exit_status = 128 + SIGINT;
9586                         if (i == EXSIG)
9587                                 exit_status = 128 + pending_sig;
9588                         exitstatus = exit_status;
9589                         if (i == EXINT || spclbltin > 0) {
9590  raise:
9591                                 longjmp(exception_handler->loc, 1);
9592                         }
9593                         FORCE_INT_ON;
9594                 }
9595                 goto readstatus;
9596
9597         case CMDFUNCTION:
9598                 listsetvar(varlist.list, 0);
9599                 /* See above for the rationale */
9600                 dowait(DOWAIT_NONBLOCK, NULL);
9601                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9602                         goto raise;
9603  readstatus:
9604                 status = exitstatus;
9605                 break;
9606         } /* switch */
9607
9608  out:
9609         if (cmd->ncmd.redirect)
9610                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9611         if (lastarg) {
9612                 /* dsl: I think this is intended to be used to support
9613                  * '_' in 'vi' command mode during line editing...
9614                  * However I implemented that within libedit itself.
9615                  */
9616                 setvar0("_", lastarg);
9617         }
9618         popstackmark(&smark);
9619
9620         return status;
9621 }
9622
9623 static int
9624 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9625 {
9626         char *volatile savecmdname;
9627         struct jmploc *volatile savehandler;
9628         struct jmploc jmploc;
9629         int status;
9630         int i;
9631
9632         savecmdname = commandname;
9633         savehandler = exception_handler;
9634         i = setjmp(jmploc.loc);
9635         if (i)
9636                 goto cmddone;
9637         exception_handler = &jmploc;
9638         commandname = argv[0];
9639         argptr = argv + 1;
9640         optptr = NULL;                  /* initialize nextopt */
9641         if (cmd == EVALCMD)
9642                 status = evalcmd(argc, argv, flags);
9643         else
9644                 status = (*cmd->builtin)(argc, argv);
9645         flush_stdout_stderr();
9646         status |= ferror(stdout);
9647         exitstatus = status;
9648  cmddone:
9649         clearerr(stdout);
9650         commandname = savecmdname;
9651         exception_handler = savehandler;
9652
9653         return i;
9654 }
9655
9656 static int
9657 goodname(const char *p)
9658 {
9659         return endofname(p)[0] == '\0';
9660 }
9661
9662
9663 /*
9664  * Search for a command.  This is called before we fork so that the
9665  * location of the command will be available in the parent as well as
9666  * the child.  The check for "goodname" is an overly conservative
9667  * check that the name will not be subject to expansion.
9668  */
9669 static void
9670 prehash(union node *n)
9671 {
9672         struct cmdentry entry;
9673
9674         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9675                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9676 }
9677
9678
9679 /* ============ Builtin commands
9680  *
9681  * Builtin commands whose functions are closely tied to evaluation
9682  * are implemented here.
9683  */
9684
9685 /*
9686  * Handle break and continue commands.  Break, continue, and return are
9687  * all handled by setting the evalskip flag.  The evaluation routines
9688  * above all check this flag, and if it is set they start skipping
9689  * commands rather than executing them.  The variable skipcount is
9690  * the number of loops to break/continue, or the number of function
9691  * levels to return.  (The latter is always 1.)  It should probably
9692  * be an error to break out of more loops than exist, but it isn't
9693  * in the standard shell so we don't make it one here.
9694  */
9695 static int FAST_FUNC
9696 breakcmd(int argc UNUSED_PARAM, char **argv)
9697 {
9698         int n = argv[1] ? number(argv[1]) : 1;
9699
9700         if (n <= 0)
9701                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9702         if (n > loopnest)
9703                 n = loopnest;
9704         if (n > 0) {
9705                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9706                 skipcount = n;
9707         }
9708         return 0;
9709 }
9710
9711
9712 /*
9713  * This implements the input routines used by the parser.
9714  */
9715
9716 enum {
9717         INPUT_PUSH_FILE = 1,
9718         INPUT_NOFILE_OK = 2,
9719 };
9720
9721 static smallint checkkwd;
9722 /* values of checkkwd variable */
9723 #define CHKALIAS        0x1
9724 #define CHKKWD          0x2
9725 #define CHKNL           0x4
9726
9727 /*
9728  * Push a string back onto the input at this current parsefile level.
9729  * We handle aliases this way.
9730  */
9731 #if !ENABLE_ASH_ALIAS
9732 #define pushstring(s, ap) pushstring(s)
9733 #endif
9734 static void
9735 pushstring(char *s, struct alias *ap)
9736 {
9737         struct strpush *sp;
9738         int len;
9739
9740         len = strlen(s);
9741         INT_OFF;
9742         if (g_parsefile->strpush) {
9743                 sp = ckzalloc(sizeof(*sp));
9744                 sp->prev = g_parsefile->strpush;
9745         } else {
9746                 sp = &(g_parsefile->basestrpush);
9747         }
9748         g_parsefile->strpush = sp;
9749         sp->prev_string = g_parsefile->next_to_pgetc;
9750         sp->prev_left_in_line = g_parsefile->left_in_line;
9751         sp->unget = g_parsefile->unget;
9752         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9753 #if ENABLE_ASH_ALIAS
9754         sp->ap = ap;
9755         if (ap) {
9756                 ap->flag |= ALIASINUSE;
9757                 sp->string = s;
9758         }
9759 #endif
9760         g_parsefile->next_to_pgetc = s;
9761         g_parsefile->left_in_line = len;
9762         g_parsefile->unget = 0;
9763         INT_ON;
9764 }
9765
9766 static void
9767 popstring(void)
9768 {
9769         struct strpush *sp = g_parsefile->strpush;
9770
9771         INT_OFF;
9772 #if ENABLE_ASH_ALIAS
9773         if (sp->ap) {
9774                 if (g_parsefile->next_to_pgetc[-1] == ' '
9775                  || g_parsefile->next_to_pgetc[-1] == '\t'
9776                 ) {
9777                         checkkwd |= CHKALIAS;
9778                 }
9779                 if (sp->string != sp->ap->val) {
9780                         free(sp->string);
9781                 }
9782                 sp->ap->flag &= ~ALIASINUSE;
9783                 if (sp->ap->flag & ALIASDEAD) {
9784                         unalias(sp->ap->name);
9785                 }
9786         }
9787 #endif
9788         g_parsefile->next_to_pgetc = sp->prev_string;
9789         g_parsefile->left_in_line = sp->prev_left_in_line;
9790         g_parsefile->unget = sp->unget;
9791         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
9792         g_parsefile->strpush = sp->prev;
9793         if (sp != &(g_parsefile->basestrpush))
9794                 free(sp);
9795         INT_ON;
9796 }
9797
9798 static int
9799 preadfd(void)
9800 {
9801         int nr;
9802         char *buf = g_parsefile->buf;
9803
9804         g_parsefile->next_to_pgetc = buf;
9805 #if ENABLE_FEATURE_EDITING
9806  retry:
9807         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
9808                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9809         else {
9810                 int timeout = -1;
9811 # if ENABLE_ASH_IDLE_TIMEOUT
9812                 if (iflag) {
9813                         const char *tmout_var = lookupvar("TMOUT");
9814                         if (tmout_var) {
9815                                 timeout = atoi(tmout_var) * 1000;
9816                                 if (timeout <= 0)
9817                                         timeout = -1;
9818                         }
9819                 }
9820 # endif
9821 # if ENABLE_FEATURE_TAB_COMPLETION
9822                 line_input_state->path_lookup = pathval();
9823 # endif
9824                 reinit_unicode_for_ash();
9825                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
9826                 if (nr == 0) {
9827                         /* Ctrl+C pressed */
9828                         if (trap[SIGINT]) {
9829                                 buf[0] = '\n';
9830                                 buf[1] = '\0';
9831                                 raise(SIGINT);
9832                                 return 1;
9833                         }
9834                         goto retry;
9835                 }
9836                 if (nr < 0) {
9837                         if (errno == 0) {
9838                                 /* Ctrl+D pressed */
9839                                 nr = 0;
9840                         }
9841 # if ENABLE_ASH_IDLE_TIMEOUT
9842                         else if (errno == EAGAIN && timeout > 0) {
9843                                 puts("\007timed out waiting for input: auto-logout");
9844                                 exitshell();
9845                         }
9846 # endif
9847                 }
9848         }
9849 #else
9850         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9851 #endif
9852
9853 #if 0 /* disabled: nonblock_immune_read() handles this problem */
9854         if (nr < 0) {
9855                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9856                         int flags = fcntl(0, F_GETFL);
9857                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9858                                 flags &= ~O_NONBLOCK;
9859                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9860                                         out2str("sh: turning off NDELAY mode\n");
9861                                         goto retry;
9862                                 }
9863                         }
9864                 }
9865         }
9866 #endif
9867         return nr;
9868 }
9869
9870 /*
9871  * Refill the input buffer and return the next input character:
9872  *
9873  * 1) If a string was pushed back on the input, pop it;
9874  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9875  *    or we are reading from a string so we can't refill the buffer,
9876  *    return EOF.
9877  * 3) If there is more stuff in this buffer, use it else call read to fill it.
9878  * 4) Process input up to the next newline, deleting nul characters.
9879  */
9880 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9881 #define pgetc_debug(...) ((void)0)
9882 static int pgetc(void);
9883 static int
9884 preadbuffer(void)
9885 {
9886         char *q;
9887         int more;
9888
9889         if (g_parsefile->strpush) {
9890 #if ENABLE_ASH_ALIAS
9891                 if (g_parsefile->left_in_line == -1
9892                  && g_parsefile->strpush->ap
9893                  && g_parsefile->next_to_pgetc[-1] != ' '
9894                  && g_parsefile->next_to_pgetc[-1] != '\t'
9895                 ) {
9896                         pgetc_debug("preadbuffer PEOA");
9897                         return PEOA;
9898                 }
9899 #endif
9900                 popstring();
9901                 return pgetc();
9902         }
9903         /* on both branches above g_parsefile->left_in_line < 0.
9904          * "pgetc" needs refilling.
9905          */
9906
9907         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9908          * pungetc() may increment it a few times.
9909          * Assuming it won't increment it to less than -90.
9910          */
9911         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9912                 pgetc_debug("preadbuffer PEOF1");
9913                 /* even in failure keep left_in_line and next_to_pgetc
9914                  * in lock step, for correct multi-layer pungetc.
9915                  * left_in_line was decremented before preadbuffer(),
9916                  * must inc next_to_pgetc: */
9917                 g_parsefile->next_to_pgetc++;
9918                 return PEOF;
9919         }
9920
9921         more = g_parsefile->left_in_buffer;
9922         if (more <= 0) {
9923                 flush_stdout_stderr();
9924  again:
9925                 more = preadfd();
9926                 if (more <= 0) {
9927                         /* don't try reading again */
9928                         g_parsefile->left_in_line = -99;
9929                         pgetc_debug("preadbuffer PEOF2");
9930                         g_parsefile->next_to_pgetc++;
9931                         return PEOF;
9932                 }
9933         }
9934
9935         /* Find out where's the end of line.
9936          * Set g_parsefile->left_in_line
9937          * and g_parsefile->left_in_buffer acordingly.
9938          * NUL chars are deleted.
9939          */
9940         q = g_parsefile->next_to_pgetc;
9941         for (;;) {
9942                 char c;
9943
9944                 more--;
9945
9946                 c = *q;
9947                 if (c == '\0') {
9948                         memmove(q, q + 1, more);
9949                 } else {
9950                         q++;
9951                         if (c == '\n') {
9952                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9953                                 break;
9954                         }
9955                 }
9956
9957                 if (more <= 0) {
9958                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9959                         if (g_parsefile->left_in_line < 0)
9960                                 goto again;
9961                         break;
9962                 }
9963         }
9964         g_parsefile->left_in_buffer = more;
9965
9966         if (vflag) {
9967                 char save = *q;
9968                 *q = '\0';
9969                 out2str(g_parsefile->next_to_pgetc);
9970                 *q = save;
9971         }
9972
9973         pgetc_debug("preadbuffer at %d:%p'%s'",
9974                         g_parsefile->left_in_line,
9975                         g_parsefile->next_to_pgetc,
9976                         g_parsefile->next_to_pgetc);
9977         return (unsigned char)*g_parsefile->next_to_pgetc++;
9978 }
9979
9980 static void
9981 nlprompt(void)
9982 {
9983         g_parsefile->linno++;
9984         setprompt_if(doprompt, 2);
9985 }
9986 static void
9987 nlnoprompt(void)
9988 {
9989         g_parsefile->linno++;
9990         needprompt = doprompt;
9991 }
9992
9993 static int
9994 pgetc(void)
9995 {
9996         int c;
9997
9998         pgetc_debug("pgetc at %d:%p'%s'",
9999                         g_parsefile->left_in_line,
10000                         g_parsefile->next_to_pgetc,
10001                         g_parsefile->next_to_pgetc);
10002         if (g_parsefile->unget)
10003                 return g_parsefile->lastc[--g_parsefile->unget];
10004
10005         if (--g_parsefile->left_in_line >= 0)
10006                 c = (signed char)*g_parsefile->next_to_pgetc++;
10007         else
10008                 c = preadbuffer();
10009
10010         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10011         g_parsefile->lastc[0] = c;
10012
10013         return c;
10014 }
10015
10016 #if ENABLE_ASH_ALIAS
10017 static int
10018 pgetc_without_PEOA(void)
10019 {
10020         int c;
10021         do {
10022                 pgetc_debug("pgetc at %d:%p'%s'",
10023                                 g_parsefile->left_in_line,
10024                                 g_parsefile->next_to_pgetc,
10025                                 g_parsefile->next_to_pgetc);
10026                 c = pgetc();
10027         } while (c == PEOA);
10028         return c;
10029 }
10030 #else
10031 # define pgetc_without_PEOA() pgetc()
10032 #endif
10033
10034 /*
10035  * Read a line from the script.
10036  */
10037 static char *
10038 pfgets(char *line, int len)
10039 {
10040         char *p = line;
10041         int nleft = len;
10042         int c;
10043
10044         while (--nleft > 0) {
10045                 c = pgetc_without_PEOA();
10046                 if (c == PEOF) {
10047                         if (p == line)
10048                                 return NULL;
10049                         break;
10050                 }
10051                 *p++ = c;
10052                 if (c == '\n')
10053                         break;
10054         }
10055         *p = '\0';
10056         return line;
10057 }
10058
10059 /*
10060  * Undo a call to pgetc.  Only two characters may be pushed back.
10061  * PEOF may be pushed back.
10062  */
10063 static void
10064 pungetc(void)
10065 {
10066         g_parsefile->unget++;
10067 }
10068
10069 /* This one eats backslash+newline */
10070 static int
10071 pgetc_eatbnl(void)
10072 {
10073         int c;
10074
10075         while ((c = pgetc()) == '\\') {
10076                 if (pgetc() != '\n') {
10077                         pungetc();
10078                         break;
10079                 }
10080
10081                 nlprompt();
10082         }
10083
10084         return c;
10085 }
10086
10087 /*
10088  * To handle the "." command, a stack of input files is used.  Pushfile
10089  * adds a new entry to the stack and popfile restores the previous level.
10090  */
10091 static void
10092 pushfile(void)
10093 {
10094         struct parsefile *pf;
10095
10096         pf = ckzalloc(sizeof(*pf));
10097         pf->prev = g_parsefile;
10098         pf->pf_fd = -1;
10099         /*pf->strpush = NULL; - ckzalloc did it */
10100         /*pf->basestrpush.prev = NULL;*/
10101         /*pf->unget = 0;*/
10102         g_parsefile = pf;
10103 }
10104
10105 static void
10106 popfile(void)
10107 {
10108         struct parsefile *pf = g_parsefile;
10109
10110         INT_OFF;
10111         if (pf->pf_fd >= 0)
10112                 close(pf->pf_fd);
10113         free(pf->buf);
10114         while (pf->strpush)
10115                 popstring();
10116         g_parsefile = pf->prev;
10117         free(pf);
10118         INT_ON;
10119 }
10120
10121 /*
10122  * Return to top level.
10123  */
10124 static void
10125 popallfiles(void)
10126 {
10127         while (g_parsefile != &basepf)
10128                 popfile();
10129 }
10130
10131 /*
10132  * Close the file(s) that the shell is reading commands from.  Called
10133  * after a fork is done.
10134  */
10135 static void
10136 closescript(void)
10137 {
10138         popallfiles();
10139         if (g_parsefile->pf_fd > 0) {
10140                 close(g_parsefile->pf_fd);
10141                 g_parsefile->pf_fd = 0;
10142         }
10143 }
10144
10145 /*
10146  * Like setinputfile, but takes an open file descriptor.  Call this with
10147  * interrupts off.
10148  */
10149 static void
10150 setinputfd(int fd, int push)
10151 {
10152         if (push) {
10153                 pushfile();
10154                 g_parsefile->buf = NULL;
10155         }
10156         g_parsefile->pf_fd = fd;
10157         if (g_parsefile->buf == NULL)
10158                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10159         g_parsefile->left_in_buffer = 0;
10160         g_parsefile->left_in_line = 0;
10161         g_parsefile->linno = 1;
10162 }
10163
10164 /*
10165  * Set the input to take input from a file.  If push is set, push the
10166  * old input onto the stack first.
10167  */
10168 static int
10169 setinputfile(const char *fname, int flags)
10170 {
10171         int fd;
10172
10173         INT_OFF;
10174         fd = open(fname, O_RDONLY);
10175         if (fd < 0) {
10176                 if (flags & INPUT_NOFILE_OK)
10177                         goto out;
10178                 exitstatus = 127;
10179                 ash_msg_and_raise_error("can't open '%s'", fname);
10180         }
10181         if (fd < 10)
10182                 fd = savefd(fd);
10183         else
10184                 close_on_exec_on(fd);
10185         setinputfd(fd, flags & INPUT_PUSH_FILE);
10186  out:
10187         INT_ON;
10188         return fd;
10189 }
10190
10191 /*
10192  * Like setinputfile, but takes input from a string.
10193  */
10194 static void
10195 setinputstring(char *string)
10196 {
10197         INT_OFF;
10198         pushfile();
10199         g_parsefile->next_to_pgetc = string;
10200         g_parsefile->left_in_line = strlen(string);
10201         g_parsefile->buf = NULL;
10202         g_parsefile->linno = 1;
10203         INT_ON;
10204 }
10205
10206
10207 /*
10208  * Routines to check for mail.
10209  */
10210
10211 #if ENABLE_ASH_MAIL
10212
10213 /* Hash of mtimes of mailboxes */
10214 static unsigned mailtime_hash;
10215 /* Set if MAIL or MAILPATH is changed. */
10216 static smallint mail_var_path_changed;
10217
10218 /*
10219  * Print appropriate message(s) if mail has arrived.
10220  * If mail_var_path_changed is set,
10221  * then the value of MAIL has mail_var_path_changed,
10222  * so we just update the values.
10223  */
10224 static void
10225 chkmail(void)
10226 {
10227         const char *mpath;
10228         char *p;
10229         char *q;
10230         unsigned new_hash;
10231         struct stackmark smark;
10232         struct stat statb;
10233
10234         setstackmark(&smark);
10235         mpath = mpathset() ? mpathval() : mailval();
10236         new_hash = 0;
10237         for (;;) {
10238                 p = path_advance(&mpath, nullstr);
10239                 if (p == NULL)
10240                         break;
10241                 if (*p == '\0')
10242                         continue;
10243                 for (q = p; *q; q++)
10244                         continue;
10245 #if DEBUG
10246                 if (q[-1] != '/')
10247                         abort();
10248 #endif
10249                 q[-1] = '\0';                   /* delete trailing '/' */
10250                 if (stat(p, &statb) < 0) {
10251                         continue;
10252                 }
10253                 /* Very simplistic "hash": just a sum of all mtimes */
10254                 new_hash += (unsigned)statb.st_mtime;
10255         }
10256         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10257                 if (mailtime_hash != 0)
10258                         out2str("you have mail\n");
10259                 mailtime_hash = new_hash;
10260         }
10261         mail_var_path_changed = 0;
10262         popstackmark(&smark);
10263 }
10264
10265 static void FAST_FUNC
10266 changemail(const char *val UNUSED_PARAM)
10267 {
10268         mail_var_path_changed = 1;
10269 }
10270
10271 #endif /* ASH_MAIL */
10272
10273
10274 /* ============ ??? */
10275
10276 /*
10277  * Set the shell parameters.
10278  */
10279 static void
10280 setparam(char **argv)
10281 {
10282         char **newparam;
10283         char **ap;
10284         int nparam;
10285
10286         for (nparam = 0; argv[nparam]; nparam++)
10287                 continue;
10288         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10289         while (*argv) {
10290                 *ap++ = ckstrdup(*argv++);
10291         }
10292         *ap = NULL;
10293         freeparam(&shellparam);
10294         shellparam.malloced = 1;
10295         shellparam.nparam = nparam;
10296         shellparam.p = newparam;
10297 #if ENABLE_ASH_GETOPTS
10298         shellparam.optind = 1;
10299         shellparam.optoff = -1;
10300 #endif
10301 }
10302
10303 /*
10304  * Process shell options.  The global variable argptr contains a pointer
10305  * to the argument list; we advance it past the options.
10306  *
10307  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10308  * For a non-interactive shell, an error condition encountered
10309  * by a special built-in ... shall cause the shell to write a diagnostic message
10310  * to standard error and exit as shown in the following table:
10311  * Error                                           Special Built-In
10312  * ...
10313  * Utility syntax error (option or operand error)  Shall exit
10314  * ...
10315  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10316  * we see that bash does not do that (set "finishes" with error code 1 instead,
10317  * and shell continues), and people rely on this behavior!
10318  * Testcase:
10319  * set -o barfoo 2>/dev/null
10320  * echo $?
10321  *
10322  * Oh well. Let's mimic that.
10323  */
10324 static int
10325 plus_minus_o(char *name, int val)
10326 {
10327         int i;
10328
10329         if (name) {
10330                 for (i = 0; i < NOPTS; i++) {
10331                         if (strcmp(name, optnames(i)) == 0) {
10332                                 optlist[i] = val;
10333                                 return 0;
10334                         }
10335                 }
10336                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10337                 return 1;
10338         }
10339         for (i = 0; i < NOPTS; i++) {
10340                 if (val) {
10341                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10342                 } else {
10343                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10344                 }
10345         }
10346         return 0;
10347 }
10348 static void
10349 setoption(int flag, int val)
10350 {
10351         int i;
10352
10353         for (i = 0; i < NOPTS; i++) {
10354                 if (optletters(i) == flag) {
10355                         optlist[i] = val;
10356                         return;
10357                 }
10358         }
10359         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10360         /* NOTREACHED */
10361 }
10362 static int
10363 options(int cmdline)
10364 {
10365         char *p;
10366         int val;
10367         int c;
10368
10369         if (cmdline)
10370                 minusc = NULL;
10371         while ((p = *argptr) != NULL) {
10372                 c = *p++;
10373                 if (c != '-' && c != '+')
10374                         break;
10375                 argptr++;
10376                 val = 0; /* val = 0 if c == '+' */
10377                 if (c == '-') {
10378                         val = 1;
10379                         if (p[0] == '\0' || LONE_DASH(p)) {
10380                                 if (!cmdline) {
10381                                         /* "-" means turn off -x and -v */
10382                                         if (p[0] == '\0')
10383                                                 xflag = vflag = 0;
10384                                         /* "--" means reset params */
10385                                         else if (*argptr == NULL)
10386                                                 setparam(argptr);
10387                                 }
10388                                 break;    /* "-" or "--" terminates options */
10389                         }
10390                 }
10391                 /* first char was + or - */
10392                 while ((c = *p++) != '\0') {
10393                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10394                         if (c == 'c' && cmdline) {
10395                                 minusc = p;     /* command is after shell args */
10396                         } else if (c == 'o') {
10397                                 if (plus_minus_o(*argptr, val)) {
10398                                         /* it already printed err message */
10399                                         return 1; /* error */
10400                                 }
10401                                 if (*argptr)
10402                                         argptr++;
10403                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10404                                 isloginsh = 1;
10405                         /* bash does not accept +-login, we also won't */
10406                         } else if (cmdline && val && (c == '-')) { /* long options */
10407                                 if (strcmp(p, "login") == 0)
10408                                         isloginsh = 1;
10409                                 break;
10410                         } else {
10411                                 setoption(c, val);
10412                         }
10413                 }
10414         }
10415         return 0;
10416 }
10417
10418 /*
10419  * The shift builtin command.
10420  */
10421 static int FAST_FUNC
10422 shiftcmd(int argc UNUSED_PARAM, char **argv)
10423 {
10424         int n;
10425         char **ap1, **ap2;
10426
10427         n = 1;
10428         if (argv[1])
10429                 n = number(argv[1]);
10430         if (n > shellparam.nparam)
10431                 n = 0; /* bash compat, was = shellparam.nparam; */
10432         INT_OFF;
10433         shellparam.nparam -= n;
10434         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10435                 if (shellparam.malloced)
10436                         free(*ap1);
10437         }
10438         ap2 = shellparam.p;
10439         while ((*ap2++ = *ap1++) != NULL)
10440                 continue;
10441 #if ENABLE_ASH_GETOPTS
10442         shellparam.optind = 1;
10443         shellparam.optoff = -1;
10444 #endif
10445         INT_ON;
10446         return 0;
10447 }
10448
10449 /*
10450  * POSIX requires that 'set' (but not export or readonly) output the
10451  * variables in lexicographic order - by the locale's collating order (sigh).
10452  * Maybe we could keep them in an ordered balanced binary tree
10453  * instead of hashed lists.
10454  * For now just roll 'em through qsort for printing...
10455  */
10456 static int
10457 showvars(const char *sep_prefix, int on, int off)
10458 {
10459         const char *sep;
10460         char **ep, **epend;
10461
10462         ep = listvars(on, off, &epend);
10463         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10464
10465         sep = *sep_prefix ? " " : sep_prefix;
10466
10467         for (; ep < epend; ep++) {
10468                 const char *p;
10469                 const char *q;
10470
10471                 p = strchrnul(*ep, '=');
10472                 q = nullstr;
10473                 if (*p)
10474                         q = single_quote(++p);
10475                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10476         }
10477         return 0;
10478 }
10479
10480 /*
10481  * The set command builtin.
10482  */
10483 static int FAST_FUNC
10484 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10485 {
10486         int retval;
10487
10488         if (!argv[1])
10489                 return showvars(nullstr, 0, VUNSET);
10490
10491         INT_OFF;
10492         retval = options(/*cmdline:*/ 0);
10493         if (retval == 0) { /* if no parse error... */
10494                 optschanged();
10495                 if (*argptr != NULL) {
10496                         setparam(argptr);
10497                 }
10498         }
10499         INT_ON;
10500         return retval;
10501 }
10502
10503 #if ENABLE_ASH_RANDOM_SUPPORT
10504 static void FAST_FUNC
10505 change_random(const char *value)
10506 {
10507         uint32_t t;
10508
10509         if (value == NULL) {
10510                 /* "get", generate */
10511                 t = next_random(&random_gen);
10512                 /* set without recursion */
10513                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10514                 vrandom.flags &= ~VNOFUNC;
10515         } else {
10516                 /* set/reset */
10517                 t = strtoul(value, NULL, 10);
10518                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10519         }
10520 }
10521 #endif
10522
10523 #if ENABLE_ASH_GETOPTS
10524 static int
10525 getopts(char *optstr, char *optvar, char **optfirst)
10526 {
10527         char *p, *q;
10528         char c = '?';
10529         int done = 0;
10530         char sbuf[2];
10531         char **optnext;
10532         int ind = shellparam.optind;
10533         int off = shellparam.optoff;
10534
10535         sbuf[1] = '\0';
10536
10537         shellparam.optind = -1;
10538         optnext = optfirst + ind - 1;
10539
10540         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10541                 p = NULL;
10542         else
10543                 p = optnext[-1] + off;
10544         if (p == NULL || *p == '\0') {
10545                 /* Current word is done, advance */
10546                 p = *optnext;
10547                 if (p == NULL || *p != '-' || *++p == '\0') {
10548  atend:
10549                         p = NULL;
10550                         done = 1;
10551                         goto out;
10552                 }
10553                 optnext++;
10554                 if (LONE_DASH(p))        /* check for "--" */
10555                         goto atend;
10556         }
10557
10558         c = *p++;
10559         for (q = optstr; *q != c;) {
10560                 if (*q == '\0') {
10561                         if (optstr[0] == ':') {
10562                                 sbuf[0] = c;
10563                                 /*sbuf[1] = '\0'; - already is */
10564                                 setvar0("OPTARG", sbuf);
10565                         } else {
10566                                 fprintf(stderr, "Illegal option -%c\n", c);
10567                                 unsetvar("OPTARG");
10568                         }
10569                         c = '?';
10570                         goto out;
10571                 }
10572                 if (*++q == ':')
10573                         q++;
10574         }
10575
10576         if (*++q == ':') {
10577                 if (*p == '\0' && (p = *optnext) == NULL) {
10578                         if (optstr[0] == ':') {
10579                                 sbuf[0] = c;
10580                                 /*sbuf[1] = '\0'; - already is */
10581                                 setvar0("OPTARG", sbuf);
10582                                 c = ':';
10583                         } else {
10584                                 fprintf(stderr, "No arg for -%c option\n", c);
10585                                 unsetvar("OPTARG");
10586                                 c = '?';
10587                         }
10588                         goto out;
10589                 }
10590
10591                 if (p == *optnext)
10592                         optnext++;
10593                 setvar0("OPTARG", p);
10594                 p = NULL;
10595         } else
10596                 setvar0("OPTARG", nullstr);
10597  out:
10598         ind = optnext - optfirst + 1;
10599         setvar("OPTIND", itoa(ind), VNOFUNC);
10600         sbuf[0] = c;
10601         /*sbuf[1] = '\0'; - already is */
10602         setvar0(optvar, sbuf);
10603
10604         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10605         shellparam.optind = ind;
10606
10607         return done;
10608 }
10609
10610 /*
10611  * The getopts builtin.  Shellparam.optnext points to the next argument
10612  * to be processed.  Shellparam.optptr points to the next character to
10613  * be processed in the current argument.  If shellparam.optnext is NULL,
10614  * then it's the first time getopts has been called.
10615  */
10616 static int FAST_FUNC
10617 getoptscmd(int argc, char **argv)
10618 {
10619         char **optbase;
10620
10621         if (argc < 3)
10622                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10623         if (argc == 3) {
10624                 optbase = shellparam.p;
10625                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10626                         shellparam.optind = 1;
10627                         shellparam.optoff = -1;
10628                 }
10629         } else {
10630                 optbase = &argv[3];
10631                 if ((unsigned)shellparam.optind > argc - 2) {
10632                         shellparam.optind = 1;
10633                         shellparam.optoff = -1;
10634                 }
10635         }
10636
10637         return getopts(argv[1], argv[2], optbase);
10638 }
10639 #endif /* ASH_GETOPTS */
10640
10641
10642 /* ============ Shell parser */
10643
10644 struct heredoc {
10645         struct heredoc *next;   /* next here document in list */
10646         union node *here;       /* redirection node */
10647         char *eofmark;          /* string indicating end of input */
10648         smallint striptabs;     /* if set, strip leading tabs */
10649 };
10650
10651 static smallint tokpushback;           /* last token pushed back */
10652 static smallint quoteflag;             /* set if (part of) last token was quoted */
10653 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10654 static struct heredoc *heredoclist;    /* list of here documents to read */
10655 static char *wordtext;                 /* text of last word returned by readtoken */
10656 static struct nodelist *backquotelist;
10657 static union node *redirnode;
10658 static struct heredoc *heredoc;
10659
10660 static const char *
10661 tokname(char *buf, int tok)
10662 {
10663         if (tok < TSEMI)
10664                 return tokname_array[tok];
10665         sprintf(buf, "\"%s\"", tokname_array[tok]);
10666         return buf;
10667 }
10668
10669 /* raise_error_unexpected_syntax:
10670  * Called when an unexpected token is read during the parse.  The argument
10671  * is the token that is expected, or -1 if more than one type of token can
10672  * occur at this point.
10673  */
10674 static void raise_error_unexpected_syntax(int) NORETURN;
10675 static void
10676 raise_error_unexpected_syntax(int token)
10677 {
10678         char msg[64];
10679         char buf[16];
10680         int l;
10681
10682         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10683         if (token >= 0)
10684                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10685         raise_error_syntax(msg);
10686         /* NOTREACHED */
10687 }
10688
10689 #define EOFMARKLEN 79
10690
10691 /* parsing is heavily cross-recursive, need these forward decls */
10692 static union node *andor(void);
10693 static union node *pipeline(void);
10694 static union node *parse_command(void);
10695 static void parseheredoc(void);
10696 static int peektoken(void);
10697 static int readtoken(void);
10698
10699 static union node *
10700 list(int nlflag)
10701 {
10702         union node *n1, *n2, *n3;
10703         int tok;
10704
10705         n1 = NULL;
10706         for (;;) {
10707                 switch (peektoken()) {
10708                 case TNL:
10709                         if (!(nlflag & 1))
10710                                 break;
10711                         parseheredoc();
10712                         return n1;
10713
10714                 case TEOF:
10715                         if (!n1 && (nlflag & 1))
10716                                 n1 = NODE_EOF;
10717                         parseheredoc();
10718                         return n1;
10719                 }
10720
10721                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10722                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10723                         return n1;
10724                 nlflag |= 2;
10725
10726                 n2 = andor();
10727                 tok = readtoken();
10728                 if (tok == TBACKGND) {
10729                         if (n2->type == NPIPE) {
10730                                 n2->npipe.pipe_backgnd = 1;
10731                         } else {
10732                                 if (n2->type != NREDIR) {
10733                                         n3 = stzalloc(sizeof(struct nredir));
10734                                         n3->nredir.n = n2;
10735                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10736                                         n2 = n3;
10737                                 }
10738                                 n2->type = NBACKGND;
10739                         }
10740                 }
10741                 if (n1 == NULL) {
10742                         n1 = n2;
10743                 } else {
10744                         n3 = stzalloc(sizeof(struct nbinary));
10745                         n3->type = NSEMI;
10746                         n3->nbinary.ch1 = n1;
10747                         n3->nbinary.ch2 = n2;
10748                         n1 = n3;
10749                 }
10750                 switch (tok) {
10751                 case TNL:
10752                 case TEOF:
10753                         tokpushback = 1;
10754                         /* fall through */
10755                 case TBACKGND:
10756                 case TSEMI:
10757                         break;
10758                 default:
10759                         if ((nlflag & 1))
10760                                 raise_error_unexpected_syntax(-1);
10761                         tokpushback = 1;
10762                         return n1;
10763                 }
10764         }
10765 }
10766
10767 static union node *
10768 andor(void)
10769 {
10770         union node *n1, *n2, *n3;
10771         int t;
10772
10773         n1 = pipeline();
10774         for (;;) {
10775                 t = readtoken();
10776                 if (t == TAND) {
10777                         t = NAND;
10778                 } else if (t == TOR) {
10779                         t = NOR;
10780                 } else {
10781                         tokpushback = 1;
10782                         return n1;
10783                 }
10784                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10785                 n2 = pipeline();
10786                 n3 = stzalloc(sizeof(struct nbinary));
10787                 n3->type = t;
10788                 n3->nbinary.ch1 = n1;
10789                 n3->nbinary.ch2 = n2;
10790                 n1 = n3;
10791         }
10792 }
10793
10794 static union node *
10795 pipeline(void)
10796 {
10797         union node *n1, *n2, *pipenode;
10798         struct nodelist *lp, *prev;
10799         int negate;
10800
10801         negate = 0;
10802         TRACE(("pipeline: entered\n"));
10803         if (readtoken() == TNOT) {
10804                 negate = !negate;
10805                 checkkwd = CHKKWD | CHKALIAS;
10806         } else
10807                 tokpushback = 1;
10808         n1 = parse_command();
10809         if (readtoken() == TPIPE) {
10810                 pipenode = stzalloc(sizeof(struct npipe));
10811                 pipenode->type = NPIPE;
10812                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10813                 lp = stzalloc(sizeof(struct nodelist));
10814                 pipenode->npipe.cmdlist = lp;
10815                 lp->n = n1;
10816                 do {
10817                         prev = lp;
10818                         lp = stzalloc(sizeof(struct nodelist));
10819                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10820                         lp->n = parse_command();
10821                         prev->next = lp;
10822                 } while (readtoken() == TPIPE);
10823                 lp->next = NULL;
10824                 n1 = pipenode;
10825         }
10826         tokpushback = 1;
10827         if (negate) {
10828                 n2 = stzalloc(sizeof(struct nnot));
10829                 n2->type = NNOT;
10830                 n2->nnot.com = n1;
10831                 return n2;
10832         }
10833         return n1;
10834 }
10835
10836 static union node *
10837 makename(void)
10838 {
10839         union node *n;
10840
10841         n = stzalloc(sizeof(struct narg));
10842         n->type = NARG;
10843         /*n->narg.next = NULL; - stzalloc did it */
10844         n->narg.text = wordtext;
10845         n->narg.backquote = backquotelist;
10846         return n;
10847 }
10848
10849 static void
10850 fixredir(union node *n, const char *text, int err)
10851 {
10852         int fd;
10853
10854         TRACE(("Fix redir %s %d\n", text, err));
10855         if (!err)
10856                 n->ndup.vname = NULL;
10857
10858         fd = bb_strtou(text, NULL, 10);
10859         if (!errno && fd >= 0)
10860                 n->ndup.dupfd = fd;
10861         else if (LONE_DASH(text))
10862                 n->ndup.dupfd = -1;
10863         else {
10864                 if (err)
10865                         raise_error_syntax("bad fd number");
10866                 n->ndup.vname = makename();
10867         }
10868 }
10869
10870 /*
10871  * Returns true if the text contains nothing to expand (no dollar signs
10872  * or backquotes).
10873  */
10874 static int
10875 noexpand(const char *text)
10876 {
10877         unsigned char c;
10878
10879         while ((c = *text++) != '\0') {
10880                 if (c == CTLQUOTEMARK)
10881                         continue;
10882                 if (c == CTLESC)
10883                         text++;
10884                 else if (SIT(c, BASESYNTAX) == CCTL)
10885                         return 0;
10886         }
10887         return 1;
10888 }
10889
10890 static void
10891 parsefname(void)
10892 {
10893         union node *n = redirnode;
10894
10895         if (readtoken() != TWORD)
10896                 raise_error_unexpected_syntax(-1);
10897         if (n->type == NHERE) {
10898                 struct heredoc *here = heredoc;
10899                 struct heredoc *p;
10900                 int i;
10901
10902                 if (quoteflag == 0)
10903                         n->type = NXHERE;
10904                 TRACE(("Here document %d\n", n->type));
10905                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10906                         raise_error_syntax("illegal eof marker for << redirection");
10907                 rmescapes(wordtext, 0);
10908                 here->eofmark = wordtext;
10909                 here->next = NULL;
10910                 if (heredoclist == NULL)
10911                         heredoclist = here;
10912                 else {
10913                         for (p = heredoclist; p->next; p = p->next)
10914                                 continue;
10915                         p->next = here;
10916                 }
10917         } else if (n->type == NTOFD || n->type == NFROMFD) {
10918                 fixredir(n, wordtext, 0);
10919         } else {
10920                 n->nfile.fname = makename();
10921         }
10922 }
10923
10924 static union node *
10925 simplecmd(void)
10926 {
10927         union node *args, **app;
10928         union node *n = NULL;
10929         union node *vars, **vpp;
10930         union node **rpp, *redir;
10931         int savecheckkwd;
10932 #if ENABLE_ASH_BASH_COMPAT
10933         smallint double_brackets_flag = 0;
10934         smallint function_flag = 0;
10935 #endif
10936
10937         args = NULL;
10938         app = &args;
10939         vars = NULL;
10940         vpp = &vars;
10941         redir = NULL;
10942         rpp = &redir;
10943
10944         savecheckkwd = CHKALIAS;
10945         for (;;) {
10946                 int t;
10947                 checkkwd = savecheckkwd;
10948                 t = readtoken();
10949                 switch (t) {
10950 #if ENABLE_ASH_BASH_COMPAT
10951                 case TFUNCTION:
10952                         if (peektoken() != TWORD)
10953                                 raise_error_unexpected_syntax(TWORD);
10954                         function_flag = 1;
10955                         break;
10956                 case TAND: /* "&&" */
10957                 case TOR: /* "||" */
10958                         if (!double_brackets_flag) {
10959                                 tokpushback = 1;
10960                                 goto out;
10961                         }
10962                         wordtext = (char *) (t == TAND ? "-a" : "-o");
10963 #endif
10964                 case TWORD:
10965                         n = stzalloc(sizeof(struct narg));
10966                         n->type = NARG;
10967                         /*n->narg.next = NULL; - stzalloc did it */
10968                         n->narg.text = wordtext;
10969 #if ENABLE_ASH_BASH_COMPAT
10970                         if (strcmp("[[", wordtext) == 0)
10971                                 double_brackets_flag = 1;
10972                         else if (strcmp("]]", wordtext) == 0)
10973                                 double_brackets_flag = 0;
10974 #endif
10975                         n->narg.backquote = backquotelist;
10976                         if (savecheckkwd && isassignment(wordtext)) {
10977                                 *vpp = n;
10978                                 vpp = &n->narg.next;
10979                         } else {
10980                                 *app = n;
10981                                 app = &n->narg.next;
10982                                 savecheckkwd = 0;
10983                         }
10984 #if ENABLE_ASH_BASH_COMPAT
10985                         if (function_flag) {
10986                                 checkkwd = CHKNL | CHKKWD;
10987                                 switch (peektoken()) {
10988                                 case TBEGIN:
10989                                 case TIF:
10990                                 case TCASE:
10991                                 case TUNTIL:
10992                                 case TWHILE:
10993                                 case TFOR:
10994                                         goto do_func;
10995                                 case TLP:
10996                                         function_flag = 0;
10997                                         break;
10998                                 case TWORD:
10999                                         if (strcmp("[[", wordtext) == 0)
11000                                                 goto do_func;
11001                                         /* fall through */
11002                                 default:
11003                                         raise_error_unexpected_syntax(-1);
11004                                 }
11005                         }
11006 #endif
11007                         break;
11008                 case TREDIR:
11009                         *rpp = n = redirnode;
11010                         rpp = &n->nfile.next;
11011                         parsefname();   /* read name of redirection file */
11012                         break;
11013                 case TLP:
11014  IF_ASH_BASH_COMPAT(do_func:)
11015                         if (args && app == &args->narg.next
11016                          && !vars && !redir
11017                         ) {
11018                                 struct builtincmd *bcmd;
11019                                 const char *name;
11020
11021                                 /* We have a function */
11022                                 if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP)
11023                                         raise_error_unexpected_syntax(TRP);
11024                                 name = n->narg.text;
11025                                 if (!goodname(name)
11026                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11027                                 ) {
11028                                         raise_error_syntax("bad function name");
11029                                 }
11030                                 n->type = NDEFUN;
11031                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11032                                 n->narg.next = parse_command();
11033                                 return n;
11034                         }
11035                         IF_ASH_BASH_COMPAT(function_flag = 0;)
11036                         /* fall through */
11037                 default:
11038                         tokpushback = 1;
11039                         goto out;
11040                 }
11041         }
11042  out:
11043         *app = NULL;
11044         *vpp = NULL;
11045         *rpp = NULL;
11046         n = stzalloc(sizeof(struct ncmd));
11047         n->type = NCMD;
11048         n->ncmd.args = args;
11049         n->ncmd.assign = vars;
11050         n->ncmd.redirect = redir;
11051         return n;
11052 }
11053
11054 static union node *
11055 parse_command(void)
11056 {
11057         union node *n1, *n2;
11058         union node *ap, **app;
11059         union node *cp, **cpp;
11060         union node *redir, **rpp;
11061         union node **rpp2;
11062         int t;
11063
11064         redir = NULL;
11065         rpp2 = &redir;
11066
11067         switch (readtoken()) {
11068         default:
11069                 raise_error_unexpected_syntax(-1);
11070                 /* NOTREACHED */
11071         case TIF:
11072                 n1 = stzalloc(sizeof(struct nif));
11073                 n1->type = NIF;
11074                 n1->nif.test = list(0);
11075                 if (readtoken() != TTHEN)
11076                         raise_error_unexpected_syntax(TTHEN);
11077                 n1->nif.ifpart = list(0);
11078                 n2 = n1;
11079                 while (readtoken() == TELIF) {
11080                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11081                         n2 = n2->nif.elsepart;
11082                         n2->type = NIF;
11083                         n2->nif.test = list(0);
11084                         if (readtoken() != TTHEN)
11085                                 raise_error_unexpected_syntax(TTHEN);
11086                         n2->nif.ifpart = list(0);
11087                 }
11088                 if (lasttoken == TELSE)
11089                         n2->nif.elsepart = list(0);
11090                 else {
11091                         n2->nif.elsepart = NULL;
11092                         tokpushback = 1;
11093                 }
11094                 t = TFI;
11095                 break;
11096         case TWHILE:
11097         case TUNTIL: {
11098                 int got;
11099                 n1 = stzalloc(sizeof(struct nbinary));
11100                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11101                 n1->nbinary.ch1 = list(0);
11102                 got = readtoken();
11103                 if (got != TDO) {
11104                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11105                                         got == TWORD ? wordtext : ""));
11106                         raise_error_unexpected_syntax(TDO);
11107                 }
11108                 n1->nbinary.ch2 = list(0);
11109                 t = TDONE;
11110                 break;
11111         }
11112         case TFOR:
11113                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11114                         raise_error_syntax("bad for loop variable");
11115                 n1 = stzalloc(sizeof(struct nfor));
11116                 n1->type = NFOR;
11117                 n1->nfor.var = wordtext;
11118                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11119                 if (readtoken() == TIN) {
11120                         app = &ap;
11121                         while (readtoken() == TWORD) {
11122                                 n2 = stzalloc(sizeof(struct narg));
11123                                 n2->type = NARG;
11124                                 /*n2->narg.next = NULL; - stzalloc did it */
11125                                 n2->narg.text = wordtext;
11126                                 n2->narg.backquote = backquotelist;
11127                                 *app = n2;
11128                                 app = &n2->narg.next;
11129                         }
11130                         *app = NULL;
11131                         n1->nfor.args = ap;
11132                         if (lasttoken != TNL && lasttoken != TSEMI)
11133                                 raise_error_unexpected_syntax(-1);
11134                 } else {
11135                         n2 = stzalloc(sizeof(struct narg));
11136                         n2->type = NARG;
11137                         /*n2->narg.next = NULL; - stzalloc did it */
11138                         n2->narg.text = (char *)dolatstr;
11139                         /*n2->narg.backquote = NULL;*/
11140                         n1->nfor.args = n2;
11141                         /*
11142                          * Newline or semicolon here is optional (but note
11143                          * that the original Bourne shell only allowed NL).
11144                          */
11145                         if (lasttoken != TSEMI)
11146                                 tokpushback = 1;
11147                 }
11148                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11149                 if (readtoken() != TDO)
11150                         raise_error_unexpected_syntax(TDO);
11151                 n1->nfor.body = list(0);
11152                 t = TDONE;
11153                 break;
11154         case TCASE:
11155                 n1 = stzalloc(sizeof(struct ncase));
11156                 n1->type = NCASE;
11157                 if (readtoken() != TWORD)
11158                         raise_error_unexpected_syntax(TWORD);
11159                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11160                 n2->type = NARG;
11161                 /*n2->narg.next = NULL; - stzalloc did it */
11162                 n2->narg.text = wordtext;
11163                 n2->narg.backquote = backquotelist;
11164                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11165                 if (readtoken() != TIN)
11166                         raise_error_unexpected_syntax(TIN);
11167                 cpp = &n1->ncase.cases;
11168  next_case:
11169                 checkkwd = CHKNL | CHKKWD;
11170                 t = readtoken();
11171                 while (t != TESAC) {
11172                         if (lasttoken == TLP)
11173                                 readtoken();
11174                         *cpp = cp = stzalloc(sizeof(struct nclist));
11175                         cp->type = NCLIST;
11176                         app = &cp->nclist.pattern;
11177                         for (;;) {
11178                                 *app = ap = stzalloc(sizeof(struct narg));
11179                                 ap->type = NARG;
11180                                 /*ap->narg.next = NULL; - stzalloc did it */
11181                                 ap->narg.text = wordtext;
11182                                 ap->narg.backquote = backquotelist;
11183                                 if (readtoken() != TPIPE)
11184                                         break;
11185                                 app = &ap->narg.next;
11186                                 readtoken();
11187                         }
11188                         //ap->narg.next = NULL;
11189                         if (lasttoken != TRP)
11190                                 raise_error_unexpected_syntax(TRP);
11191                         cp->nclist.body = list(2);
11192
11193                         cpp = &cp->nclist.next;
11194
11195                         checkkwd = CHKNL | CHKKWD;
11196                         t = readtoken();
11197                         if (t != TESAC) {
11198                                 if (t != TENDCASE)
11199                                         raise_error_unexpected_syntax(TENDCASE);
11200                                 goto next_case;
11201                         }
11202                 }
11203                 *cpp = NULL;
11204                 goto redir;
11205         case TLP:
11206                 n1 = stzalloc(sizeof(struct nredir));
11207                 n1->type = NSUBSHELL;
11208                 n1->nredir.n = list(0);
11209                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11210                 t = TRP;
11211                 break;
11212         case TBEGIN:
11213                 n1 = list(0);
11214                 t = TEND;
11215                 break;
11216         IF_ASH_BASH_COMPAT(case TFUNCTION:)
11217         case TWORD:
11218         case TREDIR:
11219                 tokpushback = 1;
11220                 return simplecmd();
11221         }
11222
11223         if (readtoken() != t)
11224                 raise_error_unexpected_syntax(t);
11225
11226  redir:
11227         /* Now check for redirection which may follow command */
11228         checkkwd = CHKKWD | CHKALIAS;
11229         rpp = rpp2;
11230         while (readtoken() == TREDIR) {
11231                 *rpp = n2 = redirnode;
11232                 rpp = &n2->nfile.next;
11233                 parsefname();
11234         }
11235         tokpushback = 1;
11236         *rpp = NULL;
11237         if (redir) {
11238                 if (n1->type != NSUBSHELL) {
11239                         n2 = stzalloc(sizeof(struct nredir));
11240                         n2->type = NREDIR;
11241                         n2->nredir.n = n1;
11242                         n1 = n2;
11243                 }
11244                 n1->nredir.redirect = redir;
11245         }
11246         return n1;
11247 }
11248
11249 #if ENABLE_ASH_BASH_COMPAT
11250 static int
11251 decode_dollar_squote(void)
11252 {
11253         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11254         int c, cnt;
11255         char *p;
11256         char buf[4];
11257
11258         c = pgetc();
11259         p = strchr(C_escapes, c);
11260         if (p) {
11261                 buf[0] = c;
11262                 p = buf;
11263                 cnt = 3;
11264                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11265                         do {
11266                                 c = pgetc();
11267                                 *++p = c;
11268                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11269                         pungetc();
11270                 } else if (c == 'x') { /* \xHH */
11271                         do {
11272                                 c = pgetc();
11273                                 *++p = c;
11274                         } while (isxdigit(c) && --cnt);
11275                         pungetc();
11276                         if (cnt == 3) { /* \x but next char is "bad" */
11277                                 c = 'x';
11278                                 goto unrecognized;
11279                         }
11280                 } else { /* simple seq like \\ or \t */
11281                         p++;
11282                 }
11283                 *p = '\0';
11284                 p = buf;
11285                 c = bb_process_escape_sequence((void*)&p);
11286         } else { /* unrecognized "\z": print both chars unless ' or " */
11287                 if (c != '\'' && c != '"') {
11288  unrecognized:
11289                         c |= 0x100; /* "please encode \, then me" */
11290                 }
11291         }
11292         return c;
11293 }
11294 #endif
11295
11296 /*
11297  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11298  * is not NULL, read a here document.  In the latter case, eofmark is the
11299  * word which marks the end of the document and striptabs is true if
11300  * leading tabs should be stripped from the document.  The argument c
11301  * is the first character of the input token or document.
11302  *
11303  * Because C does not have internal subroutines, I have simulated them
11304  * using goto's to implement the subroutine linkage.  The following macros
11305  * will run code that appears at the end of readtoken1.
11306  */
11307 #define CHECKEND()      {goto checkend; checkend_return:;}
11308 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11309 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11310 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11311 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11312 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11313 static int
11314 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11315 {
11316         /* NB: syntax parameter fits into smallint */
11317         /* c parameter is an unsigned char or PEOF or PEOA */
11318         char *out;
11319         size_t len;
11320         char line[EOFMARKLEN + 1];
11321         struct nodelist *bqlist;
11322         smallint quotef;
11323         smallint dblquote;
11324         smallint oldstyle;
11325         smallint prevsyntax; /* syntax before arithmetic */
11326 #if ENABLE_ASH_EXPAND_PRMT
11327         smallint pssyntax;   /* we are expanding a prompt string */
11328 #endif
11329         int varnest;         /* levels of variables expansion */
11330         int arinest;         /* levels of arithmetic expansion */
11331         int parenlevel;      /* levels of parens in arithmetic */
11332         int dqvarnest;       /* levels of variables expansion within double quotes */
11333
11334         IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
11335
11336         startlinno = g_parsefile->linno;
11337         bqlist = NULL;
11338         quotef = 0;
11339         prevsyntax = 0;
11340 #if ENABLE_ASH_EXPAND_PRMT
11341         pssyntax = (syntax == PSSYNTAX);
11342         if (pssyntax)
11343                 syntax = DQSYNTAX;
11344 #endif
11345         dblquote = (syntax == DQSYNTAX);
11346         varnest = 0;
11347         arinest = 0;
11348         parenlevel = 0;
11349         dqvarnest = 0;
11350
11351         STARTSTACKSTR(out);
11352  loop:
11353         /* For each line, until end of word */
11354         CHECKEND();     /* set c to PEOF if at end of here document */
11355         for (;;) {      /* until end of line or end of word */
11356                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11357                 switch (SIT(c, syntax)) {
11358                 case CNL:       /* '\n' */
11359                         if (syntax == BASESYNTAX)
11360                                 goto endword;   /* exit outer loop */
11361                         USTPUTC(c, out);
11362                         nlprompt();
11363                         c = pgetc();
11364                         goto loop;              /* continue outer loop */
11365                 case CWORD:
11366                         USTPUTC(c, out);
11367                         break;
11368                 case CCTL:
11369 #if ENABLE_ASH_BASH_COMPAT
11370                         if (c == '\\' && bash_dollar_squote) {
11371                                 c = decode_dollar_squote();
11372                                 if (c == '\0') {
11373                                         /* skip $'\000', $'\x00' (like bash) */
11374                                         break;
11375                                 }
11376                                 if (c & 0x100) {
11377                                         /* Unknown escape. Encode as '\z' */
11378                                         c = (unsigned char)c;
11379                                         if (eofmark == NULL || dblquote)
11380                                                 USTPUTC(CTLESC, out);
11381                                         USTPUTC('\\', out);
11382                                 }
11383                         }
11384 #endif
11385                         if (eofmark == NULL || dblquote)
11386                                 USTPUTC(CTLESC, out);
11387                         USTPUTC(c, out);
11388                         break;
11389                 case CBACK:     /* backslash */
11390                         c = pgetc_without_PEOA();
11391                         if (c == PEOF) {
11392                                 USTPUTC(CTLESC, out);
11393                                 USTPUTC('\\', out);
11394                                 pungetc();
11395                         } else if (c == '\n') {
11396                                 nlprompt();
11397                         } else {
11398 #if ENABLE_ASH_EXPAND_PRMT
11399                                 if (c == '$' && pssyntax) {
11400                                         USTPUTC(CTLESC, out);
11401                                         USTPUTC('\\', out);
11402                                 }
11403 #endif
11404                                 /* Backslash is retained if we are in "str" and next char isn't special */
11405                                 if (dblquote
11406                                  && c != '\\'
11407                                  && c != '`'
11408                                  && c != '$'
11409                                  && (c != '"' || eofmark != NULL)
11410                                 ) {
11411                                         USTPUTC('\\', out);
11412                                 }
11413                                 USTPUTC(CTLESC, out);
11414                                 USTPUTC(c, out);
11415                                 quotef = 1;
11416                         }
11417                         break;
11418                 case CSQUOTE:
11419                         syntax = SQSYNTAX;
11420  quotemark:
11421                         if (eofmark == NULL) {
11422                                 USTPUTC(CTLQUOTEMARK, out);
11423                         }
11424                         break;
11425                 case CDQUOTE:
11426                         syntax = DQSYNTAX;
11427                         dblquote = 1;
11428                         goto quotemark;
11429                 case CENDQUOTE:
11430                         IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
11431                         if (eofmark != NULL && varnest == 0) {
11432                                 USTPUTC(c, out);
11433                         } else {
11434                                 if (dqvarnest == 0) {
11435                                         syntax = BASESYNTAX;
11436                                         dblquote = 0;
11437                                 }
11438                                 quotef = 1;
11439                                 goto quotemark;
11440                         }
11441                         break;
11442                 case CVAR:      /* '$' */
11443                         PARSESUB();             /* parse substitution */
11444                         break;
11445                 case CENDVAR:   /* '}' */
11446                         if (varnest > 0) {
11447                                 varnest--;
11448                                 if (dqvarnest > 0) {
11449                                         dqvarnest--;
11450                                 }
11451                                 c = CTLENDVAR;
11452                         }
11453                         USTPUTC(c, out);
11454                         break;
11455 #if ENABLE_SH_MATH_SUPPORT
11456                 case CLP:       /* '(' in arithmetic */
11457                         parenlevel++;
11458                         USTPUTC(c, out);
11459                         break;
11460                 case CRP:       /* ')' in arithmetic */
11461                         if (parenlevel > 0) {
11462                                 parenlevel--;
11463                         } else {
11464                                 if (pgetc_eatbnl() == ')') {
11465                                         c = CTLENDARI;
11466                                         if (--arinest == 0) {
11467                                                 syntax = prevsyntax;
11468                                         }
11469                                 } else {
11470                                         /*
11471                                          * unbalanced parens
11472                                          * (don't 2nd guess - no error)
11473                                          */
11474                                         pungetc();
11475                                 }
11476                         }
11477                         USTPUTC(c, out);
11478                         break;
11479 #endif
11480                 case CBQUOTE:   /* '`' */
11481                         PARSEBACKQOLD();
11482                         break;
11483                 case CENDFILE:
11484                         goto endword;           /* exit outer loop */
11485                 case CIGN:
11486                         break;
11487                 default:
11488                         if (varnest == 0) {
11489 #if ENABLE_ASH_BASH_COMPAT
11490                                 if (c == '&') {
11491 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11492                                         if (pgetc() == '>')
11493                                                 c = 0x100 + '>'; /* flag &> */
11494                                         pungetc();
11495                                 }
11496 #endif
11497                                 goto endword;   /* exit outer loop */
11498                         }
11499                         IF_ASH_ALIAS(if (c != PEOA))
11500                                 USTPUTC(c, out);
11501                 }
11502                 c = pgetc();
11503         } /* for (;;) */
11504  endword:
11505
11506 #if ENABLE_SH_MATH_SUPPORT
11507         if (syntax == ARISYNTAX)
11508                 raise_error_syntax("missing '))'");
11509 #endif
11510         if (syntax != BASESYNTAX && eofmark == NULL)
11511                 raise_error_syntax("unterminated quoted string");
11512         if (varnest != 0) {
11513                 startlinno = g_parsefile->linno;
11514                 /* { */
11515                 raise_error_syntax("missing '}'");
11516         }
11517         USTPUTC('\0', out);
11518         len = out - (char *)stackblock();
11519         out = stackblock();
11520         if (eofmark == NULL) {
11521                 if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>'))
11522                  && quotef == 0
11523                 ) {
11524                         if (isdigit_str9(out)) {
11525                                 PARSEREDIR(); /* passed as params: out, c */
11526                                 lasttoken = TREDIR;
11527                                 return lasttoken;
11528                         }
11529                         /* else: non-number X seen, interpret it
11530                          * as "NNNX>file" = "NNNX >file" */
11531                 }
11532                 pungetc();
11533         }
11534         quoteflag = quotef;
11535         backquotelist = bqlist;
11536         grabstackblock(len);
11537         wordtext = out;
11538         lasttoken = TWORD;
11539         return lasttoken;
11540 /* end of readtoken routine */
11541
11542 /*
11543  * Check to see whether we are at the end of the here document.  When this
11544  * is called, c is set to the first character of the next input line.  If
11545  * we are at the end of the here document, this routine sets the c to PEOF.
11546  */
11547 checkend: {
11548         if (eofmark) {
11549 #if ENABLE_ASH_ALIAS
11550                 if (c == PEOA)
11551                         c = pgetc_without_PEOA();
11552 #endif
11553                 if (striptabs) {
11554                         while (c == '\t') {
11555                                 c = pgetc_without_PEOA();
11556                         }
11557                 }
11558                 if (c == *eofmark) {
11559                         if (pfgets(line, sizeof(line)) != NULL) {
11560                                 char *p, *q;
11561                                 int cc;
11562
11563                                 p = line;
11564                                 for (q = eofmark + 1;; p++, q++) {
11565                                         cc = *p;
11566                                         if (cc == '\n')
11567                                                 cc = 0;
11568                                         if (!*q || cc != *q)
11569                                                 break;
11570                                 }
11571                                 if (cc == *q) {
11572                                         c = PEOF;
11573                                         nlnoprompt();
11574                                 } else {
11575                                         pushstring(line, NULL);
11576                                 }
11577                         }
11578                 }
11579         }
11580         goto checkend_return;
11581 }
11582
11583 /*
11584  * Parse a redirection operator.  The variable "out" points to a string
11585  * specifying the fd to be redirected.  The variable "c" contains the
11586  * first character of the redirection operator.
11587  */
11588 parseredir: {
11589         /* out is already checked to be a valid number or "" */
11590         int fd = (*out == '\0' ? -1 : atoi(out));
11591         union node *np;
11592
11593         np = stzalloc(sizeof(struct nfile));
11594         if (c == '>') {
11595                 np->nfile.fd = 1;
11596                 c = pgetc();
11597                 if (c == '>')
11598                         np->type = NAPPEND;
11599                 else if (c == '|')
11600                         np->type = NCLOBBER;
11601                 else if (c == '&')
11602                         np->type = NTOFD;
11603                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11604                 else {
11605                         np->type = NTO;
11606                         pungetc();
11607                 }
11608         }
11609 #if ENABLE_ASH_BASH_COMPAT
11610         else if (c == 0x100 + '>') { /* this flags &> redirection */
11611                 np->nfile.fd = 1;
11612                 pgetc(); /* this is '>', no need to check */
11613                 np->type = NTO2;
11614         }
11615 #endif
11616         else { /* c == '<' */
11617                 /*np->nfile.fd = 0; - stzalloc did it */
11618                 c = pgetc();
11619                 switch (c) {
11620                 case '<':
11621                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11622                                 np = stzalloc(sizeof(struct nhere));
11623                                 /*np->nfile.fd = 0; - stzalloc did it */
11624                         }
11625                         np->type = NHERE;
11626                         heredoc = stzalloc(sizeof(struct heredoc));
11627                         heredoc->here = np;
11628                         c = pgetc();
11629                         if (c == '-') {
11630                                 heredoc->striptabs = 1;
11631                         } else {
11632                                 /*heredoc->striptabs = 0; - stzalloc did it */
11633                                 pungetc();
11634                         }
11635                         break;
11636
11637                 case '&':
11638                         np->type = NFROMFD;
11639                         break;
11640
11641                 case '>':
11642                         np->type = NFROMTO;
11643                         break;
11644
11645                 default:
11646                         np->type = NFROM;
11647                         pungetc();
11648                         break;
11649                 }
11650         }
11651         if (fd >= 0)
11652                 np->nfile.fd = fd;
11653         redirnode = np;
11654         goto parseredir_return;
11655 }
11656
11657 /*
11658  * Parse a substitution.  At this point, we have read the dollar sign
11659  * and nothing else.
11660  */
11661
11662 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11663  * (assuming ascii char codes, as the original implementation did) */
11664 #define is_special(c) \
11665         (((unsigned)(c) - 33 < 32) \
11666                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11667 parsesub: {
11668         unsigned char subtype;
11669         int typeloc;
11670
11671         c = pgetc_eatbnl();
11672         if (c > 255 /* PEOA or PEOF */
11673          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11674         ) {
11675 #if ENABLE_ASH_BASH_COMPAT
11676                 if (syntax != DQSYNTAX && c == '\'')
11677                         bash_dollar_squote = 1;
11678                 else
11679 #endif
11680                         USTPUTC('$', out);
11681                 pungetc();
11682         } else if (c == '(') {
11683                 /* $(command) or $((arith)) */
11684                 if (pgetc_eatbnl() == '(') {
11685 #if ENABLE_SH_MATH_SUPPORT
11686                         PARSEARITH();
11687 #else
11688                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11689 #endif
11690                 } else {
11691                         pungetc();
11692                         PARSEBACKQNEW();
11693                 }
11694         } else {
11695                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11696                 USTPUTC(CTLVAR, out);
11697                 typeloc = out - (char *)stackblock();
11698                 STADJUST(1, out);
11699                 subtype = VSNORMAL;
11700                 if (c == '{') {
11701                         c = pgetc_eatbnl();
11702                         subtype = 0;
11703                 }
11704  varname:
11705                 if (is_name(c)) {
11706                         /* $[{[#]]NAME[}] */
11707                         do {
11708                                 STPUTC(c, out);
11709                                 c = pgetc_eatbnl();
11710                         } while (is_in_name(c));
11711                 } else if (isdigit(c)) {
11712                         /* $[{[#]]NUM[}] */
11713                         do {
11714                                 STPUTC(c, out);
11715                                 c = pgetc_eatbnl();
11716                         } while (isdigit(c));
11717                 } else if (is_special(c)) {
11718                         /* $[{[#]]<specialchar>[}] */
11719                         int cc = c;
11720
11721                         c = pgetc_eatbnl();
11722                         if (!subtype && cc == '#') {
11723                                 subtype = VSLENGTH;
11724                                 if (c == '_' || isalnum(c))
11725                                         goto varname;
11726                                 cc = c;
11727                                 c = pgetc_eatbnl();
11728                                 if (cc == '}' || c != '}') {
11729                                         pungetc();
11730                                         subtype = 0;
11731                                         c = cc;
11732                                         cc = '#';
11733                                 }
11734                         }
11735                         USTPUTC(cc, out);
11736                 } else {
11737                         goto badsub;
11738                 }
11739                 if (c != '}' && subtype == VSLENGTH) {
11740                         /* ${#VAR didn't end with } */
11741                         goto badsub;
11742                 }
11743
11744                 if (subtype == 0) {
11745                         static const char types[] ALIGN1 = "}-+?=";
11746                         /* ${VAR...} but not $VAR or ${#VAR} */
11747                         /* c == first char after VAR */
11748                         switch (c) {
11749                         case ':':
11750                                 c = pgetc_eatbnl();
11751 #if ENABLE_ASH_BASH_COMPAT
11752                                 /* This check is only needed to not misinterpret
11753                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11754                                  * constructs.
11755                                  */
11756                                 if (!strchr(types, c)) {
11757                                         subtype = VSSUBSTR;
11758                                         pungetc();
11759                                         break; /* "goto badsub" is bigger (!) */
11760                                 }
11761 #endif
11762                                 subtype = VSNUL;
11763                                 /*FALLTHROUGH*/
11764                         default: {
11765                                 const char *p = strchr(types, c);
11766                                 if (p == NULL)
11767                                         break;
11768                                 subtype |= p - types + VSNORMAL;
11769                                 break;
11770                         }
11771                         case '%':
11772                         case '#': {
11773                                 int cc = c;
11774                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11775                                 c = pgetc_eatbnl();
11776                                 if (c != cc)
11777                                         goto badsub;
11778                                 subtype++;
11779                                 break;
11780                         }
11781 #if ENABLE_ASH_BASH_COMPAT
11782                         case '/':
11783                                 /* ${v/[/]pattern/repl} */
11784 //TODO: encode pattern and repl separately.
11785 // Currently ${v/$var_with_slash/repl} is horribly broken
11786                                 subtype = VSREPLACE;
11787                                 c = pgetc_eatbnl();
11788                                 if (c != '/')
11789                                         goto badsub;
11790                                 subtype++; /* VSREPLACEALL */
11791                                 break;
11792 #endif
11793                         }
11794                 } else {
11795  badsub:
11796                         pungetc();
11797                 }
11798                 ((unsigned char *)stackblock())[typeloc] = subtype;
11799                 if (subtype != VSNORMAL) {
11800                         varnest++;
11801                         if (dblquote)
11802                                 dqvarnest++;
11803                 }
11804                 STPUTC('=', out);
11805         }
11806         goto parsesub_return;
11807 }
11808
11809 /*
11810  * Called to parse command substitutions.  Newstyle is set if the command
11811  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11812  * list of commands (passed by reference), and savelen is the number of
11813  * characters on the top of the stack which must be preserved.
11814  */
11815 parsebackq: {
11816         struct nodelist **nlpp;
11817         union node *n;
11818         char *str;
11819         size_t savelen;
11820         smallint saveprompt = 0;
11821
11822         str = NULL;
11823         savelen = out - (char *)stackblock();
11824         if (savelen > 0) {
11825                 /*
11826                  * FIXME: this can allocate very large block on stack and SEGV.
11827                  * Example:
11828                  * echo "..<100kbytes>..`true` $(true) `true` ..."
11829                  * allocates 100kb for every command subst. With about
11830                  * a hundred command substitutions stack overflows.
11831                  * With larger prepended string, SEGV happens sooner.
11832                  */
11833                 str = alloca(savelen);
11834                 memcpy(str, stackblock(), savelen);
11835         }
11836
11837         if (oldstyle) {
11838                 /* We must read until the closing backquote, giving special
11839                  * treatment to some slashes, and then push the string and
11840                  * reread it as input, interpreting it normally.
11841                  */
11842                 char *pout;
11843                 size_t psavelen;
11844                 char *pstr;
11845
11846                 STARTSTACKSTR(pout);
11847                 for (;;) {
11848                         int pc;
11849
11850                         setprompt_if(needprompt, 2);
11851                         pc = pgetc();
11852                         switch (pc) {
11853                         case '`':
11854                                 goto done;
11855
11856                         case '\\':
11857                                 pc = pgetc();
11858                                 if (pc == '\n') {
11859                                         nlprompt();
11860                                         /*
11861                                          * If eating a newline, avoid putting
11862                                          * the newline into the new character
11863                                          * stream (via the STPUTC after the
11864                                          * switch).
11865                                          */
11866                                         continue;
11867                                 }
11868                                 if (pc != '\\' && pc != '`' && pc != '$'
11869                                  && (!dblquote || pc != '"')
11870                                 ) {
11871                                         STPUTC('\\', pout);
11872                                 }
11873                                 if (pc <= 255 /* not PEOA or PEOF */) {
11874                                         break;
11875                                 }
11876                                 /* fall through */
11877
11878                         case PEOF:
11879                         IF_ASH_ALIAS(case PEOA:)
11880                                 startlinno = g_parsefile->linno;
11881                                 raise_error_syntax("EOF in backquote substitution");
11882
11883                         case '\n':
11884                                 nlnoprompt();
11885                                 break;
11886
11887                         default:
11888                                 break;
11889                         }
11890                         STPUTC(pc, pout);
11891                 }
11892  done:
11893                 STPUTC('\0', pout);
11894                 psavelen = pout - (char *)stackblock();
11895                 if (psavelen > 0) {
11896                         pstr = grabstackstr(pout);
11897                         setinputstring(pstr);
11898                 }
11899         }
11900         nlpp = &bqlist;
11901         while (*nlpp)
11902                 nlpp = &(*nlpp)->next;
11903         *nlpp = stzalloc(sizeof(**nlpp));
11904         /* (*nlpp)->next = NULL; - stzalloc did it */
11905
11906         if (oldstyle) {
11907                 saveprompt = doprompt;
11908                 doprompt = 0;
11909         }
11910
11911         n = list(2);
11912
11913         if (oldstyle)
11914                 doprompt = saveprompt;
11915         else if (readtoken() != TRP)
11916                 raise_error_unexpected_syntax(TRP);
11917
11918         (*nlpp)->n = n;
11919         if (oldstyle) {
11920                 /*
11921                  * Start reading from old file again, ignoring any pushed back
11922                  * tokens left from the backquote parsing
11923                  */
11924                 popfile();
11925                 tokpushback = 0;
11926         }
11927         while (stackblocksize() <= savelen)
11928                 growstackblock();
11929         STARTSTACKSTR(out);
11930         if (str) {
11931                 memcpy(out, str, savelen);
11932                 STADJUST(savelen, out);
11933         }
11934         USTPUTC(CTLBACKQ, out);
11935         if (oldstyle)
11936                 goto parsebackq_oldreturn;
11937         goto parsebackq_newreturn;
11938 }
11939
11940 #if ENABLE_SH_MATH_SUPPORT
11941 /*
11942  * Parse an arithmetic expansion (indicate start of one and set state)
11943  */
11944 parsearith: {
11945         if (++arinest == 1) {
11946                 prevsyntax = syntax;
11947                 syntax = ARISYNTAX;
11948         }
11949         USTPUTC(CTLARI, out);
11950         goto parsearith_return;
11951 }
11952 #endif
11953 } /* end of readtoken */
11954
11955 /*
11956  * Read the next input token.
11957  * If the token is a word, we set backquotelist to the list of cmds in
11958  *      backquotes.  We set quoteflag to true if any part of the word was
11959  *      quoted.
11960  * If the token is TREDIR, then we set redirnode to a structure containing
11961  *      the redirection.
11962  * In all cases, the variable startlinno is set to the number of the line
11963  *      on which the token starts.
11964  *
11965  * [Change comment:  here documents and internal procedures]
11966  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
11967  *  word parsing code into a separate routine.  In this case, readtoken
11968  *  doesn't need to have any internal procedures, but parseword does.
11969  *  We could also make parseoperator in essence the main routine, and
11970  *  have parseword (readtoken1?) handle both words and redirection.]
11971  */
11972 #define NEW_xxreadtoken
11973 #ifdef NEW_xxreadtoken
11974 /* singles must be first! */
11975 static const char xxreadtoken_chars[7] ALIGN1 = {
11976         '\n', '(', ')', /* singles */
11977         '&', '|', ';',  /* doubles */
11978         0
11979 };
11980
11981 #define xxreadtoken_singles 3
11982 #define xxreadtoken_doubles 3
11983
11984 static const char xxreadtoken_tokens[] ALIGN1 = {
11985         TNL, TLP, TRP,          /* only single occurrence allowed */
11986         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11987         TEOF,                   /* corresponds to trailing nul */
11988         TAND, TOR, TENDCASE     /* if double occurrence */
11989 };
11990
11991 static int
11992 xxreadtoken(void)
11993 {
11994         int c;
11995
11996         if (tokpushback) {
11997                 tokpushback = 0;
11998                 return lasttoken;
11999         }
12000         setprompt_if(needprompt, 2);
12001         startlinno = g_parsefile->linno;
12002         for (;;) {                      /* until token or start of word found */
12003                 c = pgetc();
12004                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12005                         continue;
12006
12007                 if (c == '#') {
12008                         while ((c = pgetc()) != '\n' && c != PEOF)
12009                                 continue;
12010                         pungetc();
12011                 } else if (c == '\\') {
12012                         if (pgetc() != '\n') {
12013                                 pungetc();
12014                                 break; /* return readtoken1(...) */
12015                         }
12016                         nlprompt();
12017                 } else {
12018                         const char *p;
12019
12020                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12021                         if (c != PEOF) {
12022                                 if (c == '\n') {
12023                                         nlnoprompt();
12024                                 }
12025
12026                                 p = strchr(xxreadtoken_chars, c);
12027                                 if (p == NULL)
12028                                         break; /* return readtoken1(...) */
12029
12030                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12031                                         int cc = pgetc();
12032                                         if (cc == c) {    /* double occurrence? */
12033                                                 p += xxreadtoken_doubles + 1;
12034                                         } else {
12035                                                 pungetc();
12036 #if ENABLE_ASH_BASH_COMPAT
12037                                                 if (c == '&' && cc == '>') /* &> */
12038                                                         break; /* return readtoken1(...) */
12039 #endif
12040                                         }
12041                                 }
12042                         }
12043                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12044                         return lasttoken;
12045                 }
12046         } /* for (;;) */
12047
12048         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12049 }
12050 #else /* old xxreadtoken */
12051 #define RETURN(token)   return lasttoken = token
12052 static int
12053 xxreadtoken(void)
12054 {
12055         int c;
12056
12057         if (tokpushback) {
12058                 tokpushback = 0;
12059                 return lasttoken;
12060         }
12061         setprompt_if(needprompt, 2);
12062         startlinno = g_parsefile->linno;
12063         for (;;) {      /* until token or start of word found */
12064                 c = pgetc();
12065                 switch (c) {
12066                 case ' ': case '\t':
12067                 IF_ASH_ALIAS(case PEOA:)
12068                         continue;
12069                 case '#':
12070                         while ((c = pgetc()) != '\n' && c != PEOF)
12071                                 continue;
12072                         pungetc();
12073                         continue;
12074                 case '\\':
12075                         if (pgetc() == '\n') {
12076                                 nlprompt();
12077                                 continue;
12078                         }
12079                         pungetc();
12080                         goto breakloop;
12081                 case '\n':
12082                         nlnoprompt();
12083                         RETURN(TNL);
12084                 case PEOF:
12085                         RETURN(TEOF);
12086                 case '&':
12087                         if (pgetc() == '&')
12088                                 RETURN(TAND);
12089                         pungetc();
12090                         RETURN(TBACKGND);
12091                 case '|':
12092                         if (pgetc() == '|')
12093                                 RETURN(TOR);
12094                         pungetc();
12095                         RETURN(TPIPE);
12096                 case ';':
12097                         if (pgetc() == ';')
12098                                 RETURN(TENDCASE);
12099                         pungetc();
12100                         RETURN(TSEMI);
12101                 case '(':
12102                         RETURN(TLP);
12103                 case ')':
12104                         RETURN(TRP);
12105                 default:
12106                         goto breakloop;
12107                 }
12108         }
12109  breakloop:
12110         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12111 #undef RETURN
12112 }
12113 #endif /* old xxreadtoken */
12114
12115 static int
12116 readtoken(void)
12117 {
12118         int t;
12119         int kwd = checkkwd;
12120 #if DEBUG
12121         smallint alreadyseen = tokpushback;
12122 #endif
12123
12124 #if ENABLE_ASH_ALIAS
12125  top:
12126 #endif
12127
12128         t = xxreadtoken();
12129
12130         /*
12131          * eat newlines
12132          */
12133         if (kwd & CHKNL) {
12134                 while (t == TNL) {
12135                         parseheredoc();
12136                         t = xxreadtoken();
12137                 }
12138         }
12139
12140         if (t != TWORD || quoteflag) {
12141                 goto out;
12142         }
12143
12144         /*
12145          * check for keywords
12146          */
12147         if (kwd & CHKKWD) {
12148                 const char *const *pp;
12149
12150                 pp = findkwd(wordtext);
12151                 if (pp) {
12152                         lasttoken = t = pp - tokname_array;
12153                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12154                         goto out;
12155                 }
12156         }
12157
12158         if (checkkwd & CHKALIAS) {
12159 #if ENABLE_ASH_ALIAS
12160                 struct alias *ap;
12161                 ap = lookupalias(wordtext, 1);
12162                 if (ap != NULL) {
12163                         if (*ap->val) {
12164                                 pushstring(ap->val, ap);
12165                         }
12166                         goto top;
12167                 }
12168 #endif
12169         }
12170  out:
12171         checkkwd = 0;
12172 #if DEBUG
12173         if (!alreadyseen)
12174                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12175         else
12176                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12177 #endif
12178         return t;
12179 }
12180
12181 static int
12182 peektoken(void)
12183 {
12184         int t;
12185
12186         t = readtoken();
12187         tokpushback = 1;
12188         return t;
12189 }
12190
12191 /*
12192  * Read and parse a command.  Returns NODE_EOF on end of file.
12193  * (NULL is a valid parse tree indicating a blank line.)
12194  */
12195 static union node *
12196 parsecmd(int interact)
12197 {
12198         tokpushback = 0;
12199         checkkwd = 0;
12200         heredoclist = 0;
12201         doprompt = interact;
12202         setprompt_if(doprompt, doprompt);
12203         needprompt = 0;
12204         return list(1);
12205 }
12206
12207 /*
12208  * Input any here documents.
12209  */
12210 static void
12211 parseheredoc(void)
12212 {
12213         struct heredoc *here;
12214         union node *n;
12215
12216         here = heredoclist;
12217         heredoclist = NULL;
12218
12219         while (here) {
12220                 setprompt_if(needprompt, 2);
12221                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12222                                 here->eofmark, here->striptabs);
12223                 n = stzalloc(sizeof(struct narg));
12224                 n->narg.type = NARG;
12225                 /*n->narg.next = NULL; - stzalloc did it */
12226                 n->narg.text = wordtext;
12227                 n->narg.backquote = backquotelist;
12228                 here->here->nhere.doc = n;
12229                 here = here->next;
12230         }
12231 }
12232
12233
12234 /*
12235  * called by editline -- any expansions to the prompt should be added here.
12236  */
12237 #if ENABLE_ASH_EXPAND_PRMT
12238 static const char *
12239 expandstr(const char *ps)
12240 {
12241         union node n;
12242         int saveprompt;
12243
12244         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12245          * and token processing _can_ alter it (delete NULs etc). */
12246         setinputstring((char *)ps);
12247
12248         saveprompt = doprompt;
12249         doprompt = 0;
12250         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12251         doprompt = saveprompt;
12252
12253         popfile();
12254
12255         n.narg.type = NARG;
12256         n.narg.next = NULL;
12257         n.narg.text = wordtext;
12258         n.narg.backquote = backquotelist;
12259
12260         expandarg(&n, NULL, EXP_QUOTED);
12261         return stackblock();
12262 }
12263 #endif
12264
12265 /*
12266  * Execute a command or commands contained in a string.
12267  */
12268 static int
12269 evalstring(char *s, int flags)
12270 {
12271         union node *n;
12272         struct stackmark smark;
12273         int status;
12274
12275         s = sstrdup(s);
12276         setinputstring(s);
12277         setstackmark(&smark);
12278
12279         status = 0;
12280         while ((n = parsecmd(0)) != NODE_EOF) {
12281                 int i;
12282
12283                 i = evaltree(n, flags);
12284                 if (n)
12285                         status = i;
12286                 popstackmark(&smark);
12287                 if (evalskip)
12288                         break;
12289         }
12290         popstackmark(&smark);
12291         popfile();
12292         stunalloc(s);
12293
12294         return status;
12295 }
12296
12297 /*
12298  * The eval command.
12299  */
12300 static int FAST_FUNC
12301 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12302 {
12303         char *p;
12304         char *concat;
12305
12306         if (argv[1]) {
12307                 p = argv[1];
12308                 argv += 2;
12309                 if (argv[0]) {
12310                         STARTSTACKSTR(concat);
12311                         for (;;) {
12312                                 concat = stack_putstr(p, concat);
12313                                 p = *argv++;
12314                                 if (p == NULL)
12315                                         break;
12316                                 STPUTC(' ', concat);
12317                         }
12318                         STPUTC('\0', concat);
12319                         p = grabstackstr(concat);
12320                 }
12321                 return evalstring(p, flags & EV_TESTED);
12322         }
12323         return 0;
12324 }
12325
12326 /*
12327  * Read and execute commands.
12328  * "Top" is nonzero for the top level command loop;
12329  * it turns on prompting if the shell is interactive.
12330  */
12331 static int
12332 cmdloop(int top)
12333 {
12334         union node *n;
12335         struct stackmark smark;
12336         int inter;
12337         int status = 0;
12338         int numeof = 0;
12339
12340         TRACE(("cmdloop(%d) called\n", top));
12341         for (;;) {
12342                 int skip;
12343
12344                 setstackmark(&smark);
12345 #if JOBS
12346                 if (doing_jobctl)
12347                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12348 #endif
12349                 inter = 0;
12350                 if (iflag && top) {
12351                         inter++;
12352                         chkmail();
12353                 }
12354                 n = parsecmd(inter);
12355 #if DEBUG
12356                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12357                         showtree(n);
12358 #endif
12359                 if (n == NODE_EOF) {
12360                         if (!top || numeof >= 50)
12361                                 break;
12362                         if (!stoppedjobs()) {
12363                                 if (!Iflag)
12364                                         break;
12365                                 out2str("\nUse \"exit\" to leave shell.\n");
12366                         }
12367                         numeof++;
12368                 } else if (nflag == 0) {
12369                         int i;
12370
12371                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12372                         job_warning >>= 1;
12373                         numeof = 0;
12374                         i = evaltree(n, 0);
12375                         if (n)
12376                                 status = i;
12377                 }
12378                 popstackmark(&smark);
12379                 skip = evalskip;
12380
12381                 if (skip) {
12382                         evalskip &= ~SKIPFUNC;
12383                         break;
12384                 }
12385         }
12386         return status;
12387 }
12388
12389 /*
12390  * Take commands from a file.  To be compatible we should do a path
12391  * search for the file, which is necessary to find sub-commands.
12392  */
12393 static char *
12394 find_dot_file(char *name)
12395 {
12396         char *fullname;
12397         const char *path = pathval();
12398         struct stat statb;
12399
12400         /* don't try this for absolute or relative paths */
12401         if (strchr(name, '/'))
12402                 return name;
12403
12404         /* IIRC standards do not say whether . is to be searched.
12405          * And it is even smaller this way, making it unconditional for now:
12406          */
12407         if (1) { /* ENABLE_ASH_BASH_COMPAT */
12408                 fullname = name;
12409                 goto try_cur_dir;
12410         }
12411
12412         while ((fullname = path_advance(&path, name)) != NULL) {
12413  try_cur_dir:
12414                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12415                         /*
12416                          * Don't bother freeing here, since it will
12417                          * be freed by the caller.
12418                          */
12419                         return fullname;
12420                 }
12421                 if (fullname != name)
12422                         stunalloc(fullname);
12423         }
12424
12425         /* not found in the PATH */
12426         ash_msg_and_raise_error("%s: not found", name);
12427         /* NOTREACHED */
12428 }
12429
12430 static int FAST_FUNC
12431 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12432 {
12433         /* "false; . empty_file; echo $?" should print 0, not 1: */
12434         int status = 0;
12435         char *fullname;
12436         char **argv;
12437         struct strlist *sp;
12438         volatile struct shparam saveparam;
12439
12440         for (sp = cmdenviron; sp; sp = sp->next)
12441                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12442
12443         nextopt(nullstr); /* handle possible "--" */
12444         argv = argptr;
12445
12446         if (!argv[0]) {
12447                 /* bash says: "bash: .: filename argument required" */
12448                 return 2; /* bash compat */
12449         }
12450
12451         /* This aborts if file isn't found, which is POSIXly correct.
12452          * bash returns exitcode 1 instead.
12453          */
12454         fullname = find_dot_file(argv[0]);
12455         argv++;
12456         if (argv[0]) { /* . FILE ARGS, ARGS exist */
12457                 int argc;
12458                 saveparam = shellparam;
12459                 shellparam.malloced = 0;
12460                 argc = 1;
12461                 while (argv[argc])
12462                         argc++;
12463                 shellparam.nparam = argc;
12464                 shellparam.p = argv;
12465         };
12466
12467         /* This aborts if file can't be opened, which is POSIXly correct.
12468          * bash returns exitcode 1 instead.
12469          */
12470         setinputfile(fullname, INPUT_PUSH_FILE);
12471         commandname = fullname;
12472         status = cmdloop(0);
12473         popfile();
12474
12475         if (argv[0]) {
12476                 freeparam(&shellparam);
12477                 shellparam = saveparam;
12478         };
12479
12480         return status;
12481 }
12482
12483 static int FAST_FUNC
12484 exitcmd(int argc UNUSED_PARAM, char **argv)
12485 {
12486         if (stoppedjobs())
12487                 return 0;
12488         if (argv[1])
12489                 exitstatus = number(argv[1]);
12490         raise_exception(EXEXIT);
12491         /* NOTREACHED */
12492 }
12493
12494 /*
12495  * Read a file containing shell functions.
12496  */
12497 static void
12498 readcmdfile(char *name)
12499 {
12500         setinputfile(name, INPUT_PUSH_FILE);
12501         cmdloop(0);
12502         popfile();
12503 }
12504
12505
12506 /* ============ find_command inplementation */
12507
12508 /*
12509  * Resolve a command name.  If you change this routine, you may have to
12510  * change the shellexec routine as well.
12511  */
12512 static void
12513 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12514 {
12515         struct tblentry *cmdp;
12516         int idx;
12517         int prev;
12518         char *fullname;
12519         struct stat statb;
12520         int e;
12521         int updatetbl;
12522         struct builtincmd *bcmd;
12523
12524         /* If name contains a slash, don't use PATH or hash table */
12525         if (strchr(name, '/') != NULL) {
12526                 entry->u.index = -1;
12527                 if (act & DO_ABS) {
12528                         while (stat(name, &statb) < 0) {
12529 #ifdef SYSV
12530                                 if (errno == EINTR)
12531                                         continue;
12532 #endif
12533                                 entry->cmdtype = CMDUNKNOWN;
12534                                 return;
12535                         }
12536                 }
12537                 entry->cmdtype = CMDNORMAL;
12538                 return;
12539         }
12540
12541 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12542
12543         updatetbl = (path == pathval());
12544         if (!updatetbl) {
12545                 act |= DO_ALTPATH;
12546                 if (strstr(path, "%builtin") != NULL)
12547                         act |= DO_ALTBLTIN;
12548         }
12549
12550         /* If name is in the table, check answer will be ok */
12551         cmdp = cmdlookup(name, 0);
12552         if (cmdp != NULL) {
12553                 int bit;
12554
12555                 switch (cmdp->cmdtype) {
12556                 default:
12557 #if DEBUG
12558                         abort();
12559 #endif
12560                 case CMDNORMAL:
12561                         bit = DO_ALTPATH;
12562                         break;
12563                 case CMDFUNCTION:
12564                         bit = DO_NOFUNC;
12565                         break;
12566                 case CMDBUILTIN:
12567                         bit = DO_ALTBLTIN;
12568                         break;
12569                 }
12570                 if (act & bit) {
12571                         updatetbl = 0;
12572                         cmdp = NULL;
12573                 } else if (cmdp->rehash == 0)
12574                         /* if not invalidated by cd, we're done */
12575                         goto success;
12576         }
12577
12578         /* If %builtin not in path, check for builtin next */
12579         bcmd = find_builtin(name);
12580         if (bcmd) {
12581                 if (IS_BUILTIN_REGULAR(bcmd))
12582                         goto builtin_success;
12583                 if (act & DO_ALTPATH) {
12584                         if (!(act & DO_ALTBLTIN))
12585                                 goto builtin_success;
12586                 } else if (builtinloc <= 0) {
12587                         goto builtin_success;
12588                 }
12589         }
12590
12591 #if ENABLE_FEATURE_SH_STANDALONE
12592         {
12593                 int applet_no = find_applet_by_name(name);
12594                 if (applet_no >= 0) {
12595                         entry->cmdtype = CMDNORMAL;
12596                         entry->u.index = -2 - applet_no;
12597                         return;
12598                 }
12599         }
12600 #endif
12601
12602         /* We have to search path. */
12603         prev = -1;              /* where to start */
12604         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12605                 if (cmdp->cmdtype == CMDBUILTIN)
12606                         prev = builtinloc;
12607                 else
12608                         prev = cmdp->param.index;
12609         }
12610
12611         e = ENOENT;
12612         idx = -1;
12613  loop:
12614         while ((fullname = path_advance(&path, name)) != NULL) {
12615                 stunalloc(fullname);
12616                 /* NB: code below will still use fullname
12617                  * despite it being "unallocated" */
12618                 idx++;
12619                 if (pathopt) {
12620                         if (prefix(pathopt, "builtin")) {
12621                                 if (bcmd)
12622                                         goto builtin_success;
12623                                 continue;
12624                         }
12625                         if ((act & DO_NOFUNC)
12626                          || !prefix(pathopt, "func")
12627                         ) {     /* ignore unimplemented options */
12628                                 continue;
12629                         }
12630                 }
12631                 /* if rehash, don't redo absolute path names */
12632                 if (fullname[0] == '/' && idx <= prev) {
12633                         if (idx < prev)
12634                                 continue;
12635                         TRACE(("searchexec \"%s\": no change\n", name));
12636                         goto success;
12637                 }
12638                 while (stat(fullname, &statb) < 0) {
12639 #ifdef SYSV
12640                         if (errno == EINTR)
12641                                 continue;
12642 #endif
12643                         if (errno != ENOENT && errno != ENOTDIR)
12644                                 e = errno;
12645                         goto loop;
12646                 }
12647                 e = EACCES;     /* if we fail, this will be the error */
12648                 if (!S_ISREG(statb.st_mode))
12649                         continue;
12650                 if (pathopt) {          /* this is a %func directory */
12651                         stalloc(strlen(fullname) + 1);
12652                         /* NB: stalloc will return space pointed by fullname
12653                          * (because we don't have any intervening allocations
12654                          * between stunalloc above and this stalloc) */
12655                         readcmdfile(fullname);
12656                         cmdp = cmdlookup(name, 0);
12657                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12658                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12659                         stunalloc(fullname);
12660                         goto success;
12661                 }
12662                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12663                 if (!updatetbl) {
12664                         entry->cmdtype = CMDNORMAL;
12665                         entry->u.index = idx;
12666                         return;
12667                 }
12668                 INT_OFF;
12669                 cmdp = cmdlookup(name, 1);
12670                 cmdp->cmdtype = CMDNORMAL;
12671                 cmdp->param.index = idx;
12672                 INT_ON;
12673                 goto success;
12674         }
12675
12676         /* We failed.  If there was an entry for this command, delete it */
12677         if (cmdp && updatetbl)
12678                 delete_cmd_entry();
12679         if (act & DO_ERR)
12680                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12681         entry->cmdtype = CMDUNKNOWN;
12682         return;
12683
12684  builtin_success:
12685         if (!updatetbl) {
12686                 entry->cmdtype = CMDBUILTIN;
12687                 entry->u.cmd = bcmd;
12688                 return;
12689         }
12690         INT_OFF;
12691         cmdp = cmdlookup(name, 1);
12692         cmdp->cmdtype = CMDBUILTIN;
12693         cmdp->param.cmd = bcmd;
12694         INT_ON;
12695  success:
12696         cmdp->rehash = 0;
12697         entry->cmdtype = cmdp->cmdtype;
12698         entry->u = cmdp->param;
12699 }
12700
12701
12702 /*
12703  * The trap builtin.
12704  */
12705 static int FAST_FUNC
12706 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12707 {
12708         char *action;
12709         char **ap;
12710         int signo, exitcode;
12711
12712         nextopt(nullstr);
12713         ap = argptr;
12714         if (!*ap) {
12715                 for (signo = 0; signo < NSIG; signo++) {
12716                         char *tr = trap_ptr[signo];
12717                         if (tr) {
12718                                 /* note: bash adds "SIG", but only if invoked
12719                                  * as "bash". If called as "sh", or if set -o posix,
12720                                  * then it prints short signal names.
12721                                  * We are printing short names: */
12722                                 out1fmt("trap -- %s %s\n",
12723                                                 single_quote(tr),
12724                                                 get_signame(signo));
12725                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12726                  * In this case, we will exit very soon, no need to free(). */
12727                                 /* if (trap_ptr != trap && tp[0]) */
12728                                 /*      free(tr); */
12729                         }
12730                 }
12731                 /*
12732                 if (trap_ptr != trap) {
12733                         free(trap_ptr);
12734                         trap_ptr = trap;
12735                 }
12736                 */
12737                 return 0;
12738         }
12739
12740         action = NULL;
12741         if (ap[1])
12742                 action = *ap++;
12743         exitcode = 0;
12744         while (*ap) {
12745                 signo = get_signum(*ap);
12746                 if (signo < 0) {
12747                         /* Mimic bash message exactly */
12748                         ash_msg("%s: invalid signal specification", *ap);
12749                         exitcode = 1;
12750                         goto next;
12751                 }
12752                 INT_OFF;
12753                 if (action) {
12754                         if (LONE_DASH(action))
12755                                 action = NULL;
12756                         else {
12757                                 if (action[0]) /* not NULL and not "" and not "-" */
12758                                         may_have_traps = 1;
12759                                 action = ckstrdup(action);
12760                         }
12761                 }
12762                 free(trap[signo]);
12763                 trap[signo] = action;
12764                 if (signo != 0)
12765                         setsignal(signo);
12766                 INT_ON;
12767  next:
12768                 ap++;
12769         }
12770         return exitcode;
12771 }
12772
12773
12774 /* ============ Builtins */
12775
12776 #if ENABLE_ASH_HELP
12777 static int FAST_FUNC
12778 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12779 {
12780         unsigned col;
12781         unsigned i;
12782
12783         out1fmt(
12784                 "Built-in commands:\n"
12785                 "------------------\n");
12786         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12787                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12788                                         builtintab[i].name + 1);
12789                 if (col > 60) {
12790                         out1fmt("\n");
12791                         col = 0;
12792                 }
12793         }
12794 # if ENABLE_FEATURE_SH_STANDALONE
12795         {
12796                 const char *a = applet_names;
12797                 while (*a) {
12798                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12799                         if (col > 60) {
12800                                 out1fmt("\n");
12801                                 col = 0;
12802                         }
12803                         while (*a++ != '\0')
12804                                 continue;
12805                 }
12806         }
12807 # endif
12808         newline_and_flush(stdout);
12809         return EXIT_SUCCESS;
12810 }
12811 #endif
12812
12813 #if MAX_HISTORY
12814 static int FAST_FUNC
12815 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12816 {
12817         show_history(line_input_state);
12818         return EXIT_SUCCESS;
12819 }
12820 #endif
12821
12822 /*
12823  * The export and readonly commands.
12824  */
12825 static int FAST_FUNC
12826 exportcmd(int argc UNUSED_PARAM, char **argv)
12827 {
12828         struct var *vp;
12829         char *name;
12830         const char *p;
12831         char **aptr;
12832         char opt;
12833         int flag;
12834         int flag_off;
12835
12836         /* "readonly" in bash accepts, but ignores -n.
12837          * We do the same: it saves a conditional in nextopt's param.
12838          */
12839         flag_off = 0;
12840         while ((opt = nextopt("np")) != '\0') {
12841                 if (opt == 'n')
12842                         flag_off = VEXPORT;
12843         }
12844         flag = VEXPORT;
12845         if (argv[0][0] == 'r') {
12846                 flag = VREADONLY;
12847                 flag_off = 0; /* readonly ignores -n */
12848         }
12849         flag_off = ~flag_off;
12850
12851         /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
12852         {
12853                 aptr = argptr;
12854                 name = *aptr;
12855                 if (name) {
12856                         do {
12857                                 p = strchr(name, '=');
12858                                 if (p != NULL) {
12859                                         p++;
12860                                 } else {
12861                                         vp = *findvar(hashvar(name), name);
12862                                         if (vp) {
12863                                                 vp->flags = ((vp->flags | flag) & flag_off);
12864                                                 continue;
12865                                         }
12866                                 }
12867                                 setvar(name, p, (flag & flag_off));
12868                         } while ((name = *++aptr) != NULL);
12869                         return 0;
12870                 }
12871         }
12872
12873         /* No arguments. Show the list of exported or readonly vars.
12874          * -n is ignored.
12875          */
12876         showvars(argv[0], flag, 0);
12877         return 0;
12878 }
12879
12880 /*
12881  * Delete a function if it exists.
12882  */
12883 static void
12884 unsetfunc(const char *name)
12885 {
12886         struct tblentry *cmdp;
12887
12888         cmdp = cmdlookup(name, 0);
12889         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
12890                 delete_cmd_entry();
12891 }
12892
12893 /*
12894  * The unset builtin command.  We unset the function before we unset the
12895  * variable to allow a function to be unset when there is a readonly variable
12896  * with the same name.
12897  */
12898 static int FAST_FUNC
12899 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12900 {
12901         char **ap;
12902         int i;
12903         int flag = 0;
12904         int ret = 0;
12905
12906         while ((i = nextopt("vf")) != 0) {
12907                 flag = i;
12908         }
12909
12910         for (ap = argptr; *ap; ap++) {
12911                 if (flag != 'f') {
12912                         i = unsetvar(*ap);
12913                         ret |= i;
12914                         if (!(i & 2))
12915                                 continue;
12916                 }
12917                 if (flag != 'v')
12918                         unsetfunc(*ap);
12919         }
12920         return ret & 1;
12921 }
12922
12923 static const unsigned char timescmd_str[] ALIGN1 = {
12924         ' ',  offsetof(struct tms, tms_utime),
12925         '\n', offsetof(struct tms, tms_stime),
12926         ' ',  offsetof(struct tms, tms_cutime),
12927         '\n', offsetof(struct tms, tms_cstime),
12928         0
12929 };
12930 static int FAST_FUNC
12931 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12932 {
12933         unsigned long clk_tck, s, t;
12934         const unsigned char *p;
12935         struct tms buf;
12936
12937         clk_tck = bb_clk_tck();
12938         times(&buf);
12939
12940         p = timescmd_str;
12941         do {
12942                 t = *(clock_t *)(((char *) &buf) + p[1]);
12943                 s = t / clk_tck;
12944                 t = t % clk_tck;
12945                 out1fmt("%lum%lu.%03lus%c",
12946                         s / 60, s % 60,
12947                         (t * 1000) / clk_tck,
12948                         p[0]);
12949                 p += 2;
12950         } while (*p);
12951
12952         return 0;
12953 }
12954
12955 #if ENABLE_SH_MATH_SUPPORT
12956 /*
12957  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
12958  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12959  *
12960  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12961  */
12962 static int FAST_FUNC
12963 letcmd(int argc UNUSED_PARAM, char **argv)
12964 {
12965         arith_t i;
12966
12967         argv++;
12968         if (!*argv)
12969                 ash_msg_and_raise_error("expression expected");
12970         do {
12971                 i = ash_arith(*argv);
12972         } while (*++argv);
12973
12974         return !i;
12975 }
12976 #endif
12977
12978 /*
12979  * The read builtin. Options:
12980  *      -r              Do not interpret '\' specially
12981  *      -s              Turn off echo (tty only)
12982  *      -n NCHARS       Read NCHARS max
12983  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
12984  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
12985  *      -u FD           Read from given FD instead of fd 0
12986  * This uses unbuffered input, which may be avoidable in some cases.
12987  * TODO: bash also has:
12988  *      -a ARRAY        Read into array[0],[1],etc
12989  *      -d DELIM        End on DELIM char, not newline
12990  *      -e              Use line editing (tty only)
12991  */
12992 static int FAST_FUNC
12993 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12994 {
12995         char *opt_n = NULL;
12996         char *opt_p = NULL;
12997         char *opt_t = NULL;
12998         char *opt_u = NULL;
12999         int read_flags = 0;
13000         const char *r;
13001         int i;
13002
13003         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13004                 switch (i) {
13005                 case 'p':
13006                         opt_p = optionarg;
13007                         break;
13008                 case 'n':
13009                         opt_n = optionarg;
13010                         break;
13011                 case 's':
13012                         read_flags |= BUILTIN_READ_SILENT;
13013                         break;
13014                 case 't':
13015                         opt_t = optionarg;
13016                         break;
13017                 case 'r':
13018                         read_flags |= BUILTIN_READ_RAW;
13019                         break;
13020                 case 'u':
13021                         opt_u = optionarg;
13022                         break;
13023                 default:
13024                         break;
13025                 }
13026         }
13027
13028         /* "read -s" needs to save/restore termios, can't allow ^C
13029          * to jump out of it.
13030          */
13031         INT_OFF;
13032         r = shell_builtin_read(setvar0,
13033                 argptr,
13034                 bltinlookup("IFS"), /* can be NULL */
13035                 read_flags,
13036                 opt_n,
13037                 opt_p,
13038                 opt_t,
13039                 opt_u
13040         );
13041         INT_ON;
13042
13043         if ((uintptr_t)r > 1)
13044                 ash_msg_and_raise_error(r);
13045
13046         return (uintptr_t)r;
13047 }
13048
13049 static int FAST_FUNC
13050 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13051 {
13052         static const char permuser[3] ALIGN1 = "ogu";
13053
13054         mode_t mask;
13055         int symbolic_mode = 0;
13056
13057         while (nextopt("S") != '\0') {
13058                 symbolic_mode = 1;
13059         }
13060
13061         INT_OFF;
13062         mask = umask(0);
13063         umask(mask);
13064         INT_ON;
13065
13066         if (*argptr == NULL) {
13067                 if (symbolic_mode) {
13068                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13069                         char *p = buf;
13070                         int i;
13071
13072                         i = 2;
13073                         for (;;) {
13074                                 *p++ = ',';
13075                                 *p++ = permuser[i];
13076                                 *p++ = '=';
13077                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13078                                 if (!(mask & 0400)) *p++ = 'r';
13079                                 if (!(mask & 0200)) *p++ = 'w';
13080                                 if (!(mask & 0100)) *p++ = 'x';
13081                                 mask <<= 3;
13082                                 if (--i < 0)
13083                                         break;
13084                         }
13085                         *p = '\0';
13086                         puts(buf + 1);
13087                 } else {
13088                         out1fmt("%04o\n", mask);
13089                 }
13090         } else {
13091                 char *modestr = *argptr;
13092                 /* numeric umasks are taken as-is */
13093                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13094                 if (!isdigit(modestr[0]))
13095                         mask ^= 0777;
13096                 mask = bb_parse_mode(modestr, mask);
13097                 if ((unsigned)mask > 0777) {
13098                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13099                 }
13100                 if (!isdigit(modestr[0]))
13101                         mask ^= 0777;
13102                 umask(mask);
13103         }
13104         return 0;
13105 }
13106
13107 static int FAST_FUNC
13108 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13109 {
13110         return shell_builtin_ulimit(argv);
13111 }
13112
13113 /* ============ main() and helpers */
13114
13115 /*
13116  * Called to exit the shell.
13117  */
13118 static void
13119 exitshell(void)
13120 {
13121         struct jmploc loc;
13122         char *p;
13123         int status;
13124
13125 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13126         save_history(line_input_state);
13127 #endif
13128         status = exitstatus;
13129         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13130         if (setjmp(loc.loc)) {
13131                 if (exception_type == EXEXIT)
13132                         status = exitstatus;
13133                 goto out;
13134         }
13135         exception_handler = &loc;
13136         p = trap[0];
13137         if (p) {
13138                 trap[0] = NULL;
13139                 evalskip = 0;
13140                 evalstring(p, 0);
13141                 /*free(p); - we'll exit soon */
13142         }
13143  out:
13144         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13145          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13146          */
13147         setjobctl(0);
13148         flush_stdout_stderr();
13149         _exit(status);
13150         /* NOTREACHED */
13151 }
13152
13153 static void
13154 init(void)
13155 {
13156         /* we will never free this */
13157         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13158
13159         signal(SIGCHLD, SIG_DFL);
13160         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13161          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13162          */
13163         signal(SIGHUP, SIG_DFL);
13164
13165         {
13166                 char **envp;
13167                 const char *p;
13168                 struct stat st1, st2;
13169
13170                 initvar();
13171                 for (envp = environ; envp && *envp; envp++) {
13172                         p = endofname(*envp);
13173                         if (p != *envp && *p == '=') {
13174                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13175                         }
13176                 }
13177
13178                 setvareq((char*)defoptindvar, VTEXTFIXED);
13179
13180                 setvar0("PPID", utoa(getppid()));
13181 #if ENABLE_ASH_BASH_COMPAT
13182                 p = lookupvar("SHLVL");
13183                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13184                 if (!lookupvar("HOSTNAME")) {
13185                         struct utsname uts;
13186                         uname(&uts);
13187                         setvar0("HOSTNAME", uts.nodename);
13188                 }
13189 #endif
13190                 p = lookupvar("PWD");
13191                 if (p) {
13192                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13193                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13194                         ) {
13195                                 p = NULL;
13196                         }
13197                 }
13198                 setpwd(p, 0);
13199         }
13200 }
13201
13202
13203 //usage:#define ash_trivial_usage
13204 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13205 //usage:#define ash_full_usage "\n\n"
13206 //usage:        "Unix shell interpreter"
13207
13208 //usage:#if ENABLE_FEATURE_SH_IS_ASH
13209 //usage:# define sh_trivial_usage ash_trivial_usage
13210 //usage:# define sh_full_usage    ash_full_usage
13211 //usage:#endif
13212 //usage:#if ENABLE_FEATURE_BASH_IS_ASH
13213 //usage:# define bash_trivial_usage ash_trivial_usage
13214 //usage:# define bash_full_usage    ash_full_usage
13215 //usage:#endif
13216
13217 /*
13218  * Process the shell command line arguments.
13219  */
13220 static void
13221 procargs(char **argv)
13222 {
13223         int i;
13224         const char *xminusc;
13225         char **xargv;
13226
13227         xargv = argv;
13228         arg0 = xargv[0];
13229         /* if (xargv[0]) - mmm, this is always true! */
13230                 xargv++;
13231         for (i = 0; i < NOPTS; i++)
13232                 optlist[i] = 2;
13233         argptr = xargv;
13234         if (options(/*cmdline:*/ 1)) {
13235                 /* it already printed err message */
13236                 raise_exception(EXERROR);
13237         }
13238         xargv = argptr;
13239         xminusc = minusc;
13240         if (*xargv == NULL) {
13241                 if (xminusc)
13242                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13243                 sflag = 1;
13244         }
13245         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13246                 iflag = 1;
13247         if (mflag == 2)
13248                 mflag = iflag;
13249         for (i = 0; i < NOPTS; i++)
13250                 if (optlist[i] == 2)
13251                         optlist[i] = 0;
13252 #if DEBUG == 2
13253         debug = 1;
13254 #endif
13255         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13256         if (xminusc) {
13257                 minusc = *xargv++;
13258                 if (*xargv)
13259                         goto setarg0;
13260         } else if (!sflag) {
13261                 setinputfile(*xargv, 0);
13262  setarg0:
13263                 arg0 = *xargv++;
13264                 commandname = arg0;
13265         }
13266
13267         shellparam.p = xargv;
13268 #if ENABLE_ASH_GETOPTS
13269         shellparam.optind = 1;
13270         shellparam.optoff = -1;
13271 #endif
13272         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13273         while (*xargv) {
13274                 shellparam.nparam++;
13275                 xargv++;
13276         }
13277         optschanged();
13278 }
13279
13280 /*
13281  * Read /etc/profile, ~/.profile, $ENV.
13282  */
13283 static void
13284 read_profile(const char *name)
13285 {
13286         name = expandstr(name);
13287         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13288                 return;
13289         cmdloop(0);
13290         popfile();
13291 }
13292
13293 /*
13294  * This routine is called when an error or an interrupt occurs in an
13295  * interactive shell and control is returned to the main command loop.
13296  */
13297 static void
13298 reset(void)
13299 {
13300         /* from eval.c: */
13301         evalskip = 0;
13302         loopnest = 0;
13303         /* from input.c: */
13304         g_parsefile->left_in_buffer = 0;
13305         g_parsefile->left_in_line = 0;      /* clear input buffer */
13306         popallfiles();
13307         /* from parser.c: */
13308         tokpushback = 0;
13309         checkkwd = 0;
13310         /* from redir.c: */
13311         while (redirlist)
13312                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13313 }
13314
13315 #if PROFILE
13316 static short profile_buf[16384];
13317 extern int etext();
13318 #endif
13319
13320 /*
13321  * Main routine.  We initialize things, parse the arguments, execute
13322  * profiles if we're a login shell, and then call cmdloop to execute
13323  * commands.  The setjmp call sets up the location to jump to when an
13324  * exception occurs.  When an exception occurs the variable "state"
13325  * is used to figure out how far we had gotten.
13326  */
13327 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13328 int ash_main(int argc UNUSED_PARAM, char **argv)
13329 {
13330         volatile smallint state;
13331         struct jmploc jmploc;
13332         struct stackmark smark;
13333
13334         /* Initialize global data */
13335         INIT_G_misc();
13336         INIT_G_memstack();
13337         INIT_G_var();
13338 #if ENABLE_ASH_ALIAS
13339         INIT_G_alias();
13340 #endif
13341         INIT_G_cmdtable();
13342
13343 #if PROFILE
13344         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13345 #endif
13346
13347 #if ENABLE_FEATURE_EDITING
13348         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13349 #endif
13350         state = 0;
13351         if (setjmp(jmploc.loc)) {
13352                 smallint e;
13353                 smallint s;
13354
13355                 reset();
13356
13357                 e = exception_type;
13358                 s = state;
13359                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13360                         exitshell();
13361                 }
13362                 if (e == EXINT) {
13363                         newline_and_flush(stderr);
13364                 }
13365
13366                 popstackmark(&smark);
13367                 FORCE_INT_ON; /* enable interrupts */
13368                 if (s == 1)
13369                         goto state1;
13370                 if (s == 2)
13371                         goto state2;
13372                 if (s == 3)
13373                         goto state3;
13374                 goto state4;
13375         }
13376         exception_handler = &jmploc;
13377 #if DEBUG
13378         opentrace();
13379         TRACE(("Shell args: "));
13380         trace_puts_args(argv);
13381 #endif
13382         rootpid = getpid();
13383
13384         init();
13385         setstackmark(&smark);
13386         procargs(argv);
13387
13388         if (argv[0] && argv[0][0] == '-')
13389                 isloginsh = 1;
13390         if (isloginsh) {
13391                 const char *hp;
13392
13393                 state = 1;
13394                 read_profile("/etc/profile");
13395  state1:
13396                 state = 2;
13397                 hp = lookupvar("HOME");
13398                 if (hp)
13399                         read_profile("$HOME/.profile");
13400         }
13401  state2:
13402         state = 3;
13403         if (
13404 #ifndef linux
13405          getuid() == geteuid() && getgid() == getegid() &&
13406 #endif
13407          iflag
13408         ) {
13409                 const char *shinit = lookupvar("ENV");
13410                 if (shinit != NULL && *shinit != '\0')
13411                         read_profile(shinit);
13412         }
13413         popstackmark(&smark);
13414  state3:
13415         state = 4;
13416         if (minusc) {
13417                 /* evalstring pushes parsefile stack.
13418                  * Ensure we don't falsely claim that 0 (stdin)
13419                  * is one of stacked source fds.
13420                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13421                 // if (!sflag) g_parsefile->pf_fd = -1;
13422                 // ^^ not necessary since now we special-case fd 0
13423                 // in is_hidden_fd() to not be considered "hidden fd"
13424                 evalstring(minusc, 0);
13425         }
13426
13427         if (sflag || minusc == NULL) {
13428 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13429                 if (iflag) {
13430                         const char *hp = lookupvar("HISTFILE");
13431                         if (!hp) {
13432                                 hp = lookupvar("HOME");
13433                                 if (hp) {
13434                                         hp = concat_path_file(hp, ".ash_history");
13435                                         setvar0("HISTFILE", hp);
13436                                         free((char*)hp);
13437                                         hp = lookupvar("HISTFILE");
13438                                 }
13439                         }
13440                         if (hp)
13441                                 line_input_state->hist_file = hp;
13442 # if ENABLE_FEATURE_SH_HISTFILESIZE
13443                         hp = lookupvar("HISTFILESIZE");
13444                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13445 # endif
13446                 }
13447 #endif
13448  state4: /* XXX ??? - why isn't this before the "if" statement */
13449                 cmdloop(1);
13450         }
13451 #if PROFILE
13452         monitor(0);
13453 #endif
13454 #ifdef GPROF
13455         {
13456                 extern void _mcleanup(void);
13457                 _mcleanup();
13458         }
13459 #endif
13460         TRACE(("End of main reached\n"));
13461         exitshell();
13462         /* NOTREACHED */
13463 }
13464
13465
13466 /*-
13467  * Copyright (c) 1989, 1991, 1993, 1994
13468  *      The Regents of the University of California.  All rights reserved.
13469  *
13470  * This code is derived from software contributed to Berkeley by
13471  * Kenneth Almquist.
13472  *
13473  * Redistribution and use in source and binary forms, with or without
13474  * modification, are permitted provided that the following conditions
13475  * are met:
13476  * 1. Redistributions of source code must retain the above copyright
13477  *    notice, this list of conditions and the following disclaimer.
13478  * 2. Redistributions in binary form must reproduce the above copyright
13479  *    notice, this list of conditions and the following disclaimer in the
13480  *    documentation and/or other materials provided with the distribution.
13481  * 3. Neither the name of the University nor the names of its contributors
13482  *    may be used to endorse or promote products derived from this software
13483  *    without specific prior written permission.
13484  *
13485  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13486  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13487  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13488  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13489  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13490  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13491  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13492  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13493  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13494  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13495  * SUCH DAMAGE.
13496  */