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