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