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