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