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