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