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