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