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