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