ash: fix execution of shell scripts without shebang
[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 "busybox.h" /* for applet_names */
40 #include <paths.h>
41 #include <setjmp.h>
42 #include <fnmatch.h>
43 #include <sys/times.h>
44
45 #include "shell_common.h"
46 #if ENABLE_SH_MATH_SUPPORT
47 # include "math.h"
48 #endif
49 #if ENABLE_ASH_RANDOM_SUPPORT
50 # include "random.h"
51 #else
52 # define CLEAR_RANDOM_T(rnd) ((void)0)
53 #endif
54
55 #include "NUM_APPLETS.h"
56 #if NUM_APPLETS == 1
57 /* STANDALONE does not make sense, and won't compile */
58 # undef CONFIG_FEATURE_SH_STANDALONE
59 # undef ENABLE_FEATURE_SH_STANDALONE
60 # undef IF_FEATURE_SH_STANDALONE
61 # undef IF_NOT_FEATURE_SH_STANDALONE
62 # define ENABLE_FEATURE_SH_STANDALONE 0
63 # define IF_FEATURE_SH_STANDALONE(...)
64 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
65 #endif
66
67 #ifndef PIPE_BUF
68 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
69 #endif
70
71 #if !BB_MMU
72 # error "Do not even bother, ash will not run on NOMMU machine"
73 #endif
74
75 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
76 //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
77 //applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash))
78
79 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
80 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
81
82 //config:config ASH
83 //config:       bool "ash"
84 //config:       default y
85 //config:       depends on !NOMMU
86 //config:       help
87 //config:         Tha 'ash' shell adds about 60k in the default configuration and is
88 //config:         the most complete and most pedantically correct shell included with
89 //config:         busybox. This shell is actually a derivative of the Debian 'dash'
90 //config:         shell (by Herbert Xu), which was created by porting the 'ash' shell
91 //config:         (written by Kenneth Almquist) from NetBSD.
92 //config:
93 //config:config ASH_BASH_COMPAT
94 //config:       bool "bash-compatible extensions"
95 //config:       default y
96 //config:       depends on ASH
97 //config:       help
98 //config:         Enable bash-compatible extensions.
99 //config:
100 //config:config ASH_IDLE_TIMEOUT
101 //config:       bool "Idle timeout variable"
102 //config:       default n
103 //config:       depends on ASH
104 //config:       help
105 //config:         Enables bash-like auto-logout after $TMOUT seconds of idle time.
106 //config:
107 //config:config ASH_JOB_CONTROL
108 //config:       bool "Job control"
109 //config:       default y
110 //config:       depends on ASH
111 //config:       help
112 //config:         Enable job control in the ash shell.
113 //config:
114 //config:config ASH_ALIAS
115 //config:       bool "Alias support"
116 //config:       default y
117 //config:       depends on ASH
118 //config:       help
119 //config:         Enable alias support in the ash shell.
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "Builtin getopt to parse positional parameters"
123 //config:       default y
124 //config:       depends on ASH
125 //config:       help
126 //config:         Enable support for getopts builtin in ash.
127 //config:
128 //config:config ASH_BUILTIN_ECHO
129 //config:       bool "Builtin version of 'echo'"
130 //config:       default y
131 //config:       depends on ASH
132 //config:       help
133 //config:         Enable support for echo builtin in ash.
134 //config:
135 //config:config ASH_BUILTIN_PRINTF
136 //config:       bool "Builtin version of 'printf'"
137 //config:       default y
138 //config:       depends on ASH
139 //config:       help
140 //config:         Enable support for printf builtin in ash.
141 //config:
142 //config:config ASH_BUILTIN_TEST
143 //config:       bool "Builtin version of 'test'"
144 //config:       default y
145 //config:       depends on ASH
146 //config:       help
147 //config:         Enable support for test builtin in ash.
148 //config:
149 //config:config ASH_CMDCMD
150 //config:       bool "'command' command to override shell builtins"
151 //config:       default y
152 //config:       depends on ASH
153 //config:       help
154 //config:         Enable support for the ash 'command' builtin, which allows
155 //config:         you to run the specified command with the specified arguments,
156 //config:         even when there is an ash builtin command with the same name.
157 //config:
158 //config:config ASH_MAIL
159 //config:       bool "Check for new mail on interactive shells"
160 //config:       default n
161 //config:       depends on ASH
162 //config:       help
163 //config:         Enable "check for new mail" function in the ash shell.
164 //config:
165 //config:config ASH_OPTIMIZE_FOR_SIZE
166 //config:       bool "Optimize for size instead of speed"
167 //config:       default y
168 //config:       depends on ASH
169 //config:       help
170 //config:         Compile ash for reduced size at the price of speed.
171 //config:
172 //config:config ASH_RANDOM_SUPPORT
173 //config:       bool "Pseudorandom generator and $RANDOM variable"
174 //config:       default y
175 //config:       depends on ASH
176 //config:       help
177 //config:         Enable pseudorandom generator and dynamic variable "$RANDOM".
178 //config:         Each read of "$RANDOM" will generate a new pseudorandom value.
179 //config:         You can reset the generator by using a specified start value.
180 //config:         After "unset RANDOM" the generator will switch off and this
181 //config:         variable will no longer have special treatment.
182 //config:
183 //config:config ASH_EXPAND_PRMT
184 //config:       bool "Expand prompt string"
185 //config:       default y
186 //config:       depends on ASH
187 //config:       help
188 //config:         "PS#" may contain volatile content, such as backquote commands.
189 //config:         This option recreates the prompt string from the environment
190 //config:         variable each time it is displayed.
191 //config:
192
193 //usage:#define ash_trivial_usage NOUSAGE_STR
194 //usage:#define ash_full_usage ""
195 //usage:#define sh_trivial_usage NOUSAGE_STR
196 //usage:#define sh_full_usage ""
197 //usage:#define bash_trivial_usage NOUSAGE_STR
198 //usage:#define bash_full_usage ""
199
200
201 /* ============ Hash table sizes. Configurable. */
202
203 #define VTABSIZE 39
204 #define ATABSIZE 39
205 #define CMDTABLESIZE 31         /* should be prime */
206
207
208 /* ============ Shell options */
209
210 static const char *const optletters_optnames[] = {
211         "e"   "errexit",
212         "f"   "noglob",
213         "I"   "ignoreeof",
214         "i"   "interactive",
215         "m"   "monitor",
216         "n"   "noexec",
217         "s"   "stdin",
218         "x"   "xtrace",
219         "v"   "verbose",
220         "C"   "noclobber",
221         "a"   "allexport",
222         "b"   "notify",
223         "u"   "nounset",
224         "\0"  "vi"
225 #if ENABLE_ASH_BASH_COMPAT
226         ,"\0"  "pipefail"
227 #endif
228 #if DEBUG
229         ,"\0"  "nolog"
230         ,"\0"  "debug"
231 #endif
232 };
233
234 #define optletters(n)  optletters_optnames[n][0]
235 #define optnames(n)   (optletters_optnames[n] + 1)
236
237 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
238
239
240 /* ============ Misc data */
241
242 #define msg_illnum "Illegal number: %s"
243
244 /*
245  * We enclose jmp_buf in a structure so that we can declare pointers to
246  * jump locations.  The global variable handler contains the location to
247  * jump to when an exception occurs, and the global variable exception_type
248  * contains a code identifying the exception.  To implement nested
249  * exception handlers, the user should save the value of handler on entry
250  * to an inner scope, set handler to point to a jmploc structure for the
251  * inner scope, and restore handler on exit from the scope.
252  */
253 struct jmploc {
254         jmp_buf loc;
255 };
256
257 struct globals_misc {
258         /* pid of main shell */
259         int rootpid;
260         /* shell level: 0 for the main shell, 1 for its children, and so on */
261         int shlvl;
262 #define rootshell (!shlvl)
263         char *minusc;  /* argument to -c option */
264
265         char *curdir; // = nullstr;     /* current working directory */
266         char *physdir; // = nullstr;    /* physical working directory */
267
268         char *arg0; /* value of $0 */
269
270         struct jmploc *exception_handler;
271
272         volatile int suppress_int; /* counter */
273         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
274         /* last pending signal */
275         volatile /*sig_atomic_t*/ smallint pending_sig;
276         smallint exception_type; /* kind of exception (0..5) */
277         /* exceptions */
278 #define EXINT 0         /* SIGINT received */
279 #define EXERROR 1       /* a generic error */
280 #define EXSHELLPROC 2   /* execute a shell procedure */
281 #define EXEXEC 3        /* command execution failed */
282 #define EXEXIT 4        /* exit the shell */
283 #define EXSIG 5         /* trapped signal in wait(1) */
284
285         smallint isloginsh;
286         char nullstr[1];        /* zero length string */
287
288         char optlist[NOPTS];
289 #define eflag optlist[0]
290 #define fflag optlist[1]
291 #define Iflag optlist[2]
292 #define iflag optlist[3]
293 #define mflag optlist[4]
294 #define nflag optlist[5]
295 #define sflag optlist[6]
296 #define xflag optlist[7]
297 #define vflag optlist[8]
298 #define Cflag optlist[9]
299 #define aflag optlist[10]
300 #define bflag optlist[11]
301 #define uflag optlist[12]
302 #define viflag optlist[13]
303 #if ENABLE_ASH_BASH_COMPAT
304 # define pipefail optlist[14]
305 #else
306 # define pipefail 0
307 #endif
308 #if DEBUG
309 # define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT]
310 # define debug optlist[15 + ENABLE_ASH_BASH_COMPAT]
311 #endif
312
313         /* trap handler commands */
314         /*
315          * Sigmode records the current value of the signal handlers for the various
316          * modes.  A value of zero means that the current handler is not known.
317          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
318          */
319         char sigmode[NSIG - 1];
320 #define S_DFL      1            /* default signal handling (SIG_DFL) */
321 #define S_CATCH    2            /* signal is caught */
322 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
323 #define S_HARD_IGN 4            /* signal is ignored permenantly */
324
325         /* indicates specified signal received */
326         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
327         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
328         char *trap[NSIG];
329         char **trap_ptr;        /* used only by "trap hack" */
330
331         /* Rarely referenced stuff */
332 #if ENABLE_ASH_RANDOM_SUPPORT
333         random_t random_gen;
334 #endif
335         pid_t backgndpid;        /* pid of last background process */
336         smallint job_warning;    /* user was warned about stopped jobs (can be 2, 1 or 0). */
337 };
338 extern struct globals_misc *const ash_ptr_to_globals_misc;
339 #define G_misc (*ash_ptr_to_globals_misc)
340 #define rootpid     (G_misc.rootpid    )
341 #define shlvl       (G_misc.shlvl      )
342 #define minusc      (G_misc.minusc     )
343 #define curdir      (G_misc.curdir     )
344 #define physdir     (G_misc.physdir    )
345 #define arg0        (G_misc.arg0       )
346 #define exception_handler (G_misc.exception_handler)
347 #define exception_type    (G_misc.exception_type   )
348 #define suppress_int      (G_misc.suppress_int     )
349 #define pending_int       (G_misc.pending_int      )
350 #define pending_sig       (G_misc.pending_sig      )
351 #define isloginsh   (G_misc.isloginsh  )
352 #define nullstr     (G_misc.nullstr    )
353 #define optlist     (G_misc.optlist    )
354 #define sigmode     (G_misc.sigmode    )
355 #define gotsig      (G_misc.gotsig     )
356 #define may_have_traps    (G_misc.may_have_traps   )
357 #define trap        (G_misc.trap       )
358 #define trap_ptr    (G_misc.trap_ptr   )
359 #define random_gen  (G_misc.random_gen )
360 #define backgndpid  (G_misc.backgndpid )
361 #define job_warning (G_misc.job_warning)
362 #define INIT_G_misc() do { \
363         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
364         barrier(); \
365         curdir = nullstr; \
366         physdir = nullstr; \
367         trap_ptr = trap; \
368 } while (0)
369
370
371 /* ============ DEBUG */
372 #if DEBUG
373 static void trace_printf(const char *fmt, ...);
374 static void trace_vprintf(const char *fmt, va_list va);
375 # define TRACE(param)    trace_printf param
376 # define TRACEV(param)   trace_vprintf param
377 # define close(fd) do { \
378         int dfd = (fd); \
379         if (close(dfd) < 0) \
380                 bb_error_msg("bug on %d: closing %d(0x%x)", \
381                         __LINE__, dfd, dfd); \
382 } while (0)
383 #else
384 # define TRACE(param)
385 # define TRACEV(param)
386 #endif
387
388
389 /* ============ Utility functions */
390 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
391
392 static int isdigit_str9(const char *str)
393 {
394         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
395         while (--maxlen && isdigit(*str))
396                 str++;
397         return (*str == '\0');
398 }
399
400 static const char *var_end(const char *var)
401 {
402         while (*var)
403                 if (*var++ == '=')
404                         break;
405         return var;
406 }
407
408
409 /* ============ Interrupts / exceptions */
410
411 static void exitshell(void) NORETURN;
412
413 /*
414  * These macros allow the user to suspend the handling of interrupt signals
415  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
416  * much more efficient and portable.  (But hacking the kernel is so much
417  * more fun than worrying about efficiency and portability. :-))
418  */
419 #define INT_OFF do { \
420         suppress_int++; \
421         xbarrier(); \
422 } while (0)
423
424 /*
425  * Called to raise an exception.  Since C doesn't include exceptions, we
426  * just do a longjmp to the exception handler.  The type of exception is
427  * stored in the global variable "exception_type".
428  */
429 static void raise_exception(int) NORETURN;
430 static void
431 raise_exception(int e)
432 {
433 #if DEBUG
434         if (exception_handler == NULL)
435                 abort();
436 #endif
437         INT_OFF;
438         exception_type = e;
439         longjmp(exception_handler->loc, 1);
440 }
441 #if DEBUG
442 #define raise_exception(e) do { \
443         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
444         raise_exception(e); \
445 } while (0)
446 #endif
447
448 /*
449  * Called from trap.c when a SIGINT is received.  (If the user specifies
450  * that SIGINT is to be trapped or ignored using the trap builtin, then
451  * this routine is not called.)  Suppressint is nonzero when interrupts
452  * are held using the INT_OFF macro.  (The test for iflag is just
453  * defensive programming.)
454  */
455 static void raise_interrupt(void) NORETURN;
456 static void
457 raise_interrupt(void)
458 {
459         int ex_type;
460
461         pending_int = 0;
462         /* Signal is not automatically unmasked after it is raised,
463          * do it ourself - unmask all signals */
464         sigprocmask_allsigs(SIG_UNBLOCK);
465         /* pending_sig = 0; - now done in signal_handler() */
466
467         ex_type = EXSIG;
468         if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
469                 if (!(rootshell && iflag)) {
470                         /* Kill ourself with SIGINT */
471                         signal(SIGINT, SIG_DFL);
472                         raise(SIGINT);
473                 }
474                 ex_type = EXINT;
475         }
476         raise_exception(ex_type);
477         /* NOTREACHED */
478 }
479 #if DEBUG
480 #define raise_interrupt() do { \
481         TRACE(("raising interrupt on line %d\n", __LINE__)); \
482         raise_interrupt(); \
483 } while (0)
484 #endif
485
486 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
487 int_on(void)
488 {
489         xbarrier();
490         if (--suppress_int == 0 && pending_int) {
491                 raise_interrupt();
492         }
493 }
494 #define INT_ON int_on()
495 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
496 force_int_on(void)
497 {
498         xbarrier();
499         suppress_int = 0;
500         if (pending_int)
501                 raise_interrupt();
502 }
503 #define FORCE_INT_ON force_int_on()
504
505 #define SAVE_INT(v) ((v) = suppress_int)
506
507 #define RESTORE_INT(v) do { \
508         xbarrier(); \
509         suppress_int = (v); \
510         if (suppress_int == 0 && pending_int) \
511                 raise_interrupt(); \
512 } while (0)
513
514
515 /* ============ Stdout/stderr output */
516
517 static void
518 outstr(const char *p, FILE *file)
519 {
520         INT_OFF;
521         fputs(p, file);
522         INT_ON;
523 }
524
525 static void
526 flush_stdout_stderr(void)
527 {
528         INT_OFF;
529         fflush_all();
530         INT_ON;
531 }
532
533 static void
534 outcslow(int c, FILE *dest)
535 {
536         INT_OFF;
537         putc(c, dest);
538         fflush(dest);
539         INT_ON;
540 }
541
542 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
543 static int
544 out1fmt(const char *fmt, ...)
545 {
546         va_list ap;
547         int r;
548
549         INT_OFF;
550         va_start(ap, fmt);
551         r = vprintf(fmt, ap);
552         va_end(ap);
553         INT_ON;
554         return r;
555 }
556
557 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
558 static int
559 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
560 {
561         va_list ap;
562         int ret;
563
564         va_start(ap, fmt);
565         INT_OFF;
566         ret = vsnprintf(outbuf, length, fmt, ap);
567         va_end(ap);
568         INT_ON;
569         return ret;
570 }
571
572 static void
573 out1str(const char *p)
574 {
575         outstr(p, stdout);
576 }
577
578 static void
579 out2str(const char *p)
580 {
581         outstr(p, stderr);
582         flush_stdout_stderr();
583 }
584
585
586 /* ============ Parser structures */
587
588 /* control characters in argument strings */
589 #define CTL_FIRST CTLESC
590 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
591 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
592 #define CTLENDVAR    ((unsigned char)'\203')
593 #define CTLBACKQ     ((unsigned char)'\204')
594 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
595 /*      CTLBACKQ | CTLQUOTE == '\205' */
596 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
597 #define CTLENDARI    ((unsigned char)'\207')
598 #define CTLQUOTEMARK ((unsigned char)'\210')
599 #define CTL_LAST CTLQUOTEMARK
600
601 /* variable substitution byte (follows CTLVAR) */
602 #define VSTYPE  0x0f            /* type of variable substitution */
603 #define VSNUL   0x10            /* colon--treat the empty string as unset */
604 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
605
606 /* values of VSTYPE field */
607 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
608 #define VSMINUS         0x2     /* ${var-text} */
609 #define VSPLUS          0x3     /* ${var+text} */
610 #define VSQUESTION      0x4     /* ${var?message} */
611 #define VSASSIGN        0x5     /* ${var=text} */
612 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
613 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
614 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
615 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
616 #define VSLENGTH        0xa     /* ${#var} */
617 #if ENABLE_ASH_BASH_COMPAT
618 #define VSSUBSTR        0xc     /* ${var:position:length} */
619 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
620 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
621 #endif
622
623 static const char dolatstr[] ALIGN1 = {
624         CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
625 };
626
627 #define NCMD      0
628 #define NPIPE     1
629 #define NREDIR    2
630 #define NBACKGND  3
631 #define NSUBSHELL 4
632 #define NAND      5
633 #define NOR       6
634 #define NSEMI     7
635 #define NIF       8
636 #define NWHILE    9
637 #define NUNTIL   10
638 #define NFOR     11
639 #define NCASE    12
640 #define NCLIST   13
641 #define NDEFUN   14
642 #define NARG     15
643 #define NTO      16
644 #if ENABLE_ASH_BASH_COMPAT
645 #define NTO2     17
646 #endif
647 #define NCLOBBER 18
648 #define NFROM    19
649 #define NFROMTO  20
650 #define NAPPEND  21
651 #define NTOFD    22
652 #define NFROMFD  23
653 #define NHERE    24
654 #define NXHERE   25
655 #define NNOT     26
656 #define N_NUMBER 27
657
658 union node;
659
660 struct ncmd {
661         smallint type; /* Nxxxx */
662         union node *assign;
663         union node *args;
664         union node *redirect;
665 };
666
667 struct npipe {
668         smallint type;
669         smallint pipe_backgnd;
670         struct nodelist *cmdlist;
671 };
672
673 struct nredir {
674         smallint type;
675         union node *n;
676         union node *redirect;
677 };
678
679 struct nbinary {
680         smallint type;
681         union node *ch1;
682         union node *ch2;
683 };
684
685 struct nif {
686         smallint type;
687         union node *test;
688         union node *ifpart;
689         union node *elsepart;
690 };
691
692 struct nfor {
693         smallint type;
694         union node *args;
695         union node *body;
696         char *var;
697 };
698
699 struct ncase {
700         smallint type;
701         union node *expr;
702         union node *cases;
703 };
704
705 struct nclist {
706         smallint type;
707         union node *next;
708         union node *pattern;
709         union node *body;
710 };
711
712 struct narg {
713         smallint type;
714         union node *next;
715         char *text;
716         struct nodelist *backquote;
717 };
718
719 /* nfile and ndup layout must match!
720  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
721  * that it is actually NTO2 (>&file), and change its type.
722  */
723 struct nfile {
724         smallint type;
725         union node *next;
726         int fd;
727         int _unused_dupfd;
728         union node *fname;
729         char *expfname;
730 };
731
732 struct ndup {
733         smallint type;
734         union node *next;
735         int fd;
736         int dupfd;
737         union node *vname;
738         char *_unused_expfname;
739 };
740
741 struct nhere {
742         smallint type;
743         union node *next;
744         int fd;
745         union node *doc;
746 };
747
748 struct nnot {
749         smallint type;
750         union node *com;
751 };
752
753 union node {
754         smallint type;
755         struct ncmd ncmd;
756         struct npipe npipe;
757         struct nredir nredir;
758         struct nbinary nbinary;
759         struct nif nif;
760         struct nfor nfor;
761         struct ncase ncase;
762         struct nclist nclist;
763         struct narg narg;
764         struct nfile nfile;
765         struct ndup ndup;
766         struct nhere nhere;
767         struct nnot nnot;
768 };
769
770 /*
771  * NODE_EOF is returned by parsecmd when it encounters an end of file.
772  * It must be distinct from NULL.
773  */
774 #define NODE_EOF ((union node *) -1L)
775
776 struct nodelist {
777         struct nodelist *next;
778         union node *n;
779 };
780
781 struct funcnode {
782         int count;
783         union node n;
784 };
785
786 /*
787  * Free a parse tree.
788  */
789 static void
790 freefunc(struct funcnode *f)
791 {
792         if (f && --f->count < 0)
793                 free(f);
794 }
795
796
797 /* ============ Debugging output */
798
799 #if DEBUG
800
801 static FILE *tracefile;
802
803 static void
804 trace_printf(const char *fmt, ...)
805 {
806         va_list va;
807
808         if (debug != 1)
809                 return;
810         if (DEBUG_TIME)
811                 fprintf(tracefile, "%u ", (int) time(NULL));
812         if (DEBUG_PID)
813                 fprintf(tracefile, "[%u] ", (int) getpid());
814         if (DEBUG_SIG)
815                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
816         va_start(va, fmt);
817         vfprintf(tracefile, fmt, va);
818         va_end(va);
819 }
820
821 static void
822 trace_vprintf(const char *fmt, va_list va)
823 {
824         if (debug != 1)
825                 return;
826         if (DEBUG_TIME)
827                 fprintf(tracefile, "%u ", (int) time(NULL));
828         if (DEBUG_PID)
829                 fprintf(tracefile, "[%u] ", (int) getpid());
830         if (DEBUG_SIG)
831                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
832         vfprintf(tracefile, fmt, va);
833 }
834
835 static void
836 trace_puts(const char *s)
837 {
838         if (debug != 1)
839                 return;
840         fputs(s, tracefile);
841 }
842
843 static void
844 trace_puts_quoted(char *s)
845 {
846         char *p;
847         char c;
848
849         if (debug != 1)
850                 return;
851         putc('"', tracefile);
852         for (p = s; *p; p++) {
853                 switch ((unsigned char)*p) {
854                 case '\n': c = 'n'; goto backslash;
855                 case '\t': c = 't'; goto backslash;
856                 case '\r': c = 'r'; goto backslash;
857                 case '\"': c = '\"'; goto backslash;
858                 case '\\': c = '\\'; goto backslash;
859                 case CTLESC: c = 'e'; goto backslash;
860                 case CTLVAR: c = 'v'; goto backslash;
861                 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
862                 case CTLBACKQ: c = 'q'; goto backslash;
863                 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
864  backslash:
865                         putc('\\', tracefile);
866                         putc(c, tracefile);
867                         break;
868                 default:
869                         if (*p >= ' ' && *p <= '~')
870                                 putc(*p, tracefile);
871                         else {
872                                 putc('\\', tracefile);
873                                 putc((*p >> 6) & 03, tracefile);
874                                 putc((*p >> 3) & 07, tracefile);
875                                 putc(*p & 07, tracefile);
876                         }
877                         break;
878                 }
879         }
880         putc('"', tracefile);
881 }
882
883 static void
884 trace_puts_args(char **ap)
885 {
886         if (debug != 1)
887                 return;
888         if (!*ap)
889                 return;
890         while (1) {
891                 trace_puts_quoted(*ap);
892                 if (!*++ap) {
893                         putc('\n', tracefile);
894                         break;
895                 }
896                 putc(' ', tracefile);
897         }
898 }
899
900 static void
901 opentrace(void)
902 {
903         char s[100];
904 #ifdef O_APPEND
905         int flags;
906 #endif
907
908         if (debug != 1) {
909                 if (tracefile)
910                         fflush(tracefile);
911                 /* leave open because libedit might be using it */
912                 return;
913         }
914         strcpy(s, "./trace");
915         if (tracefile) {
916                 if (!freopen(s, "a", tracefile)) {
917                         fprintf(stderr, "Can't re-open %s\n", s);
918                         debug = 0;
919                         return;
920                 }
921         } else {
922                 tracefile = fopen(s, "a");
923                 if (tracefile == NULL) {
924                         fprintf(stderr, "Can't open %s\n", s);
925                         debug = 0;
926                         return;
927                 }
928         }
929 #ifdef O_APPEND
930         flags = fcntl(fileno(tracefile), F_GETFL);
931         if (flags >= 0)
932                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
933 #endif
934         setlinebuf(tracefile);
935         fputs("\nTracing started.\n", tracefile);
936 }
937
938 static void
939 indent(int amount, char *pfx, FILE *fp)
940 {
941         int i;
942
943         for (i = 0; i < amount; i++) {
944                 if (pfx && i == amount - 1)
945                         fputs(pfx, fp);
946                 putc('\t', fp);
947         }
948 }
949
950 /* little circular references here... */
951 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
952
953 static void
954 sharg(union node *arg, FILE *fp)
955 {
956         char *p;
957         struct nodelist *bqlist;
958         unsigned char subtype;
959
960         if (arg->type != NARG) {
961                 out1fmt("<node type %d>\n", arg->type);
962                 abort();
963         }
964         bqlist = arg->narg.backquote;
965         for (p = arg->narg.text; *p; p++) {
966                 switch ((unsigned char)*p) {
967                 case CTLESC:
968                         p++;
969                         putc(*p, fp);
970                         break;
971                 case CTLVAR:
972                         putc('$', fp);
973                         putc('{', fp);
974                         subtype = *++p;
975                         if (subtype == VSLENGTH)
976                                 putc('#', fp);
977
978                         while (*p != '=') {
979                                 putc(*p, fp);
980                                 p++;
981                         }
982
983                         if (subtype & VSNUL)
984                                 putc(':', fp);
985
986                         switch (subtype & VSTYPE) {
987                         case VSNORMAL:
988                                 putc('}', fp);
989                                 break;
990                         case VSMINUS:
991                                 putc('-', fp);
992                                 break;
993                         case VSPLUS:
994                                 putc('+', fp);
995                                 break;
996                         case VSQUESTION:
997                                 putc('?', fp);
998                                 break;
999                         case VSASSIGN:
1000                                 putc('=', fp);
1001                                 break;
1002                         case VSTRIMLEFT:
1003                                 putc('#', fp);
1004                                 break;
1005                         case VSTRIMLEFTMAX:
1006                                 putc('#', fp);
1007                                 putc('#', fp);
1008                                 break;
1009                         case VSTRIMRIGHT:
1010                                 putc('%', fp);
1011                                 break;
1012                         case VSTRIMRIGHTMAX:
1013                                 putc('%', fp);
1014                                 putc('%', fp);
1015                                 break;
1016                         case VSLENGTH:
1017                                 break;
1018                         default:
1019                                 out1fmt("<subtype %d>", subtype);
1020                         }
1021                         break;
1022                 case CTLENDVAR:
1023                         putc('}', fp);
1024                         break;
1025                 case CTLBACKQ:
1026                 case CTLBACKQ|CTLQUOTE:
1027                         putc('$', fp);
1028                         putc('(', fp);
1029                         shtree(bqlist->n, -1, NULL, fp);
1030                         putc(')', fp);
1031                         break;
1032                 default:
1033                         putc(*p, fp);
1034                         break;
1035                 }
1036         }
1037 }
1038
1039 static void
1040 shcmd(union node *cmd, FILE *fp)
1041 {
1042         union node *np;
1043         int first;
1044         const char *s;
1045         int dftfd;
1046
1047         first = 1;
1048         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1049                 if (!first)
1050                         putc(' ', fp);
1051                 sharg(np, fp);
1052                 first = 0;
1053         }
1054         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1055                 if (!first)
1056                         putc(' ', fp);
1057                 dftfd = 0;
1058                 switch (np->nfile.type) {
1059                 case NTO:      s = ">>"+1; dftfd = 1; break;
1060                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1061                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1062 #if ENABLE_ASH_BASH_COMPAT
1063                 case NTO2:
1064 #endif
1065                 case NTOFD:    s = ">&"; dftfd = 1; break;
1066                 case NFROM:    s = "<"; break;
1067                 case NFROMFD:  s = "<&"; break;
1068                 case NFROMTO:  s = "<>"; break;
1069                 default:       s = "*error*"; break;
1070                 }
1071                 if (np->nfile.fd != dftfd)
1072                         fprintf(fp, "%d", np->nfile.fd);
1073                 fputs(s, fp);
1074                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1075                         fprintf(fp, "%d", np->ndup.dupfd);
1076                 } else {
1077                         sharg(np->nfile.fname, fp);
1078                 }
1079                 first = 0;
1080         }
1081 }
1082
1083 static void
1084 shtree(union node *n, int ind, char *pfx, FILE *fp)
1085 {
1086         struct nodelist *lp;
1087         const char *s;
1088
1089         if (n == NULL)
1090                 return;
1091
1092         indent(ind, pfx, fp);
1093
1094         if (n == NODE_EOF) {
1095                 fputs("<EOF>", fp);
1096                 return;
1097         }
1098
1099         switch (n->type) {
1100         case NSEMI:
1101                 s = "; ";
1102                 goto binop;
1103         case NAND:
1104                 s = " && ";
1105                 goto binop;
1106         case NOR:
1107                 s = " || ";
1108  binop:
1109                 shtree(n->nbinary.ch1, ind, NULL, fp);
1110                 /* if (ind < 0) */
1111                         fputs(s, fp);
1112                 shtree(n->nbinary.ch2, ind, NULL, fp);
1113                 break;
1114         case NCMD:
1115                 shcmd(n, fp);
1116                 if (ind >= 0)
1117                         putc('\n', fp);
1118                 break;
1119         case NPIPE:
1120                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1121                         shtree(lp->n, 0, NULL, fp);
1122                         if (lp->next)
1123                                 fputs(" | ", fp);
1124                 }
1125                 if (n->npipe.pipe_backgnd)
1126                         fputs(" &", fp);
1127                 if (ind >= 0)
1128                         putc('\n', fp);
1129                 break;
1130         default:
1131                 fprintf(fp, "<node type %d>", n->type);
1132                 if (ind >= 0)
1133                         putc('\n', fp);
1134                 break;
1135         }
1136 }
1137
1138 static void
1139 showtree(union node *n)
1140 {
1141         trace_puts("showtree called\n");
1142         shtree(n, 1, NULL, stderr);
1143 }
1144
1145 #endif /* DEBUG */
1146
1147
1148 /* ============ Parser data */
1149
1150 /*
1151  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1152  */
1153 struct strlist {
1154         struct strlist *next;
1155         char *text;
1156 };
1157
1158 struct alias;
1159
1160 struct strpush {
1161         struct strpush *prev;   /* preceding string on stack */
1162         char *prev_string;
1163         int prev_left_in_line;
1164 #if ENABLE_ASH_ALIAS
1165         struct alias *ap;       /* if push was associated with an alias */
1166 #endif
1167         char *string;           /* remember the string since it may change */
1168 };
1169
1170 struct parsefile {
1171         struct parsefile *prev; /* preceding file on stack */
1172         int linno;              /* current line */
1173         int pf_fd;              /* file descriptor (or -1 if string) */
1174         int left_in_line;       /* number of chars left in this line */
1175         int left_in_buffer;     /* number of chars left in this buffer past the line */
1176         char *next_to_pgetc;    /* next char in buffer */
1177         char *buf;              /* input buffer */
1178         struct strpush *strpush; /* for pushing strings at this level */
1179         struct strpush basestrpush; /* so pushing one is fast */
1180 };
1181
1182 static struct parsefile basepf;        /* top level input file */
1183 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1184 static int startlinno;                 /* line # where last token started */
1185 static char *commandname;              /* currently executing command */
1186 static struct strlist *cmdenviron;     /* environment for builtin command */
1187 static uint8_t exitstatus;             /* exit status of last command */
1188
1189
1190 /* ============ Message printing */
1191
1192 static void
1193 ash_vmsg(const char *msg, va_list ap)
1194 {
1195         fprintf(stderr, "%s: ", arg0);
1196         if (commandname) {
1197                 if (strcmp(arg0, commandname))
1198                         fprintf(stderr, "%s: ", commandname);
1199                 if (!iflag || g_parsefile->pf_fd > 0)
1200                         fprintf(stderr, "line %d: ", startlinno);
1201         }
1202         vfprintf(stderr, msg, ap);
1203         outcslow('\n', stderr);
1204 }
1205
1206 /*
1207  * Exverror is called to raise the error exception.  If the second argument
1208  * is not NULL then error prints an error message using printf style
1209  * formatting.  It then raises the error exception.
1210  */
1211 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1212 static void
1213 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1214 {
1215 #if DEBUG
1216         if (msg) {
1217                 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1218                 TRACEV((msg, ap));
1219                 TRACE(("\") pid=%d\n", getpid()));
1220         } else
1221                 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1222         if (msg)
1223 #endif
1224                 ash_vmsg(msg, ap);
1225
1226         flush_stdout_stderr();
1227         raise_exception(cond);
1228         /* NOTREACHED */
1229 }
1230
1231 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1232 static void
1233 ash_msg_and_raise_error(const char *msg, ...)
1234 {
1235         va_list ap;
1236
1237         va_start(ap, msg);
1238         ash_vmsg_and_raise(EXERROR, msg, ap);
1239         /* NOTREACHED */
1240         va_end(ap);
1241 }
1242
1243 static void raise_error_syntax(const char *) NORETURN;
1244 static void
1245 raise_error_syntax(const char *msg)
1246 {
1247         ash_msg_and_raise_error("syntax error: %s", msg);
1248         /* NOTREACHED */
1249 }
1250
1251 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1252 static void
1253 ash_msg_and_raise(int cond, const char *msg, ...)
1254 {
1255         va_list ap;
1256
1257         va_start(ap, msg);
1258         ash_vmsg_and_raise(cond, msg, ap);
1259         /* NOTREACHED */
1260         va_end(ap);
1261 }
1262
1263 /*
1264  * error/warning routines for external builtins
1265  */
1266 static void
1267 ash_msg(const char *fmt, ...)
1268 {
1269         va_list ap;
1270
1271         va_start(ap, fmt);
1272         ash_vmsg(fmt, ap);
1273         va_end(ap);
1274 }
1275
1276 /*
1277  * Return a string describing an error.  The returned string may be a
1278  * pointer to a static buffer that will be overwritten on the next call.
1279  * Action describes the operation that got the error.
1280  */
1281 static const char *
1282 errmsg(int e, const char *em)
1283 {
1284         if (e == ENOENT || e == ENOTDIR) {
1285                 return em;
1286         }
1287         return strerror(e);
1288 }
1289
1290
1291 /* ============ Memory allocation */
1292
1293 #if 0
1294 /* I consider these wrappers nearly useless:
1295  * ok, they return you to nearest exception handler, but
1296  * how much memory do you leak in the process, making
1297  * memory starvation worse?
1298  */
1299 static void *
1300 ckrealloc(void * p, size_t nbytes)
1301 {
1302         p = realloc(p, nbytes);
1303         if (!p)
1304                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1305         return p;
1306 }
1307
1308 static void *
1309 ckmalloc(size_t nbytes)
1310 {
1311         return ckrealloc(NULL, nbytes);
1312 }
1313
1314 static void *
1315 ckzalloc(size_t nbytes)
1316 {
1317         return memset(ckmalloc(nbytes), 0, nbytes);
1318 }
1319
1320 static char *
1321 ckstrdup(const char *s)
1322 {
1323         char *p = strdup(s);
1324         if (!p)
1325                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1326         return p;
1327 }
1328 #else
1329 /* Using bbox equivalents. They exit if out of memory */
1330 # define ckrealloc xrealloc
1331 # define ckmalloc  xmalloc
1332 # define ckzalloc  xzalloc
1333 # define ckstrdup  xstrdup
1334 #endif
1335
1336 /*
1337  * It appears that grabstackstr() will barf with such alignments
1338  * because stalloc() will return a string allocated in a new stackblock.
1339  */
1340 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1341 enum {
1342         /* Most machines require the value returned from malloc to be aligned
1343          * in some way.  The following macro will get this right
1344          * on many machines.  */
1345         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1346         /* Minimum size of a block */
1347         MINSIZE = SHELL_ALIGN(504),
1348 };
1349
1350 struct stack_block {
1351         struct stack_block *prev;
1352         char space[MINSIZE];
1353 };
1354
1355 struct stackmark {
1356         struct stack_block *stackp;
1357         char *stacknxt;
1358         size_t stacknleft;
1359         struct stackmark *marknext;
1360 };
1361
1362
1363 struct globals_memstack {
1364         struct stack_block *g_stackp; // = &stackbase;
1365         struct stackmark *markp;
1366         char *g_stacknxt; // = stackbase.space;
1367         char *sstrend; // = stackbase.space + MINSIZE;
1368         size_t g_stacknleft; // = MINSIZE;
1369         int    herefd; // = -1;
1370         struct stack_block stackbase;
1371 };
1372 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1373 #define G_memstack (*ash_ptr_to_globals_memstack)
1374 #define g_stackp     (G_memstack.g_stackp    )
1375 #define markp        (G_memstack.markp       )
1376 #define g_stacknxt   (G_memstack.g_stacknxt  )
1377 #define sstrend      (G_memstack.sstrend     )
1378 #define g_stacknleft (G_memstack.g_stacknleft)
1379 #define herefd       (G_memstack.herefd      )
1380 #define stackbase    (G_memstack.stackbase   )
1381 #define INIT_G_memstack() do { \
1382         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1383         barrier(); \
1384         g_stackp = &stackbase; \
1385         g_stacknxt = stackbase.space; \
1386         g_stacknleft = MINSIZE; \
1387         sstrend = stackbase.space + MINSIZE; \
1388         herefd = -1; \
1389 } while (0)
1390
1391
1392 #define stackblock()     ((void *)g_stacknxt)
1393 #define stackblocksize() g_stacknleft
1394
1395 /*
1396  * Parse trees for commands are allocated in lifo order, so we use a stack
1397  * to make this more efficient, and also to avoid all sorts of exception
1398  * handling code to handle interrupts in the middle of a parse.
1399  *
1400  * The size 504 was chosen because the Ultrix malloc handles that size
1401  * well.
1402  */
1403 static void *
1404 stalloc(size_t nbytes)
1405 {
1406         char *p;
1407         size_t aligned;
1408
1409         aligned = SHELL_ALIGN(nbytes);
1410         if (aligned > g_stacknleft) {
1411                 size_t len;
1412                 size_t blocksize;
1413                 struct stack_block *sp;
1414
1415                 blocksize = aligned;
1416                 if (blocksize < MINSIZE)
1417                         blocksize = MINSIZE;
1418                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1419                 if (len < blocksize)
1420                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1421                 INT_OFF;
1422                 sp = ckmalloc(len);
1423                 sp->prev = g_stackp;
1424                 g_stacknxt = sp->space;
1425                 g_stacknleft = blocksize;
1426                 sstrend = g_stacknxt + blocksize;
1427                 g_stackp = sp;
1428                 INT_ON;
1429         }
1430         p = g_stacknxt;
1431         g_stacknxt += aligned;
1432         g_stacknleft -= aligned;
1433         return p;
1434 }
1435
1436 static void *
1437 stzalloc(size_t nbytes)
1438 {
1439         return memset(stalloc(nbytes), 0, nbytes);
1440 }
1441
1442 static void
1443 stunalloc(void *p)
1444 {
1445 #if DEBUG
1446         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1447                 write(STDERR_FILENO, "stunalloc\n", 10);
1448                 abort();
1449         }
1450 #endif
1451         g_stacknleft += g_stacknxt - (char *)p;
1452         g_stacknxt = p;
1453 }
1454
1455 /*
1456  * Like strdup but works with the ash stack.
1457  */
1458 static char *
1459 ststrdup(const char *p)
1460 {
1461         size_t len = strlen(p) + 1;
1462         return memcpy(stalloc(len), p, len);
1463 }
1464
1465 static void
1466 setstackmark(struct stackmark *mark)
1467 {
1468         mark->stackp = g_stackp;
1469         mark->stacknxt = g_stacknxt;
1470         mark->stacknleft = g_stacknleft;
1471         mark->marknext = markp;
1472         markp = mark;
1473 }
1474
1475 static void
1476 popstackmark(struct stackmark *mark)
1477 {
1478         struct stack_block *sp;
1479
1480         if (!mark->stackp)
1481                 return;
1482
1483         INT_OFF;
1484         markp = mark->marknext;
1485         while (g_stackp != mark->stackp) {
1486                 sp = g_stackp;
1487                 g_stackp = sp->prev;
1488                 free(sp);
1489         }
1490         g_stacknxt = mark->stacknxt;
1491         g_stacknleft = mark->stacknleft;
1492         sstrend = mark->stacknxt + mark->stacknleft;
1493         INT_ON;
1494 }
1495
1496 /*
1497  * When the parser reads in a string, it wants to stick the string on the
1498  * stack and only adjust the stack pointer when it knows how big the
1499  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1500  * of space on top of the stack and stackblocklen returns the length of
1501  * this block.  Growstackblock will grow this space by at least one byte,
1502  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1503  * part of the block that has been used.
1504  */
1505 static void
1506 growstackblock(void)
1507 {
1508         size_t newlen;
1509
1510         newlen = g_stacknleft * 2;
1511         if (newlen < g_stacknleft)
1512                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1513         if (newlen < 128)
1514                 newlen += 128;
1515
1516         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1517                 struct stack_block *oldstackp;
1518                 struct stackmark *xmark;
1519                 struct stack_block *sp;
1520                 struct stack_block *prevstackp;
1521                 size_t grosslen;
1522
1523                 INT_OFF;
1524                 oldstackp = g_stackp;
1525                 sp = g_stackp;
1526                 prevstackp = sp->prev;
1527                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1528                 sp = ckrealloc(sp, grosslen);
1529                 sp->prev = prevstackp;
1530                 g_stackp = sp;
1531                 g_stacknxt = sp->space;
1532                 g_stacknleft = newlen;
1533                 sstrend = sp->space + newlen;
1534
1535                 /*
1536                  * Stack marks pointing to the start of the old block
1537                  * must be relocated to point to the new block
1538                  */
1539                 xmark = markp;
1540                 while (xmark != NULL && xmark->stackp == oldstackp) {
1541                         xmark->stackp = g_stackp;
1542                         xmark->stacknxt = g_stacknxt;
1543                         xmark->stacknleft = g_stacknleft;
1544                         xmark = xmark->marknext;
1545                 }
1546                 INT_ON;
1547         } else {
1548                 char *oldspace = g_stacknxt;
1549                 size_t oldlen = g_stacknleft;
1550                 char *p = stalloc(newlen);
1551
1552                 /* free the space we just allocated */
1553                 g_stacknxt = memcpy(p, oldspace, oldlen);
1554                 g_stacknleft += newlen;
1555         }
1556 }
1557
1558 static void
1559 grabstackblock(size_t len)
1560 {
1561         len = SHELL_ALIGN(len);
1562         g_stacknxt += len;
1563         g_stacknleft -= len;
1564 }
1565
1566 /*
1567  * The following routines are somewhat easier to use than the above.
1568  * The user declares a variable of type STACKSTR, which may be declared
1569  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1570  * the user uses the macro STPUTC to add characters to the string.  In
1571  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1572  * grown as necessary.  When the user is done, she can just leave the
1573  * string there and refer to it using stackblock().  Or she can allocate
1574  * the space for it using grabstackstr().  If it is necessary to allow
1575  * someone else to use the stack temporarily and then continue to grow
1576  * the string, the user should use grabstack to allocate the space, and
1577  * then call ungrabstr(p) to return to the previous mode of operation.
1578  *
1579  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1580  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1581  * is space for at least one character.
1582  */
1583 static void *
1584 growstackstr(void)
1585 {
1586         size_t len = stackblocksize();
1587         if (herefd >= 0 && len >= 1024) {
1588                 full_write(herefd, stackblock(), len);
1589                 return stackblock();
1590         }
1591         growstackblock();
1592         return (char *)stackblock() + len;
1593 }
1594
1595 /*
1596  * Called from CHECKSTRSPACE.
1597  */
1598 static char *
1599 makestrspace(size_t newlen, char *p)
1600 {
1601         size_t len = p - g_stacknxt;
1602         size_t size = stackblocksize();
1603
1604         for (;;) {
1605                 size_t nleft;
1606
1607                 size = stackblocksize();
1608                 nleft = size - len;
1609                 if (nleft >= newlen)
1610                         break;
1611                 growstackblock();
1612         }
1613         return (char *)stackblock() + len;
1614 }
1615
1616 static char *
1617 stack_nputstr(const char *s, size_t n, char *p)
1618 {
1619         p = makestrspace(n, p);
1620         p = (char *)memcpy(p, s, n) + n;
1621         return p;
1622 }
1623
1624 static char *
1625 stack_putstr(const char *s, char *p)
1626 {
1627         return stack_nputstr(s, strlen(s), p);
1628 }
1629
1630 static char *
1631 _STPUTC(int c, char *p)
1632 {
1633         if (p == sstrend)
1634                 p = growstackstr();
1635         *p++ = c;
1636         return p;
1637 }
1638
1639 #define STARTSTACKSTR(p)        ((p) = stackblock())
1640 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1641 #define CHECKSTRSPACE(n, p) do { \
1642         char *q = (p); \
1643         size_t l = (n); \
1644         size_t m = sstrend - q; \
1645         if (l > m) \
1646                 (p) = makestrspace(l, q); \
1647 } while (0)
1648 #define USTPUTC(c, p)           (*(p)++ = (c))
1649 #define STACKSTRNUL(p) do { \
1650         if ((p) == sstrend) \
1651                 (p) = growstackstr(); \
1652         *(p) = '\0'; \
1653 } while (0)
1654 #define STUNPUTC(p)             (--(p))
1655 #define STTOPC(p)               ((p)[-1])
1656 #define STADJUST(amount, p)     ((p) += (amount))
1657
1658 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1659 #define ungrabstackstr(s, p)    stunalloc(s)
1660 #define stackstrend()           ((void *)sstrend)
1661
1662
1663 /* ============ String helpers */
1664
1665 /*
1666  * prefix -- see if pfx is a prefix of string.
1667  */
1668 static char *
1669 prefix(const char *string, const char *pfx)
1670 {
1671         while (*pfx) {
1672                 if (*pfx++ != *string++)
1673                         return NULL;
1674         }
1675         return (char *) string;
1676 }
1677
1678 /*
1679  * Check for a valid number.  This should be elsewhere.
1680  */
1681 static int
1682 is_number(const char *p)
1683 {
1684         do {
1685                 if (!isdigit(*p))
1686                         return 0;
1687         } while (*++p != '\0');
1688         return 1;
1689 }
1690
1691 /*
1692  * Convert a string of digits to an integer, printing an error message on
1693  * failure.
1694  */
1695 static int
1696 number(const char *s)
1697 {
1698         if (!is_number(s))
1699                 ash_msg_and_raise_error(msg_illnum, s);
1700         return atoi(s);
1701 }
1702
1703 /*
1704  * Produce a possibly single quoted string suitable as input to the shell.
1705  * The return string is allocated on the stack.
1706  */
1707 static char *
1708 single_quote(const char *s)
1709 {
1710         char *p;
1711
1712         STARTSTACKSTR(p);
1713
1714         do {
1715                 char *q;
1716                 size_t len;
1717
1718                 len = strchrnul(s, '\'') - s;
1719
1720                 q = p = makestrspace(len + 3, p);
1721
1722                 *q++ = '\'';
1723                 q = (char *)memcpy(q, s, len) + len;
1724                 *q++ = '\'';
1725                 s += len;
1726
1727                 STADJUST(q - p, p);
1728
1729                 if (*s != '\'')
1730                         break;
1731                 len = 0;
1732                 do len++; while (*++s == '\'');
1733
1734                 q = p = makestrspace(len + 3, p);
1735
1736                 *q++ = '"';
1737                 q = (char *)memcpy(q, s - len, len) + len;
1738                 *q++ = '"';
1739
1740                 STADJUST(q - p, p);
1741         } while (*s);
1742
1743         USTPUTC('\0', p);
1744
1745         return stackblock();
1746 }
1747
1748
1749 /* ============ nextopt */
1750
1751 static char **argptr;                  /* argument list for builtin commands */
1752 static char *optionarg;                /* set by nextopt (like getopt) */
1753 static char *optptr;                   /* used by nextopt */
1754
1755 /*
1756  * XXX - should get rid of. Have all builtins use getopt(3).
1757  * The library getopt must have the BSD extension static variable
1758  * "optreset", otherwise it can't be used within the shell safely.
1759  *
1760  * Standard option processing (a la getopt) for builtin routines.
1761  * The only argument that is passed to nextopt is the option string;
1762  * the other arguments are unnecessary. It returns the character,
1763  * or '\0' on end of input.
1764  */
1765 static int
1766 nextopt(const char *optstring)
1767 {
1768         char *p;
1769         const char *q;
1770         char c;
1771
1772         p = optptr;
1773         if (p == NULL || *p == '\0') {
1774                 /* We ate entire "-param", take next one */
1775                 p = *argptr;
1776                 if (p == NULL)
1777                         return '\0';
1778                 if (*p != '-')
1779                         return '\0';
1780                 if (*++p == '\0') /* just "-" ? */
1781                         return '\0';
1782                 argptr++;
1783                 if (LONE_DASH(p)) /* "--" ? */
1784                         return '\0';
1785                 /* p => next "-param" */
1786         }
1787         /* p => some option char in the middle of a "-param" */
1788         c = *p++;
1789         for (q = optstring; *q != c;) {
1790                 if (*q == '\0')
1791                         ash_msg_and_raise_error("illegal option -%c", c);
1792                 if (*++q == ':')
1793                         q++;
1794         }
1795         if (*++q == ':') {
1796                 if (*p == '\0') {
1797                         p = *argptr++;
1798                         if (p == NULL)
1799                                 ash_msg_and_raise_error("no arg for -%c option", c);
1800                 }
1801                 optionarg = p;
1802                 p = NULL;
1803         }
1804         optptr = p;
1805         return c;
1806 }
1807
1808
1809 /* ============ Shell variables */
1810
1811 /*
1812  * The parsefile structure pointed to by the global variable parsefile
1813  * contains information about the current file being read.
1814  */
1815 struct shparam {
1816         int nparam;             /* # of positional parameters (without $0) */
1817 #if ENABLE_ASH_GETOPTS
1818         int optind;             /* next parameter to be processed by getopts */
1819         int optoff;             /* used by getopts */
1820 #endif
1821         unsigned char malloced; /* if parameter list dynamically allocated */
1822         char **p;               /* parameter list */
1823 };
1824
1825 /*
1826  * Free the list of positional parameters.
1827  */
1828 static void
1829 freeparam(volatile struct shparam *param)
1830 {
1831         if (param->malloced) {
1832                 char **ap, **ap1;
1833                 ap = ap1 = param->p;
1834                 while (*ap)
1835                         free(*ap++);
1836                 free(ap1);
1837         }
1838 }
1839
1840 #if ENABLE_ASH_GETOPTS
1841 static void FAST_FUNC getoptsreset(const char *value);
1842 #endif
1843
1844 struct var {
1845         struct var *next;               /* next entry in hash list */
1846         int flags;                      /* flags are defined above */
1847         const char *var_text;           /* name=value */
1848         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1849                                         /* the variable gets set/unset */
1850 };
1851
1852 struct localvar {
1853         struct localvar *next;          /* next local variable in list */
1854         struct var *vp;                 /* the variable that was made local */
1855         int flags;                      /* saved flags */
1856         const char *text;               /* saved text */
1857 };
1858
1859 /* flags */
1860 #define VEXPORT         0x01    /* variable is exported */
1861 #define VREADONLY       0x02    /* variable cannot be modified */
1862 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1863 #define VTEXTFIXED      0x08    /* text is statically allocated */
1864 #define VSTACK          0x10    /* text is allocated on the stack */
1865 #define VUNSET          0x20    /* the variable is not set */
1866 #define VNOFUNC         0x40    /* don't call the callback function */
1867 #define VNOSET          0x80    /* do not set variable - just readonly test */
1868 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1869 #if ENABLE_ASH_RANDOM_SUPPORT
1870 # define VDYNAMIC       0x200   /* dynamic variable */
1871 #else
1872 # define VDYNAMIC       0
1873 #endif
1874
1875
1876 /* Need to be before varinit_data[] */
1877 #if ENABLE_LOCALE_SUPPORT
1878 static void FAST_FUNC
1879 change_lc_all(const char *value)
1880 {
1881         if (value && *value != '\0')
1882                 setlocale(LC_ALL, value);
1883 }
1884 static void FAST_FUNC
1885 change_lc_ctype(const char *value)
1886 {
1887         if (value && *value != '\0')
1888                 setlocale(LC_CTYPE, value);
1889 }
1890 #endif
1891 #if ENABLE_ASH_MAIL
1892 static void chkmail(void);
1893 static void changemail(const char *var_value) FAST_FUNC;
1894 #else
1895 # define chkmail()  ((void)0)
1896 #endif
1897 static void changepath(const char *) FAST_FUNC;
1898 #if ENABLE_ASH_RANDOM_SUPPORT
1899 static void change_random(const char *) FAST_FUNC;
1900 #endif
1901
1902 static const struct {
1903         int flags;
1904         const char *var_text;
1905         void (*var_func)(const char *) FAST_FUNC;
1906 } varinit_data[] = {
1907         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1908 #if ENABLE_ASH_MAIL
1909         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1910         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1911 #endif
1912         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1913         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1914         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1915         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1916 #if ENABLE_ASH_GETOPTS
1917         { VSTRFIXED|VTEXTFIXED       , "OPTIND=1"  , getoptsreset    },
1918 #endif
1919 #if ENABLE_ASH_RANDOM_SUPPORT
1920         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
1921 #endif
1922 #if ENABLE_LOCALE_SUPPORT
1923         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
1924         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
1925 #endif
1926 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1927         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
1928 #endif
1929 };
1930
1931 struct redirtab;
1932
1933 struct globals_var {
1934         struct shparam shellparam;      /* $@ current positional parameters */
1935         struct redirtab *redirlist;
1936         int g_nullredirs;
1937         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1938         struct var *vartab[VTABSIZE];
1939         struct var varinit[ARRAY_SIZE(varinit_data)];
1940 };
1941 extern struct globals_var *const ash_ptr_to_globals_var;
1942 #define G_var (*ash_ptr_to_globals_var)
1943 #define shellparam    (G_var.shellparam   )
1944 //#define redirlist     (G_var.redirlist    )
1945 #define g_nullredirs  (G_var.g_nullredirs )
1946 #define preverrout_fd (G_var.preverrout_fd)
1947 #define vartab        (G_var.vartab       )
1948 #define varinit       (G_var.varinit      )
1949 #define INIT_G_var() do { \
1950         unsigned i; \
1951         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1952         barrier(); \
1953         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1954                 varinit[i].flags    = varinit_data[i].flags; \
1955                 varinit[i].var_text = varinit_data[i].var_text; \
1956                 varinit[i].var_func = varinit_data[i].var_func; \
1957         } \
1958 } while (0)
1959
1960 #define vifs      varinit[0]
1961 #if ENABLE_ASH_MAIL
1962 # define vmail    (&vifs)[1]
1963 # define vmpath   (&vmail)[1]
1964 # define vpath    (&vmpath)[1]
1965 #else
1966 # define vpath    (&vifs)[1]
1967 #endif
1968 #define vps1      (&vpath)[1]
1969 #define vps2      (&vps1)[1]
1970 #define vps4      (&vps2)[1]
1971 #if ENABLE_ASH_GETOPTS
1972 # define voptind  (&vps4)[1]
1973 # if ENABLE_ASH_RANDOM_SUPPORT
1974 #  define vrandom (&voptind)[1]
1975 # endif
1976 #else
1977 # if ENABLE_ASH_RANDOM_SUPPORT
1978 #  define vrandom (&vps4)[1]
1979 # endif
1980 #endif
1981
1982 /*
1983  * The following macros access the values of the above variables.
1984  * They have to skip over the name.  They return the null string
1985  * for unset variables.
1986  */
1987 #define ifsval()        (vifs.var_text + 4)
1988 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1989 #if ENABLE_ASH_MAIL
1990 # define mailval()      (vmail.var_text + 5)
1991 # define mpathval()     (vmpath.var_text + 9)
1992 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
1993 #endif
1994 #define pathval()       (vpath.var_text + 5)
1995 #define ps1val()        (vps1.var_text + 4)
1996 #define ps2val()        (vps2.var_text + 4)
1997 #define ps4val()        (vps4.var_text + 4)
1998 #if ENABLE_ASH_GETOPTS
1999 # define optindval()    (voptind.var_text + 7)
2000 #endif
2001
2002 #if ENABLE_ASH_GETOPTS
2003 static void FAST_FUNC
2004 getoptsreset(const char *value)
2005 {
2006         shellparam.optind = number(value);
2007         shellparam.optoff = -1;
2008 }
2009 #endif
2010
2011 /* math.h has these, otherwise define our private copies */
2012 #if !ENABLE_SH_MATH_SUPPORT
2013 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
2014 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
2015 /*
2016  * Return the pointer to the first char which is not part of a legal variable name
2017  * (a letter or underscore followed by letters, underscores, and digits).
2018  */
2019 static const char*
2020 endofname(const char *name)
2021 {
2022         if (!is_name(*name))
2023                 return name;
2024         while (*++name) {
2025                 if (!is_in_name(*name))
2026                         break;
2027         }
2028         return name;
2029 }
2030 #endif
2031
2032 /*
2033  * Compares two strings up to the first = or '\0'.  The first
2034  * string must be terminated by '='; the second may be terminated by
2035  * either '=' or '\0'.
2036  */
2037 static int
2038 varcmp(const char *p, const char *q)
2039 {
2040         int c, d;
2041
2042         while ((c = *p) == (d = *q)) {
2043                 if (!c || c == '=')
2044                         goto out;
2045                 p++;
2046                 q++;
2047         }
2048         if (c == '=')
2049                 c = '\0';
2050         if (d == '=')
2051                 d = '\0';
2052  out:
2053         return c - d;
2054 }
2055
2056 /*
2057  * Find the appropriate entry in the hash table from the name.
2058  */
2059 static struct var **
2060 hashvar(const char *p)
2061 {
2062         unsigned hashval;
2063
2064         hashval = ((unsigned char) *p) << 4;
2065         while (*p && *p != '=')
2066                 hashval += (unsigned char) *p++;
2067         return &vartab[hashval % VTABSIZE];
2068 }
2069
2070 static int
2071 vpcmp(const void *a, const void *b)
2072 {
2073         return varcmp(*(const char **)a, *(const char **)b);
2074 }
2075
2076 /*
2077  * This routine initializes the builtin variables.
2078  */
2079 static void
2080 initvar(void)
2081 {
2082         struct var *vp;
2083         struct var *end;
2084         struct var **vpp;
2085
2086         /*
2087          * PS1 depends on uid
2088          */
2089 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2090         vps1.var_text = "PS1=\\w \\$ ";
2091 #else
2092         if (!geteuid())
2093                 vps1.var_text = "PS1=# ";
2094 #endif
2095         vp = varinit;
2096         end = vp + ARRAY_SIZE(varinit);
2097         do {
2098                 vpp = hashvar(vp->var_text);
2099                 vp->next = *vpp;
2100                 *vpp = vp;
2101         } while (++vp < end);
2102 }
2103
2104 static struct var **
2105 findvar(struct var **vpp, const char *name)
2106 {
2107         for (; *vpp; vpp = &(*vpp)->next) {
2108                 if (varcmp((*vpp)->var_text, name) == 0) {
2109                         break;
2110                 }
2111         }
2112         return vpp;
2113 }
2114
2115 /*
2116  * Find the value of a variable.  Returns NULL if not set.
2117  */
2118 static const char* FAST_FUNC
2119 lookupvar(const char *name)
2120 {
2121         struct var *v;
2122
2123         v = *findvar(hashvar(name), name);
2124         if (v) {
2125 #if ENABLE_ASH_RANDOM_SUPPORT
2126         /*
2127          * Dynamic variables are implemented roughly the same way they are
2128          * in bash. Namely, they're "special" so long as they aren't unset.
2129          * As soon as they're unset, they're no longer dynamic, and dynamic
2130          * lookup will no longer happen at that point. -- PFM.
2131          */
2132                 if (v->flags & VDYNAMIC)
2133                         v->var_func(NULL);
2134 #endif
2135                 if (!(v->flags & VUNSET))
2136                         return var_end(v->var_text);
2137         }
2138         return NULL;
2139 }
2140
2141 /*
2142  * Search the environment of a builtin command.
2143  */
2144 static const char *
2145 bltinlookup(const char *name)
2146 {
2147         struct strlist *sp;
2148
2149         for (sp = cmdenviron; sp; sp = sp->next) {
2150                 if (varcmp(sp->text, name) == 0)
2151                         return var_end(sp->text);
2152         }
2153         return lookupvar(name);
2154 }
2155
2156 /*
2157  * Same as setvar except that the variable and value are passed in
2158  * the first argument as name=value.  Since the first argument will
2159  * be actually stored in the table, it should not be a string that
2160  * will go away.
2161  * Called with interrupts off.
2162  */
2163 static void
2164 setvareq(char *s, int flags)
2165 {
2166         struct var *vp, **vpp;
2167
2168         vpp = hashvar(s);
2169         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2170         vp = *findvar(vpp, s);
2171         if (vp) {
2172                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2173                         const char *n;
2174
2175                         if (flags & VNOSAVE)
2176                                 free(s);
2177                         n = vp->var_text;
2178                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2179                 }
2180
2181                 if (flags & VNOSET)
2182                         return;
2183
2184                 if (vp->var_func && !(flags & VNOFUNC))
2185                         vp->var_func(var_end(s));
2186
2187                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2188                         free((char*)vp->var_text);
2189
2190                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2191         } else {
2192                 /* variable s is not found */
2193                 if (flags & VNOSET)
2194                         return;
2195                 vp = ckzalloc(sizeof(*vp));
2196                 vp->next = *vpp;
2197                 /*vp->func = NULL; - ckzalloc did it */
2198                 *vpp = vp;
2199         }
2200         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2201                 s = ckstrdup(s);
2202         vp->var_text = s;
2203         vp->flags = flags;
2204 }
2205
2206 /*
2207  * Set the value of a variable.  The flags argument is ored with the
2208  * flags of the variable.  If val is NULL, the variable is unset.
2209  */
2210 static void
2211 setvar(const char *name, const char *val, int flags)
2212 {
2213         const char *q;
2214         char *p;
2215         char *nameeq;
2216         size_t namelen;
2217         size_t vallen;
2218
2219         q = endofname(name);
2220         p = strchrnul(q, '=');
2221         namelen = p - name;
2222         if (!namelen || p != q)
2223                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2224         vallen = 0;
2225         if (val == NULL) {
2226                 flags |= VUNSET;
2227         } else {
2228                 vallen = strlen(val);
2229         }
2230
2231         INT_OFF;
2232         nameeq = ckmalloc(namelen + vallen + 2);
2233         p = memcpy(nameeq, name, namelen) + namelen;
2234         if (val) {
2235                 *p++ = '=';
2236                 p = memcpy(p, val, vallen) + vallen;
2237         }
2238         *p = '\0';
2239         setvareq(nameeq, flags | VNOSAVE);
2240         INT_ON;
2241 }
2242
2243 static void FAST_FUNC
2244 setvar2(const char *name, const char *val)
2245 {
2246         setvar(name, val, 0);
2247 }
2248
2249 #if ENABLE_ASH_GETOPTS
2250 /*
2251  * Safe version of setvar, returns 1 on success 0 on failure.
2252  */
2253 static int
2254 setvarsafe(const char *name, const char *val, int flags)
2255 {
2256         int err;
2257         volatile int saveint;
2258         struct jmploc *volatile savehandler = exception_handler;
2259         struct jmploc jmploc;
2260
2261         SAVE_INT(saveint);
2262         if (setjmp(jmploc.loc))
2263                 err = 1;
2264         else {
2265                 exception_handler = &jmploc;
2266                 setvar(name, val, flags);
2267                 err = 0;
2268         }
2269         exception_handler = savehandler;
2270         RESTORE_INT(saveint);
2271         return err;
2272 }
2273 #endif
2274
2275 /*
2276  * Unset the specified variable.
2277  */
2278 static int
2279 unsetvar(const char *s)
2280 {
2281         struct var **vpp;
2282         struct var *vp;
2283         int retval;
2284
2285         vpp = findvar(hashvar(s), s);
2286         vp = *vpp;
2287         retval = 2;
2288         if (vp) {
2289                 int flags = vp->flags;
2290
2291                 retval = 1;
2292                 if (flags & VREADONLY)
2293                         goto out;
2294 #if ENABLE_ASH_RANDOM_SUPPORT
2295                 vp->flags &= ~VDYNAMIC;
2296 #endif
2297                 if (flags & VUNSET)
2298                         goto ok;
2299                 if ((flags & VSTRFIXED) == 0) {
2300                         INT_OFF;
2301                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2302                                 free((char*)vp->var_text);
2303                         *vpp = vp->next;
2304                         free(vp);
2305                         INT_ON;
2306                 } else {
2307                         setvar(s, 0, 0);
2308                         vp->flags &= ~VEXPORT;
2309                 }
2310  ok:
2311                 retval = 0;
2312         }
2313  out:
2314         return retval;
2315 }
2316
2317 /*
2318  * Process a linked list of variable assignments.
2319  */
2320 static void
2321 listsetvar(struct strlist *list_set_var, int flags)
2322 {
2323         struct strlist *lp = list_set_var;
2324
2325         if (!lp)
2326                 return;
2327         INT_OFF;
2328         do {
2329                 setvareq(lp->text, flags);
2330                 lp = lp->next;
2331         } while (lp);
2332         INT_ON;
2333 }
2334
2335 /*
2336  * Generate a list of variables satisfying the given conditions.
2337  */
2338 static char **
2339 listvars(int on, int off, char ***end)
2340 {
2341         struct var **vpp;
2342         struct var *vp;
2343         char **ep;
2344         int mask;
2345
2346         STARTSTACKSTR(ep);
2347         vpp = vartab;
2348         mask = on | off;
2349         do {
2350                 for (vp = *vpp; vp; vp = vp->next) {
2351                         if ((vp->flags & mask) == on) {
2352                                 if (ep == stackstrend())
2353                                         ep = growstackstr();
2354                                 *ep++ = (char*)vp->var_text;
2355                         }
2356                 }
2357         } while (++vpp < vartab + VTABSIZE);
2358         if (ep == stackstrend())
2359                 ep = growstackstr();
2360         if (end)
2361                 *end = ep;
2362         *ep++ = NULL;
2363         return grabstackstr(ep);
2364 }
2365
2366
2367 /* ============ Path search helper
2368  *
2369  * The variable path (passed by reference) should be set to the start
2370  * of the path before the first call; path_advance will update
2371  * this value as it proceeds.  Successive calls to path_advance will return
2372  * the possible path expansions in sequence.  If an option (indicated by
2373  * a percent sign) appears in the path entry then the global variable
2374  * pathopt will be set to point to it; otherwise pathopt will be set to
2375  * NULL.
2376  */
2377 static const char *pathopt;     /* set by path_advance */
2378
2379 static char *
2380 path_advance(const char **path, const char *name)
2381 {
2382         const char *p;
2383         char *q;
2384         const char *start;
2385         size_t len;
2386
2387         if (*path == NULL)
2388                 return NULL;
2389         start = *path;
2390         for (p = start; *p && *p != ':' && *p != '%'; p++)
2391                 continue;
2392         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2393         while (stackblocksize() < len)
2394                 growstackblock();
2395         q = stackblock();
2396         if (p != start) {
2397                 memcpy(q, start, p - start);
2398                 q += p - start;
2399                 *q++ = '/';
2400         }
2401         strcpy(q, name);
2402         pathopt = NULL;
2403         if (*p == '%') {
2404                 pathopt = ++p;
2405                 while (*p && *p != ':')
2406                         p++;
2407         }
2408         if (*p == ':')
2409                 *path = p + 1;
2410         else
2411                 *path = NULL;
2412         return stalloc(len);
2413 }
2414
2415
2416 /* ============ Prompt */
2417
2418 static smallint doprompt;                   /* if set, prompt the user */
2419 static smallint needprompt;                 /* true if interactive and at start of line */
2420
2421 #if ENABLE_FEATURE_EDITING
2422 static line_input_t *line_input_state;
2423 static const char *cmdedit_prompt;
2424 static void
2425 putprompt(const char *s)
2426 {
2427         if (ENABLE_ASH_EXPAND_PRMT) {
2428                 free((char*)cmdedit_prompt);
2429                 cmdedit_prompt = ckstrdup(s);
2430                 return;
2431         }
2432         cmdedit_prompt = s;
2433 }
2434 #else
2435 static void
2436 putprompt(const char *s)
2437 {
2438         out2str(s);
2439 }
2440 #endif
2441
2442 #if ENABLE_ASH_EXPAND_PRMT
2443 /* expandstr() needs parsing machinery, so it is far away ahead... */
2444 static const char *expandstr(const char *ps);
2445 #else
2446 #define expandstr(s) s
2447 #endif
2448
2449 static void
2450 setprompt_if(smallint do_set, int whichprompt)
2451 {
2452         const char *prompt;
2453         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2454
2455         if (!do_set)
2456                 return;
2457
2458         needprompt = 0;
2459
2460         switch (whichprompt) {
2461         case 1:
2462                 prompt = ps1val();
2463                 break;
2464         case 2:
2465                 prompt = ps2val();
2466                 break;
2467         default:                        /* 0 */
2468                 prompt = nullstr;
2469         }
2470 #if ENABLE_ASH_EXPAND_PRMT
2471         setstackmark(&smark);
2472         stalloc(stackblocksize());
2473 #endif
2474         putprompt(expandstr(prompt));
2475 #if ENABLE_ASH_EXPAND_PRMT
2476         popstackmark(&smark);
2477 #endif
2478 }
2479
2480
2481 /* ============ The cd and pwd commands */
2482
2483 #define CD_PHYSICAL 1
2484 #define CD_PRINT 2
2485
2486 static int
2487 cdopt(void)
2488 {
2489         int flags = 0;
2490         int i, j;
2491
2492         j = 'L';
2493         while ((i = nextopt("LP")) != '\0') {
2494                 if (i != j) {
2495                         flags ^= CD_PHYSICAL;
2496                         j = i;
2497                 }
2498         }
2499
2500         return flags;
2501 }
2502
2503 /*
2504  * Update curdir (the name of the current directory) in response to a
2505  * cd command.
2506  */
2507 static const char *
2508 updatepwd(const char *dir)
2509 {
2510         char *new;
2511         char *p;
2512         char *cdcomppath;
2513         const char *lim;
2514
2515         cdcomppath = ststrdup(dir);
2516         STARTSTACKSTR(new);
2517         if (*dir != '/') {
2518                 if (curdir == nullstr)
2519                         return 0;
2520                 new = stack_putstr(curdir, new);
2521         }
2522         new = makestrspace(strlen(dir) + 2, new);
2523         lim = (char *)stackblock() + 1;
2524         if (*dir != '/') {
2525                 if (new[-1] != '/')
2526                         USTPUTC('/', new);
2527                 if (new > lim && *lim == '/')
2528                         lim++;
2529         } else {
2530                 USTPUTC('/', new);
2531                 cdcomppath++;
2532                 if (dir[1] == '/' && dir[2] != '/') {
2533                         USTPUTC('/', new);
2534                         cdcomppath++;
2535                         lim++;
2536                 }
2537         }
2538         p = strtok(cdcomppath, "/");
2539         while (p) {
2540                 switch (*p) {
2541                 case '.':
2542                         if (p[1] == '.' && p[2] == '\0') {
2543                                 while (new > lim) {
2544                                         STUNPUTC(new);
2545                                         if (new[-1] == '/')
2546                                                 break;
2547                                 }
2548                                 break;
2549                         }
2550                         if (p[1] == '\0')
2551                                 break;
2552                         /* fall through */
2553                 default:
2554                         new = stack_putstr(p, new);
2555                         USTPUTC('/', new);
2556                 }
2557                 p = strtok(0, "/");
2558         }
2559         if (new > lim)
2560                 STUNPUTC(new);
2561         *new = 0;
2562         return stackblock();
2563 }
2564
2565 /*
2566  * Find out what the current directory is. If we already know the current
2567  * directory, this routine returns immediately.
2568  */
2569 static char *
2570 getpwd(void)
2571 {
2572         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2573         return dir ? dir : nullstr;
2574 }
2575
2576 static void
2577 setpwd(const char *val, int setold)
2578 {
2579         char *oldcur, *dir;
2580
2581         oldcur = dir = curdir;
2582
2583         if (setold) {
2584                 setvar("OLDPWD", oldcur, VEXPORT);
2585         }
2586         INT_OFF;
2587         if (physdir != nullstr) {
2588                 if (physdir != oldcur)
2589                         free(physdir);
2590                 physdir = nullstr;
2591         }
2592         if (oldcur == val || !val) {
2593                 char *s = getpwd();
2594                 physdir = s;
2595                 if (!val)
2596                         dir = s;
2597         } else
2598                 dir = ckstrdup(val);
2599         if (oldcur != dir && oldcur != nullstr) {
2600                 free(oldcur);
2601         }
2602         curdir = dir;
2603         INT_ON;
2604         setvar("PWD", dir, VEXPORT);
2605 }
2606
2607 static void hashcd(void);
2608
2609 /*
2610  * Actually do the chdir.  We also call hashcd to let the routines in exec.c
2611  * know that the current directory has changed.
2612  */
2613 static int
2614 docd(const char *dest, int flags)
2615 {
2616         const char *dir = NULL;
2617         int err;
2618
2619         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2620
2621         INT_OFF;
2622         if (!(flags & CD_PHYSICAL)) {
2623                 dir = updatepwd(dest);
2624                 if (dir)
2625                         dest = dir;
2626         }
2627         err = chdir(dest);
2628         if (err)
2629                 goto out;
2630         setpwd(dir, 1);
2631         hashcd();
2632  out:
2633         INT_ON;
2634         return err;
2635 }
2636
2637 static int FAST_FUNC
2638 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2639 {
2640         const char *dest;
2641         const char *path;
2642         const char *p;
2643         char c;
2644         struct stat statb;
2645         int flags;
2646
2647         flags = cdopt();
2648         dest = *argptr;
2649         if (!dest)
2650                 dest = bltinlookup("HOME");
2651         else if (LONE_DASH(dest)) {
2652                 dest = bltinlookup("OLDPWD");
2653                 flags |= CD_PRINT;
2654         }
2655         if (!dest)
2656                 dest = nullstr;
2657         if (*dest == '/')
2658                 goto step7;
2659         if (*dest == '.') {
2660                 c = dest[1];
2661  dotdot:
2662                 switch (c) {
2663                 case '\0':
2664                 case '/':
2665                         goto step6;
2666                 case '.':
2667                         c = dest[2];
2668                         if (c != '.')
2669                                 goto dotdot;
2670                 }
2671         }
2672         if (!*dest)
2673                 dest = ".";
2674         path = bltinlookup("CDPATH");
2675         if (!path) {
2676  step6:
2677  step7:
2678                 p = dest;
2679                 goto docd;
2680         }
2681         do {
2682                 c = *path;
2683                 p = path_advance(&path, dest);
2684                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2685                         if (c && c != ':')
2686                                 flags |= CD_PRINT;
2687  docd:
2688                         if (!docd(p, flags))
2689                                 goto out;
2690                         break;
2691                 }
2692         } while (path);
2693         ash_msg_and_raise_error("can't cd to %s", dest);
2694         /* NOTREACHED */
2695  out:
2696         if (flags & CD_PRINT)
2697                 out1fmt("%s\n", curdir);
2698         return 0;
2699 }
2700
2701 static int FAST_FUNC
2702 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2703 {
2704         int flags;
2705         const char *dir = curdir;
2706
2707         flags = cdopt();
2708         if (flags) {
2709                 if (physdir == nullstr)
2710                         setpwd(dir, 0);
2711                 dir = physdir;
2712         }
2713         out1fmt("%s\n", dir);
2714         return 0;
2715 }
2716
2717
2718 /* ============ ... */
2719
2720
2721 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2722
2723 /* Syntax classes */
2724 #define CWORD     0             /* character is nothing special */
2725 #define CNL       1             /* newline character */
2726 #define CBACK     2             /* a backslash character */
2727 #define CSQUOTE   3             /* single quote */
2728 #define CDQUOTE   4             /* double quote */
2729 #define CENDQUOTE 5             /* a terminating quote */
2730 #define CBQUOTE   6             /* backwards single quote */
2731 #define CVAR      7             /* a dollar sign */
2732 #define CENDVAR   8             /* a '}' character */
2733 #define CLP       9             /* a left paren in arithmetic */
2734 #define CRP      10             /* a right paren in arithmetic */
2735 #define CENDFILE 11             /* end of file */
2736 #define CCTL     12             /* like CWORD, except it must be escaped */
2737 #define CSPCL    13             /* these terminate a word */
2738 #define CIGN     14             /* character should be ignored */
2739
2740 #define PEOF     256
2741 #if ENABLE_ASH_ALIAS
2742 # define PEOA    257
2743 #endif
2744
2745 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2746
2747 #if ENABLE_SH_MATH_SUPPORT
2748 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2749 #else
2750 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2751 #endif
2752 static const uint16_t S_I_T[] = {
2753 #if ENABLE_ASH_ALIAS
2754         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2755 #endif
2756         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2757         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2758         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2759         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2760         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2761         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2762         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2763         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2764         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2765         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2766         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2767 #if !USE_SIT_FUNCTION
2768         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2769         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2770         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2771 #endif
2772 #undef SIT_ITEM
2773 };
2774 /* Constants below must match table above */
2775 enum {
2776 #if ENABLE_ASH_ALIAS
2777         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2778 #endif
2779         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2780         CNL_CNL_CNL_CNL                    , /*  2 */
2781         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2782         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2783         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2784         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2785         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2786         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2787         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2788         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2789         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2790         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2791         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2792         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2793 };
2794
2795 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2796  * caller must ensure proper cast on it if c is *char_ptr!
2797  */
2798 /* Values for syntax param */
2799 #define BASESYNTAX 0    /* not in quotes */
2800 #define DQSYNTAX   1    /* in double quotes */
2801 #define SQSYNTAX   2    /* in single quotes */
2802 #define ARISYNTAX  3    /* in arithmetic */
2803 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2804
2805 #if USE_SIT_FUNCTION
2806
2807 static int
2808 SIT(int c, int syntax)
2809 {
2810         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2811 # if ENABLE_ASH_ALIAS
2812         static const uint8_t syntax_index_table[] ALIGN1 = {
2813                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2814                 7, 8, 3, 3, 3, 3, 1, 1,         /* "()*-/:;<" */
2815                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2816                 11, 3                           /* "}~" */
2817         };
2818 # else
2819         static const uint8_t syntax_index_table[] ALIGN1 = {
2820                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2821                 6, 7, 2, 2, 2, 2, 0, 0,         /* "()*-/:;<" */
2822                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2823                 10, 2                           /* "}~" */
2824         };
2825 # endif
2826         const char *s;
2827         int indx;
2828
2829         if (c == PEOF)
2830                 return CENDFILE;
2831 # if ENABLE_ASH_ALIAS
2832         if (c == PEOA)
2833                 indx = 0;
2834         else
2835 # endif
2836         {
2837                 /* Cast is purely for paranoia here,
2838                  * just in case someone passed signed char to us */
2839                 if ((unsigned char)c >= CTL_FIRST
2840                  && (unsigned char)c <= CTL_LAST
2841                 ) {
2842                         return CCTL;
2843                 }
2844                 s = strchrnul(spec_symbls, c);
2845                 if (*s == '\0')
2846                         return CWORD;
2847                 indx = syntax_index_table[s - spec_symbls];
2848         }
2849         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2850 }
2851
2852 #else   /* !USE_SIT_FUNCTION */
2853
2854 static const uint8_t syntax_index_table[] = {
2855         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2856         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2857         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2858         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2859         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2860         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2861         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2862         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2863         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2864         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2865         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2866         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2867         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2868         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2869         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2870         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2871         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2872         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2873         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2874         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2875         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2876         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2877         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2878         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2879         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2880         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2881         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2882         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2883         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2884         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2885         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2886         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2887         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2888         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2889         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2890         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2891         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2892         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2893         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2894         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2895         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2896         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2897         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2898         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2899         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2900         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2901         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2902         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2903         /*  47  "/" */ CWORD_CCTL_CCTL_CWORD,
2904         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2905         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2906         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2907         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2908         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2909         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2910         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2911         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2912         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2913         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2914         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2915         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2916         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2917         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2918         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2919         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2920         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2921         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2922         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2923         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2924         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2925         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2926         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2927         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2928         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2929         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2930         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2931         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2935         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2936         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2938         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2939         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2940         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2941         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2942         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2943         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2948         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2949         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2950         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2953         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2956         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2957         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2958         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2959         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2960         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2961         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2962         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2963         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2964         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2965         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
2966         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
2967         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
2968         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
2969         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
2970         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
2971         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
2972         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
2973         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
2974         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
2975         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
2976         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
2977         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
2978         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
2979         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
2980         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
2981         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2982         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
2983         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
2984         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2985         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
2986         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
2987         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
2988         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
2989         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
2990         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
2991         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
2992         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2993         /* 137      */ CWORD_CWORD_CWORD_CWORD,
2994         /* 138      */ CWORD_CWORD_CWORD_CWORD,
2995         /* 139      */ CWORD_CWORD_CWORD_CWORD,
2996         /* 140      */ CWORD_CWORD_CWORD_CWORD,
2997         /* 141      */ CWORD_CWORD_CWORD_CWORD,
2998         /* 142      */ CWORD_CWORD_CWORD_CWORD,
2999         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3000         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3001         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3002         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3003         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3004         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3005         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3006         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3007         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3008         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3009         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3010         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3011         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3012         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3013         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3014         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3015         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3016         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3017         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3018         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3019         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3020         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3021         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3022         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3023         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3024         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3025         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3026         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3027         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3112         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3113 # if ENABLE_ASH_ALIAS
3114         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3115 # endif
3116 };
3117
3118 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3119
3120 #endif  /* !USE_SIT_FUNCTION */
3121
3122
3123 /* ============ Alias handling */
3124
3125 #if ENABLE_ASH_ALIAS
3126
3127 #define ALIASINUSE 1
3128 #define ALIASDEAD  2
3129
3130 struct alias {
3131         struct alias *next;
3132         char *name;
3133         char *val;
3134         int flag;
3135 };
3136
3137
3138 static struct alias **atab; // [ATABSIZE];
3139 #define INIT_G_alias() do { \
3140         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3141 } while (0)
3142
3143
3144 static struct alias **
3145 __lookupalias(const char *name) {
3146         unsigned int hashval;
3147         struct alias **app;
3148         const char *p;
3149         unsigned int ch;
3150
3151         p = name;
3152
3153         ch = (unsigned char)*p;
3154         hashval = ch << 4;
3155         while (ch) {
3156                 hashval += ch;
3157                 ch = (unsigned char)*++p;
3158         }
3159         app = &atab[hashval % ATABSIZE];
3160
3161         for (; *app; app = &(*app)->next) {
3162                 if (strcmp(name, (*app)->name) == 0) {
3163                         break;
3164                 }
3165         }
3166
3167         return app;
3168 }
3169
3170 static struct alias *
3171 lookupalias(const char *name, int check)
3172 {
3173         struct alias *ap = *__lookupalias(name);
3174
3175         if (check && ap && (ap->flag & ALIASINUSE))
3176                 return NULL;
3177         return ap;
3178 }
3179
3180 static struct alias *
3181 freealias(struct alias *ap)
3182 {
3183         struct alias *next;
3184
3185         if (ap->flag & ALIASINUSE) {
3186                 ap->flag |= ALIASDEAD;
3187                 return ap;
3188         }
3189
3190         next = ap->next;
3191         free(ap->name);
3192         free(ap->val);
3193         free(ap);
3194         return next;
3195 }
3196
3197 static void
3198 setalias(const char *name, const char *val)
3199 {
3200         struct alias *ap, **app;
3201
3202         app = __lookupalias(name);
3203         ap = *app;
3204         INT_OFF;
3205         if (ap) {
3206                 if (!(ap->flag & ALIASINUSE)) {
3207                         free(ap->val);
3208                 }
3209                 ap->val = ckstrdup(val);
3210                 ap->flag &= ~ALIASDEAD;
3211         } else {
3212                 /* not found */
3213                 ap = ckzalloc(sizeof(struct alias));
3214                 ap->name = ckstrdup(name);
3215                 ap->val = ckstrdup(val);
3216                 /*ap->flag = 0; - ckzalloc did it */
3217                 /*ap->next = NULL;*/
3218                 *app = ap;
3219         }
3220         INT_ON;
3221 }
3222
3223 static int
3224 unalias(const char *name)
3225 {
3226         struct alias **app;
3227
3228         app = __lookupalias(name);
3229
3230         if (*app) {
3231                 INT_OFF;
3232                 *app = freealias(*app);
3233                 INT_ON;
3234                 return 0;
3235         }
3236
3237         return 1;
3238 }
3239
3240 static void
3241 rmaliases(void)
3242 {
3243         struct alias *ap, **app;
3244         int i;
3245
3246         INT_OFF;
3247         for (i = 0; i < ATABSIZE; i++) {
3248                 app = &atab[i];
3249                 for (ap = *app; ap; ap = *app) {
3250                         *app = freealias(*app);
3251                         if (ap == *app) {
3252                                 app = &ap->next;
3253                         }
3254                 }
3255         }
3256         INT_ON;
3257 }
3258
3259 static void
3260 printalias(const struct alias *ap)
3261 {
3262         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3263 }
3264
3265 /*
3266  * TODO - sort output
3267  */
3268 static int FAST_FUNC
3269 aliascmd(int argc UNUSED_PARAM, char **argv)
3270 {
3271         char *n, *v;
3272         int ret = 0;
3273         struct alias *ap;
3274
3275         if (!argv[1]) {
3276                 int i;
3277
3278                 for (i = 0; i < ATABSIZE; i++) {
3279                         for (ap = atab[i]; ap; ap = ap->next) {
3280                                 printalias(ap);
3281                         }
3282                 }
3283                 return 0;
3284         }
3285         while ((n = *++argv) != NULL) {
3286                 v = strchr(n+1, '=');
3287                 if (v == NULL) { /* n+1: funny ksh stuff */
3288                         ap = *__lookupalias(n);
3289                         if (ap == NULL) {
3290                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3291                                 ret = 1;
3292                         } else
3293                                 printalias(ap);
3294                 } else {
3295                         *v++ = '\0';
3296                         setalias(n, v);
3297                 }
3298         }
3299
3300         return ret;
3301 }
3302
3303 static int FAST_FUNC
3304 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3305 {
3306         int i;
3307
3308         while ((i = nextopt("a")) != '\0') {
3309                 if (i == 'a') {
3310                         rmaliases();
3311                         return 0;
3312                 }
3313         }
3314         for (i = 0; *argptr; argptr++) {
3315                 if (unalias(*argptr)) {
3316                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3317                         i = 1;
3318                 }
3319         }
3320
3321         return i;
3322 }
3323
3324 #endif /* ASH_ALIAS */
3325
3326
3327 /* ============ jobs.c */
3328
3329 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3330 #define FORK_FG    0
3331 #define FORK_BG    1
3332 #define FORK_NOJOB 2
3333
3334 /* mode flags for showjob(s) */
3335 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3336 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3337 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3338
3339 /*
3340  * A job structure contains information about a job.  A job is either a
3341  * single process or a set of processes contained in a pipeline.  In the
3342  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3343  * array of pids.
3344  */
3345 struct procstat {
3346         pid_t   ps_pid;         /* process id */
3347         int     ps_status;      /* last process status from wait() */
3348         char    *ps_cmd;        /* text of command being run */
3349 };
3350
3351 struct job {
3352         struct procstat ps0;    /* status of process */
3353         struct procstat *ps;    /* status or processes when more than one */
3354 #if JOBS
3355         int stopstatus;         /* status of a stopped job */
3356 #endif
3357         uint32_t
3358                 nprocs: 16,     /* number of processes */
3359                 state: 8,
3360 #define JOBRUNNING      0       /* at least one proc running */
3361 #define JOBSTOPPED      1       /* all procs are stopped */
3362 #define JOBDONE         2       /* all procs are completed */
3363 #if JOBS
3364                 sigint: 1,      /* job was killed by SIGINT */
3365                 jobctl: 1,      /* job running under job control */
3366 #endif
3367                 waited: 1,      /* true if this entry has been waited for */
3368                 used: 1,        /* true if this entry is in used */
3369                 changed: 1;     /* true if status has changed */
3370         struct job *prev_job;   /* previous job */
3371 };
3372
3373 static struct job *makejob(/*union node *,*/ int);
3374 static int forkshell(struct job *, union node *, int);
3375 static int waitforjob(struct job *);
3376
3377 #if !JOBS
3378 enum { doing_jobctl = 0 };
3379 #define setjobctl(on) do {} while (0)
3380 #else
3381 static smallint doing_jobctl; //references:8
3382 static void setjobctl(int);
3383 #endif
3384
3385 /*
3386  * Ignore a signal.
3387  */
3388 static void
3389 ignoresig(int signo)
3390 {
3391         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3392         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3393                 /* No, need to do it */
3394                 signal(signo, SIG_IGN);
3395         }
3396         sigmode[signo - 1] = S_HARD_IGN;
3397 }
3398
3399 /*
3400  * Only one usage site - in setsignal()
3401  */
3402 static void
3403 signal_handler(int signo)
3404 {
3405         gotsig[signo - 1] = 1;
3406
3407         if (signo == SIGINT && !trap[SIGINT]) {
3408                 if (!suppress_int) {
3409                         pending_sig = 0;
3410                         raise_interrupt(); /* does not return */
3411                 }
3412                 pending_int = 1;
3413         } else {
3414                 pending_sig = signo;
3415         }
3416 }
3417
3418 /*
3419  * Set the signal handler for the specified signal.  The routine figures
3420  * out what it should be set to.
3421  */
3422 static void
3423 setsignal(int signo)
3424 {
3425         char *t;
3426         char cur_act, new_act;
3427         struct sigaction act;
3428
3429         t = trap[signo];
3430         new_act = S_DFL;
3431         if (t != NULL) { /* trap for this sig is set */
3432                 new_act = S_CATCH;
3433                 if (t[0] == '\0') /* trap is "": ignore this sig */
3434                         new_act = S_IGN;
3435         }
3436
3437         if (rootshell && new_act == S_DFL) {
3438                 switch (signo) {
3439                 case SIGINT:
3440                         if (iflag || minusc || sflag == 0)
3441                                 new_act = S_CATCH;
3442                         break;
3443                 case SIGQUIT:
3444 #if DEBUG
3445                         if (debug)
3446                                 break;
3447 #endif
3448                         /* man bash:
3449                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3450                          * commands run by bash have signal handlers
3451                          * set to the values inherited by the shell
3452                          * from its parent". */
3453                         new_act = S_IGN;
3454                         break;
3455                 case SIGTERM:
3456                         if (iflag)
3457                                 new_act = S_IGN;
3458                         break;
3459 #if JOBS
3460                 case SIGTSTP:
3461                 case SIGTTOU:
3462                         if (mflag)
3463                                 new_act = S_IGN;
3464                         break;
3465 #endif
3466                 }
3467         }
3468 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3469 //whereas we have to restore it to what shell got on entry
3470 //from the parent. See comment above
3471
3472         t = &sigmode[signo - 1];
3473         cur_act = *t;
3474         if (cur_act == 0) {
3475                 /* current setting is not yet known */
3476                 if (sigaction(signo, NULL, &act)) {
3477                         /* pretend it worked; maybe we should give a warning,
3478                          * but other shells don't. We don't alter sigmode,
3479                          * so we retry every time.
3480                          * btw, in Linux it never fails. --vda */
3481                         return;
3482                 }
3483                 if (act.sa_handler == SIG_IGN) {
3484                         cur_act = S_HARD_IGN;
3485                         if (mflag
3486                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3487                         ) {
3488                                 cur_act = S_IGN;   /* don't hard ignore these */
3489                         }
3490                 }
3491         }
3492         if (cur_act == S_HARD_IGN || cur_act == new_act)
3493                 return;
3494
3495         act.sa_handler = SIG_DFL;
3496         switch (new_act) {
3497         case S_CATCH:
3498                 act.sa_handler = signal_handler;
3499                 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3500                 sigfillset(&act.sa_mask); /* ditto */
3501                 break;
3502         case S_IGN:
3503                 act.sa_handler = SIG_IGN;
3504                 break;
3505         }
3506         sigaction_set(signo, &act);
3507
3508         *t = new_act;
3509 }
3510
3511 /* mode flags for set_curjob */
3512 #define CUR_DELETE 2
3513 #define CUR_RUNNING 1
3514 #define CUR_STOPPED 0
3515
3516 /* mode flags for dowait */
3517 #define DOWAIT_NONBLOCK WNOHANG
3518 #define DOWAIT_BLOCK    0
3519
3520 #if JOBS
3521 /* pgrp of shell on invocation */
3522 static int initialpgrp; //references:2
3523 static int ttyfd = -1; //5
3524 #endif
3525 /* array of jobs */
3526 static struct job *jobtab; //5
3527 /* size of array */
3528 static unsigned njobs; //4
3529 /* current job */
3530 static struct job *curjob; //lots
3531 /* number of presumed living untracked jobs */
3532 static int jobless; //4
3533
3534 static void
3535 set_curjob(struct job *jp, unsigned mode)
3536 {
3537         struct job *jp1;
3538         struct job **jpp, **curp;
3539
3540         /* first remove from list */
3541         jpp = curp = &curjob;
3542         while (1) {
3543                 jp1 = *jpp;
3544                 if (jp1 == jp)
3545                         break;
3546                 jpp = &jp1->prev_job;
3547         }
3548         *jpp = jp1->prev_job;
3549
3550         /* Then re-insert in correct position */
3551         jpp = curp;
3552         switch (mode) {
3553         default:
3554 #if DEBUG
3555                 abort();
3556 #endif
3557         case CUR_DELETE:
3558                 /* job being deleted */
3559                 break;
3560         case CUR_RUNNING:
3561                 /* newly created job or backgrounded job,
3562                    put after all stopped jobs. */
3563                 while (1) {
3564                         jp1 = *jpp;
3565 #if JOBS
3566                         if (!jp1 || jp1->state != JOBSTOPPED)
3567 #endif
3568                                 break;
3569                         jpp = &jp1->prev_job;
3570                 }
3571                 /* FALLTHROUGH */
3572 #if JOBS
3573         case CUR_STOPPED:
3574 #endif
3575                 /* newly stopped job - becomes curjob */
3576                 jp->prev_job = *jpp;
3577                 *jpp = jp;
3578                 break;
3579         }
3580 }
3581
3582 #if JOBS || DEBUG
3583 static int
3584 jobno(const struct job *jp)
3585 {
3586         return jp - jobtab + 1;
3587 }
3588 #endif
3589
3590 /*
3591  * Convert a job name to a job structure.
3592  */
3593 #if !JOBS
3594 #define getjob(name, getctl) getjob(name)
3595 #endif
3596 static struct job *
3597 getjob(const char *name, int getctl)
3598 {
3599         struct job *jp;
3600         struct job *found;
3601         const char *err_msg = "%s: no such job";
3602         unsigned num;
3603         int c;
3604         const char *p;
3605         char *(*match)(const char *, const char *);
3606
3607         jp = curjob;
3608         p = name;
3609         if (!p)
3610                 goto currentjob;
3611
3612         if (*p != '%')
3613                 goto err;
3614
3615         c = *++p;
3616         if (!c)
3617                 goto currentjob;
3618
3619         if (!p[1]) {
3620                 if (c == '+' || c == '%') {
3621  currentjob:
3622                         err_msg = "No current job";
3623                         goto check;
3624                 }
3625                 if (c == '-') {
3626                         if (jp)
3627                                 jp = jp->prev_job;
3628                         err_msg = "No previous job";
3629  check:
3630                         if (!jp)
3631                                 goto err;
3632                         goto gotit;
3633                 }
3634         }
3635
3636         if (is_number(p)) {
3637                 num = atoi(p);
3638                 if (num < njobs) {
3639                         jp = jobtab + num - 1;
3640                         if (jp->used)
3641                                 goto gotit;
3642                         goto err;
3643                 }
3644         }
3645
3646         match = prefix;
3647         if (*p == '?') {
3648                 match = strstr;
3649                 p++;
3650         }
3651
3652         found = NULL;
3653         while (jp) {
3654                 if (match(jp->ps[0].ps_cmd, p)) {
3655                         if (found)
3656                                 goto err;
3657                         found = jp;
3658                         err_msg = "%s: ambiguous";
3659                 }
3660                 jp = jp->prev_job;
3661         }
3662         if (!found)
3663                 goto err;
3664         jp = found;
3665
3666  gotit:
3667 #if JOBS
3668         err_msg = "job %s not created under job control";
3669         if (getctl && jp->jobctl == 0)
3670                 goto err;
3671 #endif
3672         return jp;
3673  err:
3674         ash_msg_and_raise_error(err_msg, name);
3675 }
3676
3677 /*
3678  * Mark a job structure as unused.
3679  */
3680 static void
3681 freejob(struct job *jp)
3682 {
3683         struct procstat *ps;
3684         int i;
3685
3686         INT_OFF;
3687         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3688                 if (ps->ps_cmd != nullstr)
3689                         free(ps->ps_cmd);
3690         }
3691         if (jp->ps != &jp->ps0)
3692                 free(jp->ps);
3693         jp->used = 0;
3694         set_curjob(jp, CUR_DELETE);
3695         INT_ON;
3696 }
3697
3698 #if JOBS
3699 static void
3700 xtcsetpgrp(int fd, pid_t pgrp)
3701 {
3702         if (tcsetpgrp(fd, pgrp))
3703                 ash_msg_and_raise_error("can't set tty process group (%m)");
3704 }
3705
3706 /*
3707  * Turn job control on and off.
3708  *
3709  * Note:  This code assumes that the third arg to ioctl is a character
3710  * pointer, which is true on Berkeley systems but not System V.  Since
3711  * System V doesn't have job control yet, this isn't a problem now.
3712  *
3713  * Called with interrupts off.
3714  */
3715 static void
3716 setjobctl(int on)
3717 {
3718         int fd;
3719         int pgrp;
3720
3721         if (on == doing_jobctl || rootshell == 0)
3722                 return;
3723         if (on) {
3724                 int ofd;
3725                 ofd = fd = open(_PATH_TTY, O_RDWR);
3726                 if (fd < 0) {
3727         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3728          * That sometimes helps to acquire controlling tty.
3729          * Obviously, a workaround for bugs when someone
3730          * failed to provide a controlling tty to bash! :) */
3731                         fd = 2;
3732                         while (!isatty(fd))
3733                                 if (--fd < 0)
3734                                         goto out;
3735                 }
3736                 fd = fcntl(fd, F_DUPFD, 10);
3737                 if (ofd >= 0)
3738                         close(ofd);
3739                 if (fd < 0)
3740                         goto out;
3741                 /* fd is a tty at this point */
3742                 close_on_exec_on(fd);
3743                 while (1) { /* while we are in the background */
3744                         pgrp = tcgetpgrp(fd);
3745                         if (pgrp < 0) {
3746  out:
3747                                 ash_msg("can't access tty; job control turned off");
3748                                 mflag = on = 0;
3749                                 goto close;
3750                         }
3751                         if (pgrp == getpgrp())
3752                                 break;
3753                         killpg(0, SIGTTIN);
3754                 }
3755                 initialpgrp = pgrp;
3756
3757                 setsignal(SIGTSTP);
3758                 setsignal(SIGTTOU);
3759                 setsignal(SIGTTIN);
3760                 pgrp = rootpid;
3761                 setpgid(0, pgrp);
3762                 xtcsetpgrp(fd, pgrp);
3763         } else {
3764                 /* turning job control off */
3765                 fd = ttyfd;
3766                 pgrp = initialpgrp;
3767                 /* was xtcsetpgrp, but this can make exiting ash
3768                  * loop forever if pty is already deleted */
3769                 tcsetpgrp(fd, pgrp);
3770                 setpgid(0, pgrp);
3771                 setsignal(SIGTSTP);
3772                 setsignal(SIGTTOU);
3773                 setsignal(SIGTTIN);
3774  close:
3775                 if (fd >= 0)
3776                         close(fd);
3777                 fd = -1;
3778         }
3779         ttyfd = fd;
3780         doing_jobctl = on;
3781 }
3782
3783 static int FAST_FUNC
3784 killcmd(int argc, char **argv)
3785 {
3786         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3787                 int i = 1;
3788                 do {
3789                         if (argv[i][0] == '%') {
3790                                 /*
3791                                  * "kill %N" - job kill
3792                                  * Converting to pgrp / pid kill
3793                                  */
3794                                 struct job *jp;
3795                                 char *dst;
3796                                 int j, n;
3797
3798                                 jp = getjob(argv[i], 0);
3799                                 /*
3800                                  * In jobs started under job control, we signal
3801                                  * entire process group by kill -PGRP_ID.
3802                                  * This happens, f.e., in interactive shell.
3803                                  *
3804                                  * Otherwise, we signal each child via
3805                                  * kill PID1 PID2 PID3.
3806                                  * Testcases:
3807                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3808                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3809                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3810                                  */
3811                                 n = jp->nprocs; /* can't be 0 (I hope) */
3812                                 if (jp->jobctl)
3813                                         n = 1;
3814                                 dst = alloca(n * sizeof(int)*4);
3815                                 argv[i] = dst;
3816                                 for (j = 0; j < n; j++) {
3817                                         struct procstat *ps = &jp->ps[j];
3818                                         /* Skip non-running and not-stopped members
3819                                          * (i.e. dead members) of the job
3820                                          */
3821                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3822                                                 continue;
3823                                         /*
3824                                          * kill_main has matching code to expect
3825                                          * leading space. Needed to not confuse
3826                                          * negative pids with "kill -SIGNAL_NO" syntax
3827                                          */
3828                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3829                                 }
3830                                 *dst = '\0';
3831                         }
3832                 } while (argv[++i]);
3833         }
3834         return kill_main(argc, argv);
3835 }
3836
3837 static void
3838 showpipe(struct job *jp /*, FILE *out*/)
3839 {
3840         struct procstat *ps;
3841         struct procstat *psend;
3842
3843         psend = jp->ps + jp->nprocs;
3844         for (ps = jp->ps + 1; ps < psend; ps++)
3845                 printf(" | %s", ps->ps_cmd);
3846         outcslow('\n', stdout);
3847         flush_stdout_stderr();
3848 }
3849
3850
3851 static int
3852 restartjob(struct job *jp, int mode)
3853 {
3854         struct procstat *ps;
3855         int i;
3856         int status;
3857         pid_t pgid;
3858
3859         INT_OFF;
3860         if (jp->state == JOBDONE)
3861                 goto out;
3862         jp->state = JOBRUNNING;
3863         pgid = jp->ps[0].ps_pid;
3864         if (mode == FORK_FG)
3865                 xtcsetpgrp(ttyfd, pgid);
3866         killpg(pgid, SIGCONT);
3867         ps = jp->ps;
3868         i = jp->nprocs;
3869         do {
3870                 if (WIFSTOPPED(ps->ps_status)) {
3871                         ps->ps_status = -1;
3872                 }
3873                 ps++;
3874         } while (--i);
3875  out:
3876         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3877         INT_ON;
3878         return status;
3879 }
3880
3881 static int FAST_FUNC
3882 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3883 {
3884         struct job *jp;
3885         int mode;
3886         int retval;
3887
3888         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3889         nextopt(nullstr);
3890         argv = argptr;
3891         do {
3892                 jp = getjob(*argv, 1);
3893                 if (mode == FORK_BG) {
3894                         set_curjob(jp, CUR_RUNNING);
3895                         printf("[%d] ", jobno(jp));
3896                 }
3897                 out1str(jp->ps[0].ps_cmd);
3898                 showpipe(jp /*, stdout*/);
3899                 retval = restartjob(jp, mode);
3900         } while (*argv && *++argv);
3901         return retval;
3902 }
3903 #endif
3904
3905 static int
3906 sprint_status(char *s, int status, int sigonly)
3907 {
3908         int col;
3909         int st;
3910
3911         col = 0;
3912         if (!WIFEXITED(status)) {
3913 #if JOBS
3914                 if (WIFSTOPPED(status))
3915                         st = WSTOPSIG(status);
3916                 else
3917 #endif
3918                         st = WTERMSIG(status);
3919                 if (sigonly) {
3920                         if (st == SIGINT || st == SIGPIPE)
3921                                 goto out;
3922 #if JOBS
3923                         if (WIFSTOPPED(status))
3924                                 goto out;
3925 #endif
3926                 }
3927                 st &= 0x7f;
3928 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
3929                 col = fmtstr(s, 32, strsignal(st));
3930                 if (WCOREDUMP(status)) {
3931                         col += fmtstr(s + col, 16, " (core dumped)");
3932                 }
3933         } else if (!sigonly) {
3934                 st = WEXITSTATUS(status);
3935                 if (st)
3936                         col = fmtstr(s, 16, "Done(%d)", st);
3937                 else
3938                         col = fmtstr(s, 16, "Done");
3939         }
3940  out:
3941         return col;
3942 }
3943
3944 static int
3945 dowait(int wait_flags, struct job *job)
3946 {
3947         int pid;
3948         int status;
3949         struct job *jp;
3950         struct job *thisjob;
3951         int state;
3952
3953         TRACE(("dowait(0x%x) called\n", wait_flags));
3954
3955         /* Do a wait system call. If job control is compiled in, we accept
3956          * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3957          * NB: _not_ safe_waitpid, we need to detect EINTR */
3958         if (doing_jobctl)
3959                 wait_flags |= WUNTRACED;
3960         pid = waitpid(-1, &status, wait_flags);
3961         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
3962                                 pid, status, errno, strerror(errno)));
3963         if (pid <= 0)
3964                 return pid;
3965
3966         INT_OFF;
3967         thisjob = NULL;
3968         for (jp = curjob; jp; jp = jp->prev_job) {
3969                 struct procstat *ps;
3970                 struct procstat *psend;
3971                 if (jp->state == JOBDONE)
3972                         continue;
3973                 state = JOBDONE;
3974                 ps = jp->ps;
3975                 psend = ps + jp->nprocs;
3976                 do {
3977                         if (ps->ps_pid == pid) {
3978                                 TRACE(("Job %d: changing status of proc %d "
3979                                         "from 0x%x to 0x%x\n",
3980                                         jobno(jp), pid, ps->ps_status, status));
3981                                 ps->ps_status = status;
3982                                 thisjob = jp;
3983                         }
3984                         if (ps->ps_status == -1)
3985                                 state = JOBRUNNING;
3986 #if JOBS
3987                         if (state == JOBRUNNING)
3988                                 continue;
3989                         if (WIFSTOPPED(ps->ps_status)) {
3990                                 jp->stopstatus = ps->ps_status;
3991                                 state = JOBSTOPPED;
3992                         }
3993 #endif
3994                 } while (++ps < psend);
3995                 if (thisjob)
3996                         goto gotjob;
3997         }
3998 #if JOBS
3999         if (!WIFSTOPPED(status))
4000 #endif
4001                 jobless--;
4002         goto out;
4003
4004  gotjob:
4005         if (state != JOBRUNNING) {
4006                 thisjob->changed = 1;
4007
4008                 if (thisjob->state != state) {
4009                         TRACE(("Job %d: changing state from %d to %d\n",
4010                                 jobno(thisjob), thisjob->state, state));
4011                         thisjob->state = state;
4012 #if JOBS
4013                         if (state == JOBSTOPPED) {
4014                                 set_curjob(thisjob, CUR_STOPPED);
4015                         }
4016 #endif
4017                 }
4018         }
4019
4020  out:
4021         INT_ON;
4022
4023         if (thisjob && thisjob == job) {
4024                 char s[48 + 1];
4025                 int len;
4026
4027                 len = sprint_status(s, status, 1);
4028                 if (len) {
4029                         s[len] = '\n';
4030                         s[len + 1] = '\0';
4031                         out2str(s);
4032                 }
4033         }
4034         return pid;
4035 }
4036
4037 static int
4038 blocking_wait_with_raise_on_sig(void)
4039 {
4040         pid_t pid = dowait(DOWAIT_BLOCK, NULL);
4041         if (pid <= 0 && pending_sig)
4042                 raise_exception(EXSIG);
4043         return pid;
4044 }
4045
4046 #if JOBS
4047 static void
4048 showjob(FILE *out, struct job *jp, int mode)
4049 {
4050         struct procstat *ps;
4051         struct procstat *psend;
4052         int col;
4053         int indent_col;
4054         char s[80];
4055
4056         ps = jp->ps;
4057
4058         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4059                 /* just output process (group) id of pipeline */
4060                 fprintf(out, "%d\n", ps->ps_pid);
4061                 return;
4062         }
4063
4064         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4065         indent_col = col;
4066
4067         if (jp == curjob)
4068                 s[col - 3] = '+';
4069         else if (curjob && jp == curjob->prev_job)
4070                 s[col - 3] = '-';
4071
4072         if (mode & SHOW_PIDS)
4073                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4074
4075         psend = ps + jp->nprocs;
4076
4077         if (jp->state == JOBRUNNING) {
4078                 strcpy(s + col, "Running");
4079                 col += sizeof("Running") - 1;
4080         } else {
4081                 int status = psend[-1].ps_status;
4082                 if (jp->state == JOBSTOPPED)
4083                         status = jp->stopstatus;
4084                 col += sprint_status(s + col, status, 0);
4085         }
4086         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4087
4088         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4089          * or prints several "PID             | <cmdN>" lines,
4090          * depending on SHOW_PIDS bit.
4091          * We do not print status of individual processes
4092          * between PID and <cmdN>. bash does it, but not very well:
4093          * first line shows overall job status, not process status,
4094          * making it impossible to know 1st process status.
4095          */
4096         goto start;
4097         do {
4098                 /* for each process */
4099                 s[0] = '\0';
4100                 col = 33;
4101                 if (mode & SHOW_PIDS)
4102                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4103  start:
4104                 fprintf(out, "%s%*c%s%s",
4105                                 s,
4106                                 33 - col >= 0 ? 33 - col : 0, ' ',
4107                                 ps == jp->ps ? "" : "| ",
4108                                 ps->ps_cmd
4109                 );
4110         } while (++ps != psend);
4111         outcslow('\n', out);
4112
4113         jp->changed = 0;
4114
4115         if (jp->state == JOBDONE) {
4116                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4117                 freejob(jp);
4118         }
4119 }
4120
4121 /*
4122  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4123  * statuses have changed since the last call to showjobs.
4124  */
4125 static void
4126 showjobs(FILE *out, int mode)
4127 {
4128         struct job *jp;
4129
4130         TRACE(("showjobs(0x%x) called\n", mode));
4131
4132         /* Handle all finished jobs */
4133         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4134                 continue;
4135
4136         for (jp = curjob; jp; jp = jp->prev_job) {
4137                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4138                         showjob(out, jp, mode);
4139                 }
4140         }
4141 }
4142
4143 static int FAST_FUNC
4144 jobscmd(int argc UNUSED_PARAM, char **argv)
4145 {
4146         int mode, m;
4147
4148         mode = 0;
4149         while ((m = nextopt("lp")) != '\0') {
4150                 if (m == 'l')
4151                         mode |= SHOW_PIDS;
4152                 else
4153                         mode |= SHOW_ONLY_PGID;
4154         }
4155
4156         argv = argptr;
4157         if (*argv) {
4158                 do
4159                         showjob(stdout, getjob(*argv, 0), mode);
4160                 while (*++argv);
4161         } else {
4162                 showjobs(stdout, mode);
4163         }
4164
4165         return 0;
4166 }
4167 #endif /* JOBS */
4168
4169 /* Called only on finished or stopped jobs (no members are running) */
4170 static int
4171 getstatus(struct job *job)
4172 {
4173         int status;
4174         int retval;
4175         struct procstat *ps;
4176
4177         /* Fetch last member's status */
4178         ps = job->ps + job->nprocs - 1;
4179         status = ps->ps_status;
4180         if (pipefail) {
4181                 /* "set -o pipefail" mode: use last _nonzero_ status */
4182                 while (status == 0 && --ps >= job->ps)
4183                         status = ps->ps_status;
4184         }
4185
4186         retval = WEXITSTATUS(status);
4187         if (!WIFEXITED(status)) {
4188 #if JOBS
4189                 retval = WSTOPSIG(status);
4190                 if (!WIFSTOPPED(status))
4191 #endif
4192                 {
4193                         /* XXX: limits number of signals */
4194                         retval = WTERMSIG(status);
4195 #if JOBS
4196                         if (retval == SIGINT)
4197                                 job->sigint = 1;
4198 #endif
4199                 }
4200                 retval += 128;
4201         }
4202         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4203                 jobno(job), job->nprocs, status, retval));
4204         return retval;
4205 }
4206
4207 static int FAST_FUNC
4208 waitcmd(int argc UNUSED_PARAM, char **argv)
4209 {
4210         struct job *job;
4211         int retval;
4212         struct job *jp;
4213
4214         if (pending_sig)
4215                 raise_exception(EXSIG);
4216
4217         nextopt(nullstr);
4218         retval = 0;
4219
4220         argv = argptr;
4221         if (!*argv) {
4222                 /* wait for all jobs */
4223                 for (;;) {
4224                         jp = curjob;
4225                         while (1) {
4226                                 if (!jp) /* no running procs */
4227                                         goto ret;
4228                                 if (jp->state == JOBRUNNING)
4229                                         break;
4230                                 jp->waited = 1;
4231                                 jp = jp->prev_job;
4232                         }
4233                         blocking_wait_with_raise_on_sig();
4234         /* man bash:
4235          * "When bash is waiting for an asynchronous command via
4236          * the wait builtin, the reception of a signal for which a trap
4237          * has been set will cause the wait builtin to return immediately
4238          * with an exit status greater than 128, immediately after which
4239          * the trap is executed."
4240          *
4241          * blocking_wait_with_raise_on_sig raises signal handlers
4242          * if it gets no pid (pid < 0). However,
4243          * if child sends us a signal *and immediately exits*,
4244          * blocking_wait_with_raise_on_sig gets pid > 0
4245          * and does not handle pending_sig. Check this case: */
4246                         if (pending_sig)
4247                                 raise_exception(EXSIG);
4248                 }
4249         }
4250
4251         retval = 127;
4252         do {
4253                 if (**argv != '%') {
4254                         pid_t pid = number(*argv);
4255                         job = curjob;
4256                         while (1) {
4257                                 if (!job)
4258                                         goto repeat;
4259                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4260                                         break;
4261                                 job = job->prev_job;
4262                         }
4263                 } else {
4264                         job = getjob(*argv, 0);
4265                 }
4266                 /* loop until process terminated or stopped */
4267                 while (job->state == JOBRUNNING)
4268                         blocking_wait_with_raise_on_sig();
4269                 job->waited = 1;
4270                 retval = getstatus(job);
4271  repeat: ;
4272         } while (*++argv);
4273
4274  ret:
4275         return retval;
4276 }
4277
4278 static struct job *
4279 growjobtab(void)
4280 {
4281         size_t len;
4282         ptrdiff_t offset;
4283         struct job *jp, *jq;
4284
4285         len = njobs * sizeof(*jp);
4286         jq = jobtab;
4287         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4288
4289         offset = (char *)jp - (char *)jq;
4290         if (offset) {
4291                 /* Relocate pointers */
4292                 size_t l = len;
4293
4294                 jq = (struct job *)((char *)jq + l);
4295                 while (l) {
4296                         l -= sizeof(*jp);
4297                         jq--;
4298 #define joff(p) ((struct job *)((char *)(p) + l))
4299 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4300                         if (joff(jp)->ps == &jq->ps0)
4301                                 jmove(joff(jp)->ps);
4302                         if (joff(jp)->prev_job)
4303                                 jmove(joff(jp)->prev_job);
4304                 }
4305                 if (curjob)
4306                         jmove(curjob);
4307 #undef joff
4308 #undef jmove
4309         }
4310
4311         njobs += 4;
4312         jobtab = jp;
4313         jp = (struct job *)((char *)jp + len);
4314         jq = jp + 3;
4315         do {
4316                 jq->used = 0;
4317         } while (--jq >= jp);
4318         return jp;
4319 }
4320
4321 /*
4322  * Return a new job structure.
4323  * Called with interrupts off.
4324  */
4325 static struct job *
4326 makejob(/*union node *node,*/ int nprocs)
4327 {
4328         int i;
4329         struct job *jp;
4330
4331         for (i = njobs, jp = jobtab; ; jp++) {
4332                 if (--i < 0) {
4333                         jp = growjobtab();
4334                         break;
4335                 }
4336                 if (jp->used == 0)
4337                         break;
4338                 if (jp->state != JOBDONE || !jp->waited)
4339                         continue;
4340 #if JOBS
4341                 if (doing_jobctl)
4342                         continue;
4343 #endif
4344                 freejob(jp);
4345                 break;
4346         }
4347         memset(jp, 0, sizeof(*jp));
4348 #if JOBS
4349         /* jp->jobctl is a bitfield.
4350          * "jp->jobctl |= jobctl" likely to give awful code */
4351         if (doing_jobctl)
4352                 jp->jobctl = 1;
4353 #endif
4354         jp->prev_job = curjob;
4355         curjob = jp;
4356         jp->used = 1;
4357         jp->ps = &jp->ps0;
4358         if (nprocs > 1) {
4359                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4360         }
4361         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4362                                 jobno(jp)));
4363         return jp;
4364 }
4365
4366 #if JOBS
4367 /*
4368  * Return a string identifying a command (to be printed by the
4369  * jobs command).
4370  */
4371 static char *cmdnextc;
4372
4373 static void
4374 cmdputs(const char *s)
4375 {
4376         static const char vstype[VSTYPE + 1][3] = {
4377                 "", "}", "-", "+", "?", "=",
4378                 "%", "%%", "#", "##"
4379                 IF_ASH_BASH_COMPAT(, ":", "/", "//")
4380         };
4381
4382         const char *p, *str;
4383         char cc[2];
4384         char *nextc;
4385         unsigned char c;
4386         unsigned char subtype = 0;
4387         int quoted = 0;
4388
4389         cc[1] = '\0';
4390         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4391         p = s;
4392         while ((c = *p++) != '\0') {
4393                 str = NULL;
4394                 switch (c) {
4395                 case CTLESC:
4396                         c = *p++;
4397                         break;
4398                 case CTLVAR:
4399                         subtype = *p++;
4400                         if ((subtype & VSTYPE) == VSLENGTH)
4401                                 str = "${#";
4402                         else
4403                                 str = "${";
4404                         if (!(subtype & VSQUOTE) == !(quoted & 1))
4405                                 goto dostr;
4406                         quoted ^= 1;
4407                         c = '"';
4408                         break;
4409                 case CTLENDVAR:
4410                         str = "\"}" + !(quoted & 1);
4411                         quoted >>= 1;
4412                         subtype = 0;
4413                         goto dostr;
4414                 case CTLBACKQ:
4415                         str = "$(...)";
4416                         goto dostr;
4417                 case CTLBACKQ+CTLQUOTE:
4418                         str = "\"$(...)\"";
4419                         goto dostr;
4420 #if ENABLE_SH_MATH_SUPPORT
4421                 case CTLARI:
4422                         str = "$((";
4423                         goto dostr;
4424                 case CTLENDARI:
4425                         str = "))";
4426                         goto dostr;
4427 #endif
4428                 case CTLQUOTEMARK:
4429                         quoted ^= 1;
4430                         c = '"';
4431                         break;
4432                 case '=':
4433                         if (subtype == 0)
4434                                 break;
4435                         if ((subtype & VSTYPE) != VSNORMAL)
4436                                 quoted <<= 1;
4437                         str = vstype[subtype & VSTYPE];
4438                         if (subtype & VSNUL)
4439                                 c = ':';
4440                         else
4441                                 goto checkstr;
4442                         break;
4443                 case '\'':
4444                 case '\\':
4445                 case '"':
4446                 case '$':
4447                         /* These can only happen inside quotes */
4448                         cc[0] = c;
4449                         str = cc;
4450                         c = '\\';
4451                         break;
4452                 default:
4453                         break;
4454                 }
4455                 USTPUTC(c, nextc);
4456  checkstr:
4457                 if (!str)
4458                         continue;
4459  dostr:
4460                 while ((c = *str++) != '\0') {
4461                         USTPUTC(c, nextc);
4462                 }
4463         } /* while *p++ not NUL */
4464
4465         if (quoted & 1) {
4466                 USTPUTC('"', nextc);
4467         }
4468         *nextc = 0;
4469         cmdnextc = nextc;
4470 }
4471
4472 /* cmdtxt() and cmdlist() call each other */
4473 static void cmdtxt(union node *n);
4474
4475 static void
4476 cmdlist(union node *np, int sep)
4477 {
4478         for (; np; np = np->narg.next) {
4479                 if (!sep)
4480                         cmdputs(" ");
4481                 cmdtxt(np);
4482                 if (sep && np->narg.next)
4483                         cmdputs(" ");
4484         }
4485 }
4486
4487 static void
4488 cmdtxt(union node *n)
4489 {
4490         union node *np;
4491         struct nodelist *lp;
4492         const char *p;
4493
4494         if (!n)
4495                 return;
4496         switch (n->type) {
4497         default:
4498 #if DEBUG
4499                 abort();
4500 #endif
4501         case NPIPE:
4502                 lp = n->npipe.cmdlist;
4503                 for (;;) {
4504                         cmdtxt(lp->n);
4505                         lp = lp->next;
4506                         if (!lp)
4507                                 break;
4508                         cmdputs(" | ");
4509                 }
4510                 break;
4511         case NSEMI:
4512                 p = "; ";
4513                 goto binop;
4514         case NAND:
4515                 p = " && ";
4516                 goto binop;
4517         case NOR:
4518                 p = " || ";
4519  binop:
4520                 cmdtxt(n->nbinary.ch1);
4521                 cmdputs(p);
4522                 n = n->nbinary.ch2;
4523                 goto donode;
4524         case NREDIR:
4525         case NBACKGND:
4526                 n = n->nredir.n;
4527                 goto donode;
4528         case NNOT:
4529                 cmdputs("!");
4530                 n = n->nnot.com;
4531  donode:
4532                 cmdtxt(n);
4533                 break;
4534         case NIF:
4535                 cmdputs("if ");
4536                 cmdtxt(n->nif.test);
4537                 cmdputs("; then ");
4538                 if (n->nif.elsepart) {
4539                         cmdtxt(n->nif.ifpart);
4540                         cmdputs("; else ");
4541                         n = n->nif.elsepart;
4542                 } else {
4543                         n = n->nif.ifpart;
4544                 }
4545                 p = "; fi";
4546                 goto dotail;
4547         case NSUBSHELL:
4548                 cmdputs("(");
4549                 n = n->nredir.n;
4550                 p = ")";
4551                 goto dotail;
4552         case NWHILE:
4553                 p = "while ";
4554                 goto until;
4555         case NUNTIL:
4556                 p = "until ";
4557  until:
4558                 cmdputs(p);
4559                 cmdtxt(n->nbinary.ch1);
4560                 n = n->nbinary.ch2;
4561                 p = "; done";
4562  dodo:
4563                 cmdputs("; do ");
4564  dotail:
4565                 cmdtxt(n);
4566                 goto dotail2;
4567         case NFOR:
4568                 cmdputs("for ");
4569                 cmdputs(n->nfor.var);
4570                 cmdputs(" in ");
4571                 cmdlist(n->nfor.args, 1);
4572                 n = n->nfor.body;
4573                 p = "; done";
4574                 goto dodo;
4575         case NDEFUN:
4576                 cmdputs(n->narg.text);
4577                 p = "() { ... }";
4578                 goto dotail2;
4579         case NCMD:
4580                 cmdlist(n->ncmd.args, 1);
4581                 cmdlist(n->ncmd.redirect, 0);
4582                 break;
4583         case NARG:
4584                 p = n->narg.text;
4585  dotail2:
4586                 cmdputs(p);
4587                 break;
4588         case NHERE:
4589         case NXHERE:
4590                 p = "<<...";
4591                 goto dotail2;
4592         case NCASE:
4593                 cmdputs("case ");
4594                 cmdputs(n->ncase.expr->narg.text);
4595                 cmdputs(" in ");
4596                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4597                         cmdtxt(np->nclist.pattern);
4598                         cmdputs(") ");
4599                         cmdtxt(np->nclist.body);
4600                         cmdputs(";; ");
4601                 }
4602                 p = "esac";
4603                 goto dotail2;
4604         case NTO:
4605                 p = ">";
4606                 goto redir;
4607         case NCLOBBER:
4608                 p = ">|";
4609                 goto redir;
4610         case NAPPEND:
4611                 p = ">>";
4612                 goto redir;
4613 #if ENABLE_ASH_BASH_COMPAT
4614         case NTO2:
4615 #endif
4616         case NTOFD:
4617                 p = ">&";
4618                 goto redir;
4619         case NFROM:
4620                 p = "<";
4621                 goto redir;
4622         case NFROMFD:
4623                 p = "<&";
4624                 goto redir;
4625         case NFROMTO:
4626                 p = "<>";
4627  redir:
4628                 cmdputs(utoa(n->nfile.fd));
4629                 cmdputs(p);
4630                 if (n->type == NTOFD || n->type == NFROMFD) {
4631                         cmdputs(utoa(n->ndup.dupfd));
4632                         break;
4633                 }
4634                 n = n->nfile.fname;
4635                 goto donode;
4636         }
4637 }
4638
4639 static char *
4640 commandtext(union node *n)
4641 {
4642         char *name;
4643
4644         STARTSTACKSTR(cmdnextc);
4645         cmdtxt(n);
4646         name = stackblock();
4647         TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4648                         name, cmdnextc, cmdnextc));
4649         return ckstrdup(name);
4650 }
4651 #endif /* JOBS */
4652
4653 /*
4654  * Fork off a subshell.  If we are doing job control, give the subshell its
4655  * own process group.  Jp is a job structure that the job is to be added to.
4656  * N is the command that will be evaluated by the child.  Both jp and n may
4657  * be NULL.  The mode parameter can be one of the following:
4658  *      FORK_FG - Fork off a foreground process.
4659  *      FORK_BG - Fork off a background process.
4660  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4661  *                   process group even if job control is on.
4662  *
4663  * When job control is turned off, background processes have their standard
4664  * input redirected to /dev/null (except for the second and later processes
4665  * in a pipeline).
4666  *
4667  * Called with interrupts off.
4668  */
4669 /*
4670  * Clear traps on a fork.
4671  */
4672 static void
4673 clear_traps(void)
4674 {
4675         char **tp;
4676
4677         for (tp = trap; tp < &trap[NSIG]; tp++) {
4678                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4679                         INT_OFF;
4680                         if (trap_ptr == trap)
4681                                 free(*tp);
4682                         /* else: it "belongs" to trap_ptr vector, don't free */
4683                         *tp = NULL;
4684                         if ((tp - trap) != 0)
4685                                 setsignal(tp - trap);
4686                         INT_ON;
4687                 }
4688         }
4689         may_have_traps = 0;
4690 }
4691
4692 /* Lives far away from here, needed for forkchild */
4693 static void closescript(void);
4694
4695 /* Called after fork(), in child */
4696 static NOINLINE void
4697 forkchild(struct job *jp, union node *n, int mode)
4698 {
4699         int oldlvl;
4700
4701         TRACE(("Child shell %d\n", getpid()));
4702         oldlvl = shlvl;
4703         shlvl++;
4704
4705         /* man bash: "Non-builtin commands run by bash have signal handlers
4706          * set to the values inherited by the shell from its parent".
4707          * Do we do it correctly? */
4708
4709         closescript();
4710
4711         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4712          && n && n->type == NCMD        /* is it single cmd? */
4713         /* && n->ncmd.args->type == NARG - always true? */
4714          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4715          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4716         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4717         ) {
4718                 TRACE(("Trap hack\n"));
4719                 /* Awful hack for `trap` or $(trap).
4720                  *
4721                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4722                  * contains an example where "trap" is executed in a subshell:
4723                  *
4724                  * save_traps=$(trap)
4725                  * ...
4726                  * eval "$save_traps"
4727                  *
4728                  * Standard does not say that "trap" in subshell shall print
4729                  * parent shell's traps. It only says that its output
4730                  * must have suitable form, but then, in the above example
4731                  * (which is not supposed to be normative), it implies that.
4732                  *
4733                  * bash (and probably other shell) does implement it
4734                  * (traps are reset to defaults, but "trap" still shows them),
4735                  * but as a result, "trap" logic is hopelessly messed up:
4736                  *
4737                  * # trap
4738                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4739                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4740                  * # true | trap   <--- trap is in subshell - no output (ditto)
4741                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4742                  * trap -- 'echo Ho' SIGWINCH
4743                  * # echo `(trap)`         <--- in subshell in subshell - output
4744                  * trap -- 'echo Ho' SIGWINCH
4745                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4746                  * trap -- 'echo Ho' SIGWINCH
4747                  *
4748                  * The rules when to forget and when to not forget traps
4749                  * get really complex and nonsensical.
4750                  *
4751                  * Our solution: ONLY bare $(trap) or `trap` is special.
4752                  */
4753                 /* Save trap handler strings for trap builtin to print */
4754                 trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap));
4755                 /* Fall through into clearing traps */
4756         }
4757         clear_traps();
4758 #if JOBS
4759         /* do job control only in root shell */
4760         doing_jobctl = 0;
4761         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4762                 pid_t pgrp;
4763
4764                 if (jp->nprocs == 0)
4765                         pgrp = getpid();
4766                 else
4767                         pgrp = jp->ps[0].ps_pid;
4768                 /* this can fail because we are doing it in the parent also */
4769                 setpgid(0, pgrp);
4770                 if (mode == FORK_FG)
4771                         xtcsetpgrp(ttyfd, pgrp);
4772                 setsignal(SIGTSTP);
4773                 setsignal(SIGTTOU);
4774         } else
4775 #endif
4776         if (mode == FORK_BG) {
4777                 /* man bash: "When job control is not in effect,
4778                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4779                 ignoresig(SIGINT);
4780                 ignoresig(SIGQUIT);
4781                 if (jp->nprocs == 0) {
4782                         close(0);
4783                         if (open(bb_dev_null, O_RDONLY) != 0)
4784                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4785                 }
4786         }
4787         if (oldlvl == 0) {
4788                 if (iflag) { /* why if iflag only? */
4789                         setsignal(SIGINT);
4790                         setsignal(SIGTERM);
4791                 }
4792                 /* man bash:
4793                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4794                  * commands run by bash have signal handlers
4795                  * set to the values inherited by the shell
4796                  * from its parent".
4797                  * Take care of the second rule: */
4798                 setsignal(SIGQUIT);
4799         }
4800 #if JOBS
4801         if (n && n->type == NCMD
4802          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4803         ) {
4804                 TRACE(("Job hack\n"));
4805                 /* "jobs": we do not want to clear job list for it,
4806                  * instead we remove only _its_ own_ job from job list.
4807                  * This makes "jobs .... | cat" more useful.
4808                  */
4809                 freejob(curjob);
4810                 return;
4811         }
4812 #endif
4813         for (jp = curjob; jp; jp = jp->prev_job)
4814                 freejob(jp);
4815         jobless = 0;
4816 }
4817
4818 /* Called after fork(), in parent */
4819 #if !JOBS
4820 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4821 #endif
4822 static void
4823 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4824 {
4825         TRACE(("In parent shell: child = %d\n", pid));
4826         if (!jp) {
4827                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4828                         continue;
4829                 jobless++;
4830                 return;
4831         }
4832 #if JOBS
4833         if (mode != FORK_NOJOB && jp->jobctl) {
4834                 int pgrp;
4835
4836                 if (jp->nprocs == 0)
4837                         pgrp = pid;
4838                 else
4839                         pgrp = jp->ps[0].ps_pid;
4840                 /* This can fail because we are doing it in the child also */
4841                 setpgid(pid, pgrp);
4842         }
4843 #endif
4844         if (mode == FORK_BG) {
4845                 backgndpid = pid;               /* set $! */
4846                 set_curjob(jp, CUR_RUNNING);
4847         }
4848         if (jp) {
4849                 struct procstat *ps = &jp->ps[jp->nprocs++];
4850                 ps->ps_pid = pid;
4851                 ps->ps_status = -1;
4852                 ps->ps_cmd = nullstr;
4853 #if JOBS
4854                 if (doing_jobctl && n)
4855                         ps->ps_cmd = commandtext(n);
4856 #endif
4857         }
4858 }
4859
4860 static int
4861 forkshell(struct job *jp, union node *n, int mode)
4862 {
4863         int pid;
4864
4865         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4866         pid = fork();
4867         if (pid < 0) {
4868                 TRACE(("Fork failed, errno=%d", errno));
4869                 if (jp)
4870                         freejob(jp);
4871                 ash_msg_and_raise_error("can't fork");
4872         }
4873         if (pid == 0) {
4874                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
4875                 forkchild(jp, n, mode);
4876         } else {
4877                 forkparent(jp, n, mode, pid);
4878         }
4879         return pid;
4880 }
4881
4882 /*
4883  * Wait for job to finish.
4884  *
4885  * Under job control we have the problem that while a child process
4886  * is running interrupts generated by the user are sent to the child
4887  * but not to the shell.  This means that an infinite loop started by
4888  * an interactive user may be hard to kill.  With job control turned off,
4889  * an interactive user may place an interactive program inside a loop.
4890  * If the interactive program catches interrupts, the user doesn't want
4891  * these interrupts to also abort the loop.  The approach we take here
4892  * is to have the shell ignore interrupt signals while waiting for a
4893  * foreground process to terminate, and then send itself an interrupt
4894  * signal if the child process was terminated by an interrupt signal.
4895  * Unfortunately, some programs want to do a bit of cleanup and then
4896  * exit on interrupt; unless these processes terminate themselves by
4897  * sending a signal to themselves (instead of calling exit) they will
4898  * confuse this approach.
4899  *
4900  * Called with interrupts off.
4901  */
4902 static int
4903 waitforjob(struct job *jp)
4904 {
4905         int st;
4906
4907         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4908
4909         INT_OFF;
4910         while (jp->state == JOBRUNNING) {
4911                 /* In non-interactive shells, we _can_ get
4912                  * a keyboard signal here and be EINTRed,
4913                  * but we just loop back, waiting for command to complete.
4914                  *
4915                  * man bash:
4916                  * "If bash is waiting for a command to complete and receives
4917                  * a signal for which a trap has been set, the trap
4918                  * will not be executed until the command completes."
4919                  *
4920                  * Reality is that even if trap is not set, bash
4921                  * will not act on the signal until command completes.
4922                  * Try this. sleep5intoff.c:
4923                  * #include <signal.h>
4924                  * #include <unistd.h>
4925                  * int main() {
4926                  *         sigset_t set;
4927                  *         sigemptyset(&set);
4928                  *         sigaddset(&set, SIGINT);
4929                  *         sigaddset(&set, SIGQUIT);
4930                  *         sigprocmask(SIG_BLOCK, &set, NULL);
4931                  *         sleep(5);
4932                  *         return 0;
4933                  * }
4934                  * $ bash -c './sleep5intoff; echo hi'
4935                  * ^C^C^C^C <--- pressing ^C once a second
4936                  * $ _
4937                  * $ bash -c './sleep5intoff; echo hi'
4938                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4939                  * $ _
4940                  */
4941                 dowait(DOWAIT_BLOCK, jp);
4942         }
4943         INT_ON;
4944
4945         st = getstatus(jp);
4946 #if JOBS
4947         if (jp->jobctl) {
4948                 xtcsetpgrp(ttyfd, rootpid);
4949                 /*
4950                  * This is truly gross.
4951                  * If we're doing job control, then we did a TIOCSPGRP which
4952                  * caused us (the shell) to no longer be in the controlling
4953                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
4954                  * intuit from the subprocess exit status whether a SIGINT
4955                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
4956                  */
4957                 if (jp->sigint) /* TODO: do the same with all signals */
4958                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
4959         }
4960         if (jp->state == JOBDONE)
4961 #endif
4962                 freejob(jp);
4963         return st;
4964 }
4965
4966 /*
4967  * return 1 if there are stopped jobs, otherwise 0
4968  */
4969 static int
4970 stoppedjobs(void)
4971 {
4972         struct job *jp;
4973         int retval;
4974
4975         retval = 0;
4976         if (job_warning)
4977                 goto out;
4978         jp = curjob;
4979         if (jp && jp->state == JOBSTOPPED) {
4980                 out2str("You have stopped jobs.\n");
4981                 job_warning = 2;
4982                 retval++;
4983         }
4984  out:
4985         return retval;
4986 }
4987
4988
4989 /* ============ redir.c
4990  *
4991  * Code for dealing with input/output redirection.
4992  */
4993
4994 #undef EMPTY
4995 #undef CLOSED
4996 #define EMPTY -2                /* marks an unused slot in redirtab */
4997 #define CLOSED -3               /* marks a slot of previously-closed fd */
4998
4999 /*
5000  * Open a file in noclobber mode.
5001  * The code was copied from bash.
5002  */
5003 static int
5004 noclobberopen(const char *fname)
5005 {
5006         int r, fd;
5007         struct stat finfo, finfo2;
5008
5009         /*
5010          * If the file exists and is a regular file, return an error
5011          * immediately.
5012          */
5013         r = stat(fname, &finfo);
5014         if (r == 0 && S_ISREG(finfo.st_mode)) {
5015                 errno = EEXIST;
5016                 return -1;
5017         }
5018
5019         /*
5020          * If the file was not present (r != 0), make sure we open it
5021          * exclusively so that if it is created before we open it, our open
5022          * will fail.  Make sure that we do not truncate an existing file.
5023          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5024          * file was not a regular file, we leave O_EXCL off.
5025          */
5026         if (r != 0)
5027                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5028         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5029
5030         /* If the open failed, return the file descriptor right away. */
5031         if (fd < 0)
5032                 return fd;
5033
5034         /*
5035          * OK, the open succeeded, but the file may have been changed from a
5036          * non-regular file to a regular file between the stat and the open.
5037          * We are assuming that the O_EXCL open handles the case where FILENAME
5038          * did not exist and is symlinked to an existing file between the stat
5039          * and open.
5040          */
5041
5042         /*
5043          * If we can open it and fstat the file descriptor, and neither check
5044          * revealed that it was a regular file, and the file has not been
5045          * replaced, return the file descriptor.
5046          */
5047         if (fstat(fd, &finfo2) == 0
5048          && !S_ISREG(finfo2.st_mode)
5049          && finfo.st_dev == finfo2.st_dev
5050          && finfo.st_ino == finfo2.st_ino
5051         ) {
5052                 return fd;
5053         }
5054
5055         /* The file has been replaced.  badness. */
5056         close(fd);
5057         errno = EEXIST;
5058         return -1;
5059 }
5060
5061 /*
5062  * Handle here documents.  Normally we fork off a process to write the
5063  * data to a pipe.  If the document is short, we can stuff the data in
5064  * the pipe without forking.
5065  */
5066 /* openhere needs this forward reference */
5067 static void expandhere(union node *arg, int fd);
5068 static int
5069 openhere(union node *redir)
5070 {
5071         int pip[2];
5072         size_t len = 0;
5073
5074         if (pipe(pip) < 0)
5075                 ash_msg_and_raise_error("pipe call failed");
5076         if (redir->type == NHERE) {
5077                 len = strlen(redir->nhere.doc->narg.text);
5078                 if (len <= PIPE_BUF) {
5079                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5080                         goto out;
5081                 }
5082         }
5083         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5084                 /* child */
5085                 close(pip[0]);
5086                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5087                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5088                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5089                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5090                 signal(SIGPIPE, SIG_DFL);
5091                 if (redir->type == NHERE)
5092                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5093                 else /* NXHERE */
5094                         expandhere(redir->nhere.doc, pip[1]);
5095                 _exit(EXIT_SUCCESS);
5096         }
5097  out:
5098         close(pip[1]);
5099         return pip[0];
5100 }
5101
5102 static int
5103 openredirect(union node *redir)
5104 {
5105         char *fname;
5106         int f;
5107
5108         switch (redir->nfile.type) {
5109         case NFROM:
5110                 fname = redir->nfile.expfname;
5111                 f = open(fname, O_RDONLY);
5112                 if (f < 0)
5113                         goto eopen;
5114                 break;
5115         case NFROMTO:
5116                 fname = redir->nfile.expfname;
5117                 f = open(fname, O_RDWR|O_CREAT, 0666);
5118                 if (f < 0)
5119                         goto ecreate;
5120                 break;
5121         case NTO:
5122 #if ENABLE_ASH_BASH_COMPAT
5123         case NTO2:
5124 #endif
5125                 /* Take care of noclobber mode. */
5126                 if (Cflag) {
5127                         fname = redir->nfile.expfname;
5128                         f = noclobberopen(fname);
5129                         if (f < 0)
5130                                 goto ecreate;
5131                         break;
5132                 }
5133                 /* FALLTHROUGH */
5134         case NCLOBBER:
5135                 fname = redir->nfile.expfname;
5136                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5137                 if (f < 0)
5138                         goto ecreate;
5139                 break;
5140         case NAPPEND:
5141                 fname = redir->nfile.expfname;
5142                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5143                 if (f < 0)
5144                         goto ecreate;
5145                 break;
5146         default:
5147 #if DEBUG
5148                 abort();
5149 #endif
5150                 /* Fall through to eliminate warning. */
5151 /* Our single caller does this itself */
5152 //      case NTOFD:
5153 //      case NFROMFD:
5154 //              f = -1;
5155 //              break;
5156         case NHERE:
5157         case NXHERE:
5158                 f = openhere(redir);
5159                 break;
5160         }
5161
5162         return f;
5163  ecreate:
5164         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5165  eopen:
5166         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5167 }
5168
5169 /*
5170  * Copy a file descriptor to be >= to.  Returns -1
5171  * if the source file descriptor is closed, EMPTY if there are no unused
5172  * file descriptors left.
5173  */
5174 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
5175  * old code was doing close(to) prior to copyfd() to achieve the same */
5176 enum {
5177         COPYFD_EXACT   = (int)~(INT_MAX),
5178         COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
5179 };
5180 static int
5181 copyfd(int from, int to)
5182 {
5183         int newfd;
5184
5185         if (to & COPYFD_EXACT) {
5186                 to &= ~COPYFD_EXACT;
5187                 /*if (from != to)*/
5188                         newfd = dup2(from, to);
5189         } else {
5190                 newfd = fcntl(from, F_DUPFD, to);
5191         }
5192         if (newfd < 0) {
5193                 if (errno == EMFILE)
5194                         return EMPTY;
5195                 /* Happens when source fd is not open: try "echo >&99" */
5196                 ash_msg_and_raise_error("%d: %m", from);
5197         }
5198         return newfd;
5199 }
5200
5201 /* Struct def and variable are moved down to the first usage site */
5202 struct two_fd_t {
5203         int orig, copy;
5204 };
5205 struct redirtab {
5206         struct redirtab *next;
5207         int nullredirs;
5208         int pair_count;
5209         struct two_fd_t two_fd[];
5210 };
5211 #define redirlist (G_var.redirlist)
5212
5213 static int need_to_remember(struct redirtab *rp, int fd)
5214 {
5215         int i;
5216
5217         if (!rp) /* remembering was not requested */
5218                 return 0;
5219
5220         for (i = 0; i < rp->pair_count; i++) {
5221                 if (rp->two_fd[i].orig == fd) {
5222                         /* already remembered */
5223                         return 0;
5224                 }
5225         }
5226         return 1;
5227 }
5228
5229 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5230 static int is_hidden_fd(struct redirtab *rp, int fd)
5231 {
5232         int i;
5233         struct parsefile *pf;
5234
5235         if (fd == -1)
5236                 return 0;
5237         /* Check open scripts' fds */
5238         pf = g_parsefile;
5239         while (pf) {
5240                 /* We skip pf_fd == 0 case because of the following case:
5241                  * $ ash  # running ash interactively
5242                  * $ . ./script.sh
5243                  * and in script.sh: "exec 9>&0".
5244                  * Even though top-level pf_fd _is_ 0,
5245                  * it's still ok to use it: "read" builtin uses it,
5246                  * why should we cripple "exec" builtin?
5247                  */
5248                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5249                         return 1;
5250                 }
5251                 pf = pf->prev;
5252         }
5253
5254         if (!rp)
5255                 return 0;
5256         /* Check saved fds of redirects */
5257         fd |= COPYFD_RESTORE;
5258         for (i = 0; i < rp->pair_count; i++) {
5259                 if (rp->two_fd[i].copy == fd) {
5260                         return 1;
5261                 }
5262         }
5263         return 0;
5264 }
5265
5266 /*
5267  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5268  * old file descriptors are stashed away so that the redirection can be
5269  * undone by calling popredir.
5270  */
5271 /* flags passed to redirect */
5272 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5273 #define REDIR_SAVEFD2 03        /* set preverrout */
5274 static void
5275 redirect(union node *redir, int flags)
5276 {
5277         struct redirtab *sv;
5278         int sv_pos;
5279         int i;
5280         int fd;
5281         int newfd;
5282         int copied_fd2 = -1;
5283
5284         g_nullredirs++;
5285         if (!redir) {
5286                 return;
5287         }
5288
5289         sv = NULL;
5290         sv_pos = 0;
5291         INT_OFF;
5292         if (flags & REDIR_PUSH) {
5293                 union node *tmp = redir;
5294                 do {
5295                         sv_pos++;
5296 #if ENABLE_ASH_BASH_COMPAT
5297                         if (tmp->nfile.type == NTO2)
5298                                 sv_pos++;
5299 #endif
5300                         tmp = tmp->nfile.next;
5301                 } while (tmp);
5302                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5303                 sv->next = redirlist;
5304                 sv->pair_count = sv_pos;
5305                 redirlist = sv;
5306                 sv->nullredirs = g_nullredirs - 1;
5307                 g_nullredirs = 0;
5308                 while (sv_pos > 0) {
5309                         sv_pos--;
5310                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5311                 }
5312         }
5313
5314         do {
5315                 int right_fd = -1;
5316                 fd = redir->nfile.fd;
5317                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5318                         right_fd = redir->ndup.dupfd;
5319                         //bb_error_msg("doing %d > %d", fd, right_fd);
5320                         /* redirect from/to same file descriptor? */
5321                         if (right_fd == fd)
5322                                 continue;
5323                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5324                         if (is_hidden_fd(sv, right_fd)) {
5325                                 errno = EBADF; /* as if it is closed */
5326                                 ash_msg_and_raise_error("%d: %m", right_fd);
5327                         }
5328                         newfd = -1;
5329                 } else {
5330                         newfd = openredirect(redir); /* always >= 0 */
5331                         if (fd == newfd) {
5332                                 /* Descriptor wasn't open before redirect.
5333                                  * Mark it for close in the future */
5334                                 if (need_to_remember(sv, fd)) {
5335                                         goto remember_to_close;
5336                                 }
5337                                 continue;
5338                         }
5339                 }
5340 #if ENABLE_ASH_BASH_COMPAT
5341  redirect_more:
5342 #endif
5343                 if (need_to_remember(sv, fd)) {
5344                         /* Copy old descriptor */
5345                         /* Careful to not accidentally "save"
5346                          * to the same fd as right side fd in N>&M */
5347                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5348                         i = fcntl(fd, F_DUPFD, minfd);
5349 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5350  * are closed in popredir() in the child, preventing them from leaking
5351  * into child. (popredir() also cleans up the mess in case of failures)
5352  */
5353                         if (i == -1) {
5354                                 i = errno;
5355                                 if (i != EBADF) {
5356                                         /* Strange error (e.g. "too many files" EMFILE?) */
5357                                         if (newfd >= 0)
5358                                                 close(newfd);
5359                                         errno = i;
5360                                         ash_msg_and_raise_error("%d: %m", fd);
5361                                         /* NOTREACHED */
5362                                 }
5363                                 /* EBADF: it is not open - good, remember to close it */
5364  remember_to_close:
5365                                 i = CLOSED;
5366                         } else { /* fd is open, save its copy */
5367                                 /* "exec fd>&-" should not close fds
5368                                  * which point to script file(s).
5369                                  * Force them to be restored afterwards */
5370                                 if (is_hidden_fd(sv, fd))
5371                                         i |= COPYFD_RESTORE;
5372                         }
5373                         if (fd == 2)
5374                                 copied_fd2 = i;
5375                         sv->two_fd[sv_pos].orig = fd;
5376                         sv->two_fd[sv_pos].copy = i;
5377                         sv_pos++;
5378                 }
5379                 if (newfd < 0) {
5380                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5381                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5382                                 /* Don't want to trigger debugging */
5383                                 if (fd != -1)
5384                                         close(fd);
5385                         } else {
5386                                 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5387                         }
5388                 } else if (fd != newfd) { /* move newfd to fd */
5389                         copyfd(newfd, fd | COPYFD_EXACT);
5390 #if ENABLE_ASH_BASH_COMPAT
5391                         if (!(redir->nfile.type == NTO2 && fd == 2))
5392 #endif
5393                                 close(newfd);
5394                 }
5395 #if ENABLE_ASH_BASH_COMPAT
5396                 if (redir->nfile.type == NTO2 && fd == 1) {
5397                         /* We already redirected it to fd 1, now copy it to 2 */
5398                         newfd = 1;
5399                         fd = 2;
5400                         goto redirect_more;
5401                 }
5402 #endif
5403         } while ((redir = redir->nfile.next) != NULL);
5404
5405         INT_ON;
5406         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5407                 preverrout_fd = copied_fd2;
5408 }
5409
5410 /*
5411  * Undo the effects of the last redirection.
5412  */
5413 static void
5414 popredir(int drop, int restore)
5415 {
5416         struct redirtab *rp;
5417         int i;
5418
5419         if (--g_nullredirs >= 0)
5420                 return;
5421         INT_OFF;
5422         rp = redirlist;
5423         for (i = 0; i < rp->pair_count; i++) {
5424                 int fd = rp->two_fd[i].orig;
5425                 int copy = rp->two_fd[i].copy;
5426                 if (copy == CLOSED) {
5427                         if (!drop)
5428                                 close(fd);
5429                         continue;
5430                 }
5431                 if (copy != EMPTY) {
5432                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5433                                 copy &= ~COPYFD_RESTORE;
5434                                 /*close(fd);*/
5435                                 copyfd(copy, fd | COPYFD_EXACT);
5436                         }
5437                         close(copy & ~COPYFD_RESTORE);
5438                 }
5439         }
5440         redirlist = rp->next;
5441         g_nullredirs = rp->nullredirs;
5442         free(rp);
5443         INT_ON;
5444 }
5445
5446 /*
5447  * Undo all redirections.  Called on error or interrupt.
5448  */
5449
5450 /*
5451  * Discard all saved file descriptors.
5452  */
5453 static void
5454 clearredir(int drop)
5455 {
5456         for (;;) {
5457                 g_nullredirs = 0;
5458                 if (!redirlist)
5459                         break;
5460                 popredir(drop, /*restore:*/ 0);
5461         }
5462 }
5463
5464 static int
5465 redirectsafe(union node *redir, int flags)
5466 {
5467         int err;
5468         volatile int saveint;
5469         struct jmploc *volatile savehandler = exception_handler;
5470         struct jmploc jmploc;
5471
5472         SAVE_INT(saveint);
5473         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5474         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5475         if (!err) {
5476                 exception_handler = &jmploc;
5477                 redirect(redir, flags);
5478         }
5479         exception_handler = savehandler;
5480         if (err && exception_type != EXERROR)
5481                 longjmp(exception_handler->loc, 1);
5482         RESTORE_INT(saveint);
5483         return err;
5484 }
5485
5486
5487 /* ============ Routines to expand arguments to commands
5488  *
5489  * We have to deal with backquotes, shell variables, and file metacharacters.
5490  */
5491
5492 #if ENABLE_SH_MATH_SUPPORT
5493 static arith_t
5494 ash_arith(const char *s)
5495 {
5496         arith_state_t math_state;
5497         arith_t result;
5498
5499         math_state.lookupvar = lookupvar;
5500         math_state.setvar    = setvar2;
5501         //math_state.endofname = endofname;
5502
5503         INT_OFF;
5504         result = arith(&math_state, s);
5505         if (math_state.errmsg)
5506                 ash_msg_and_raise_error(math_state.errmsg);
5507         INT_ON;
5508
5509         return result;
5510 }
5511 #endif
5512
5513 /*
5514  * expandarg flags
5515  */
5516 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5517 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5518 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5519 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5520 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5521 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
5522 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5523 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5524 #define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
5525 /*
5526  * rmescape() flags
5527  */
5528 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5529 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5530 #define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
5531 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5532 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5533
5534 /*
5535  * Structure specifying which parts of the string should be searched
5536  * for IFS characters.
5537  */
5538 struct ifsregion {
5539         struct ifsregion *next; /* next region in list */
5540         int begoff;             /* offset of start of region */
5541         int endoff;             /* offset of end of region */
5542         int nulonly;            /* search for nul bytes only */
5543 };
5544
5545 struct arglist {
5546         struct strlist *list;
5547         struct strlist **lastp;
5548 };
5549
5550 /* output of current string */
5551 static char *expdest;
5552 /* list of back quote expressions */
5553 static struct nodelist *argbackq;
5554 /* first struct in list of ifs regions */
5555 static struct ifsregion ifsfirst;
5556 /* last struct in list */
5557 static struct ifsregion *ifslastp;
5558 /* holds expanded arg list */
5559 static struct arglist exparg;
5560
5561 /*
5562  * Our own itoa().
5563  */
5564 #if !ENABLE_SH_MATH_SUPPORT
5565 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5566 typedef long arith_t;
5567 # define ARITH_FMT "%ld"
5568 #endif
5569 static int
5570 cvtnum(arith_t num)
5571 {
5572         int len;
5573
5574         expdest = makestrspace(32, expdest);
5575         len = fmtstr(expdest, 32, ARITH_FMT, num);
5576         STADJUST(len, expdest);
5577         return len;
5578 }
5579
5580 static size_t
5581 esclen(const char *start, const char *p)
5582 {
5583         size_t esc = 0;
5584
5585         while (p > start && (unsigned char)*--p == CTLESC) {
5586                 esc++;
5587         }
5588         return esc;
5589 }
5590
5591 /*
5592  * Remove any CTLESC characters from a string.
5593  */
5594 static char *
5595 rmescapes(char *str, int flag)
5596 {
5597         static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5598
5599         char *p, *q, *r;
5600         unsigned inquotes;
5601         unsigned protect_against_glob;
5602         unsigned globbing;
5603
5604         p = strpbrk(str, qchars);
5605         if (!p)
5606                 return str;
5607
5608         q = p;
5609         r = str;
5610         if (flag & RMESCAPE_ALLOC) {
5611                 size_t len = p - str;
5612                 size_t fulllen = len + strlen(p) + 1;
5613
5614                 if (flag & RMESCAPE_GROW) {
5615                         int strloc = str - (char *)stackblock();
5616                         r = makestrspace(fulllen, expdest);
5617                         /* p and str may be invalidated by makestrspace */
5618                         str = (char *)stackblock() + strloc;
5619                         p = str + len;
5620                 } else if (flag & RMESCAPE_HEAP) {
5621                         r = ckmalloc(fulllen);
5622                 } else {
5623                         r = stalloc(fulllen);
5624                 }
5625                 q = r;
5626                 if (len > 0) {
5627                         q = (char *)memcpy(q, str, len) + len;
5628                 }
5629         }
5630
5631         inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5632         globbing = flag & RMESCAPE_GLOB;
5633         protect_against_glob = globbing;
5634         while (*p) {
5635                 if ((unsigned char)*p == CTLQUOTEMARK) {
5636 // TODO: if no RMESCAPE_QUOTED in flags, inquotes never becomes 0
5637 // (alternates between RMESCAPE_QUOTED and ~RMESCAPE_QUOTED). Is it ok?
5638 // Note: both inquotes and protect_against_glob only affect whether
5639 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5640                         inquotes = ~inquotes;
5641                         p++;
5642                         protect_against_glob = globbing;
5643                         continue;
5644                 }
5645                 if (*p == '\\') {
5646                         /* naked back slash */
5647                         protect_against_glob = 0;
5648                         goto copy;
5649                 }
5650                 if ((unsigned char)*p == CTLESC) {
5651                         p++;
5652                         if (protect_against_glob && inquotes && *p != '/') {
5653                                 *q++ = '\\';
5654                         }
5655                 }
5656                 protect_against_glob = globbing;
5657  copy:
5658                 *q++ = *p++;
5659         }
5660         *q = '\0';
5661         if (flag & RMESCAPE_GROW) {
5662                 expdest = r;
5663                 STADJUST(q - r + 1, expdest);
5664         }
5665         return r;
5666 }
5667 #define pmatch(a, b) !fnmatch((a), (b), 0)
5668
5669 /*
5670  * Prepare a pattern for a expmeta (internal glob(3)) call.
5671  *
5672  * Returns an stalloced string.
5673  */
5674 static char *
5675 preglob(const char *pattern, int quoted, int flag)
5676 {
5677         flag |= RMESCAPE_GLOB;
5678         if (quoted) {
5679                 flag |= RMESCAPE_QUOTED;
5680         }
5681         return rmescapes((char *)pattern, flag);
5682 }
5683
5684 /*
5685  * Put a string on the stack.
5686  */
5687 static void
5688 memtodest(const char *p, size_t len, int syntax, int quotes)
5689 {
5690         char *q = expdest;
5691
5692         q = makestrspace(quotes ? len * 2 : len, q);
5693
5694         while (len--) {
5695                 unsigned char c = *p++;
5696                 if (c == '\0')
5697                         continue;
5698                 if (quotes) {
5699                         int n = SIT(c, syntax);
5700                         if (n == CCTL || n == CBACK)
5701                                 USTPUTC(CTLESC, q);
5702                 }
5703                 USTPUTC(c, q);
5704         }
5705
5706         expdest = q;
5707 }
5708
5709 static void
5710 strtodest(const char *p, int syntax, int quotes)
5711 {
5712         memtodest(p, strlen(p), syntax, quotes);
5713 }
5714
5715 /*
5716  * Record the fact that we have to scan this region of the
5717  * string for IFS characters.
5718  */
5719 static void
5720 recordregion(int start, int end, int nulonly)
5721 {
5722         struct ifsregion *ifsp;
5723
5724         if (ifslastp == NULL) {
5725                 ifsp = &ifsfirst;
5726         } else {
5727                 INT_OFF;
5728                 ifsp = ckzalloc(sizeof(*ifsp));
5729                 /*ifsp->next = NULL; - ckzalloc did it */
5730                 ifslastp->next = ifsp;
5731                 INT_ON;
5732         }
5733         ifslastp = ifsp;
5734         ifslastp->begoff = start;
5735         ifslastp->endoff = end;
5736         ifslastp->nulonly = nulonly;
5737 }
5738
5739 static void
5740 removerecordregions(int endoff)
5741 {
5742         if (ifslastp == NULL)
5743                 return;
5744
5745         if (ifsfirst.endoff > endoff) {
5746                 while (ifsfirst.next) {
5747                         struct ifsregion *ifsp;
5748                         INT_OFF;
5749                         ifsp = ifsfirst.next->next;
5750                         free(ifsfirst.next);
5751                         ifsfirst.next = ifsp;
5752                         INT_ON;
5753                 }
5754                 if (ifsfirst.begoff > endoff) {
5755                         ifslastp = NULL;
5756                 } else {
5757                         ifslastp = &ifsfirst;
5758                         ifsfirst.endoff = endoff;
5759                 }
5760                 return;
5761         }
5762
5763         ifslastp = &ifsfirst;
5764         while (ifslastp->next && ifslastp->next->begoff < endoff)
5765                 ifslastp = ifslastp->next;
5766         while (ifslastp->next) {
5767                 struct ifsregion *ifsp;
5768                 INT_OFF;
5769                 ifsp = ifslastp->next->next;
5770                 free(ifslastp->next);
5771                 ifslastp->next = ifsp;
5772                 INT_ON;
5773         }
5774         if (ifslastp->endoff > endoff)
5775                 ifslastp->endoff = endoff;
5776 }
5777
5778 static char *
5779 exptilde(char *startp, char *p, int flags)
5780 {
5781         unsigned char c;
5782         char *name;
5783         struct passwd *pw;
5784         const char *home;
5785         int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR);
5786         int startloc;
5787
5788         name = p + 1;
5789
5790         while ((c = *++p) != '\0') {
5791                 switch (c) {
5792                 case CTLESC:
5793                         return startp;
5794                 case CTLQUOTEMARK:
5795                         return startp;
5796                 case ':':
5797                         if (flags & EXP_VARTILDE)
5798                                 goto done;
5799                         break;
5800                 case '/':
5801                 case CTLENDVAR:
5802                         goto done;
5803                 }
5804         }
5805  done:
5806         *p = '\0';
5807         if (*name == '\0') {
5808                 home = lookupvar("HOME");
5809         } else {
5810                 pw = getpwnam(name);
5811                 if (pw == NULL)
5812                         goto lose;
5813                 home = pw->pw_dir;
5814         }
5815         if (!home || !*home)
5816                 goto lose;
5817         *p = c;
5818         startloc = expdest - (char *)stackblock();
5819         strtodest(home, SQSYNTAX, quotes);
5820         recordregion(startloc, expdest - (char *)stackblock(), 0);
5821         return p;
5822  lose:
5823         *p = c;
5824         return startp;
5825 }
5826
5827 /*
5828  * Execute a command inside back quotes.  If it's a builtin command, we
5829  * want to save its output in a block obtained from malloc.  Otherwise
5830  * we fork off a subprocess and get the output of the command via a pipe.
5831  * Should be called with interrupts off.
5832  */
5833 struct backcmd {                /* result of evalbackcmd */
5834         int fd;                 /* file descriptor to read from */
5835         int nleft;              /* number of chars in buffer */
5836         char *buf;              /* buffer */
5837         struct job *jp;         /* job structure for command */
5838 };
5839
5840 /* These forward decls are needed to use "eval" code for backticks handling: */
5841 static uint8_t back_exitstatus; /* exit status of backquoted command */
5842 #define EV_EXIT 01              /* exit after evaluating tree */
5843 static void evaltree(union node *, int);
5844
5845 static void FAST_FUNC
5846 evalbackcmd(union node *n, struct backcmd *result)
5847 {
5848         int saveherefd;
5849
5850         result->fd = -1;
5851         result->buf = NULL;
5852         result->nleft = 0;
5853         result->jp = NULL;
5854         if (n == NULL)
5855                 goto out;
5856
5857         saveherefd = herefd;
5858         herefd = -1;
5859
5860         {
5861                 int pip[2];
5862                 struct job *jp;
5863
5864                 if (pipe(pip) < 0)
5865                         ash_msg_and_raise_error("pipe call failed");
5866                 jp = makejob(/*n,*/ 1);
5867                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5868                         FORCE_INT_ON;
5869                         close(pip[0]);
5870                         if (pip[1] != 1) {
5871                                 /*close(1);*/
5872                                 copyfd(pip[1], 1 | COPYFD_EXACT);
5873                                 close(pip[1]);
5874                         }
5875                         eflag = 0;
5876                         evaltree(n, EV_EXIT); /* actually evaltreenr... */
5877                         /* NOTREACHED */
5878                 }
5879                 close(pip[1]);
5880                 result->fd = pip[0];
5881                 result->jp = jp;
5882         }
5883         herefd = saveherefd;
5884  out:
5885         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5886                 result->fd, result->buf, result->nleft, result->jp));
5887 }
5888
5889 /*
5890  * Expand stuff in backwards quotes.
5891  */
5892 static void
5893 expbackq(union node *cmd, int quoted, int quotes)
5894 {
5895         struct backcmd in;
5896         int i;
5897         char buf[128];
5898         char *p;
5899         char *dest;
5900         int startloc;
5901         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5902         struct stackmark smark;
5903
5904         INT_OFF;
5905         setstackmark(&smark);
5906         dest = expdest;
5907         startloc = dest - (char *)stackblock();
5908         grabstackstr(dest);
5909         evalbackcmd(cmd, &in);
5910         popstackmark(&smark);
5911
5912         p = in.buf;
5913         i = in.nleft;
5914         if (i == 0)
5915                 goto read;
5916         for (;;) {
5917                 memtodest(p, i, syntax, quotes);
5918  read:
5919                 if (in.fd < 0)
5920                         break;
5921                 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5922                 TRACE(("expbackq: read returns %d\n", i));
5923                 if (i <= 0)
5924                         break;
5925                 p = buf;
5926         }
5927
5928         free(in.buf);
5929         if (in.fd >= 0) {
5930                 close(in.fd);
5931                 back_exitstatus = waitforjob(in.jp);
5932         }
5933         INT_ON;
5934
5935         /* Eat all trailing newlines */
5936         dest = expdest;
5937         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5938                 STUNPUTC(dest);
5939         expdest = dest;
5940
5941         if (quoted == 0)
5942                 recordregion(startloc, dest - (char *)stackblock(), 0);
5943         TRACE(("evalbackq: size:%d:'%.*s'\n",
5944                 (int)((dest - (char *)stackblock()) - startloc),
5945                 (int)((dest - (char *)stackblock()) - startloc),
5946                 stackblock() + startloc));
5947 }
5948
5949 #if ENABLE_SH_MATH_SUPPORT
5950 /*
5951  * Expand arithmetic expression.  Backup to start of expression,
5952  * evaluate, place result in (backed up) result, adjust string position.
5953  */
5954 static void
5955 expari(int quotes)
5956 {
5957         char *p, *start;
5958         int begoff;
5959         int flag;
5960         int len;
5961
5962         /* ifsfree(); */
5963
5964         /*
5965          * This routine is slightly over-complicated for
5966          * efficiency.  Next we scan backwards looking for the
5967          * start of arithmetic.
5968          */
5969         start = stackblock();
5970         p = expdest - 1;
5971         *p = '\0';
5972         p--;
5973         while (1) {
5974                 int esc;
5975
5976                 while ((unsigned char)*p != CTLARI) {
5977                         p--;
5978 #if DEBUG
5979                         if (p < start) {
5980                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5981                         }
5982 #endif
5983                 }
5984
5985                 esc = esclen(start, p);
5986                 if (!(esc % 2)) {
5987                         break;
5988                 }
5989
5990                 p -= esc + 1;
5991         }
5992
5993         begoff = p - start;
5994
5995         removerecordregions(begoff);
5996
5997         flag = p[1];
5998
5999         expdest = p;
6000
6001         if (quotes)
6002                 rmescapes(p + 2, 0);
6003
6004         len = cvtnum(ash_arith(p + 2));
6005
6006         if (flag != '"')
6007                 recordregion(begoff, begoff + len, 0);
6008 }
6009 #endif
6010
6011 /* argstr needs it */
6012 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6013
6014 /*
6015  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6016  * characters to allow for further processing.  Otherwise treat
6017  * $@ like $* since no splitting will be performed.
6018  *
6019  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6020  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
6021  * for correct expansion of "B=$A" word.
6022  */
6023 static void
6024 argstr(char *p, int flags, struct strlist *var_str_list)
6025 {
6026         static const char spclchars[] ALIGN1 = {
6027                 '=',
6028                 ':',
6029                 CTLQUOTEMARK,
6030                 CTLENDVAR,
6031                 CTLESC,
6032                 CTLVAR,
6033                 CTLBACKQ,
6034                 CTLBACKQ | CTLQUOTE,
6035 #if ENABLE_SH_MATH_SUPPORT
6036                 CTLENDARI,
6037 #endif
6038                 '\0'
6039         };
6040         const char *reject = spclchars;
6041         int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */
6042         int breakall = flags & EXP_WORD;
6043         int inquotes;
6044         size_t length;
6045         int startloc;
6046
6047         if (!(flags & EXP_VARTILDE)) {
6048                 reject += 2;
6049         } else if (flags & EXP_VARTILDE2) {
6050                 reject++;
6051         }
6052         inquotes = 0;
6053         length = 0;
6054         if (flags & EXP_TILDE) {
6055                 char *q;
6056
6057                 flags &= ~EXP_TILDE;
6058  tilde:
6059                 q = p;
6060                 if ((unsigned char)*q == CTLESC && (flags & EXP_QWORD))
6061                         q++;
6062                 if (*q == '~')
6063                         p = exptilde(p, q, flags);
6064         }
6065  start:
6066         startloc = expdest - (char *)stackblock();
6067         for (;;) {
6068                 unsigned char c;
6069
6070                 length += strcspn(p + length, reject);
6071                 c = p[length];
6072                 if (c) {
6073                         if (!(c & 0x80)
6074                         IF_SH_MATH_SUPPORT(|| c == CTLENDARI)
6075                         ) {
6076                                 /* c == '=' || c == ':' || c == CTLENDARI */
6077                                 length++;
6078                         }
6079                 }
6080                 if (length > 0) {
6081                         int newloc;
6082                         expdest = stack_nputstr(p, length, expdest);
6083                         newloc = expdest - (char *)stackblock();
6084                         if (breakall && !inquotes && newloc > startloc) {
6085                                 recordregion(startloc, newloc, 0);
6086                         }
6087                         startloc = newloc;
6088                 }
6089                 p += length + 1;
6090                 length = 0;
6091
6092                 switch (c) {
6093                 case '\0':
6094                         goto breakloop;
6095                 case '=':
6096                         if (flags & EXP_VARTILDE2) {
6097                                 p--;
6098                                 continue;
6099                         }
6100                         flags |= EXP_VARTILDE2;
6101                         reject++;
6102                         /* fall through */
6103                 case ':':
6104                         /*
6105                          * sort of a hack - expand tildes in variable
6106                          * assignments (after the first '=' and after ':'s).
6107                          */
6108                         if (*--p == '~') {
6109                                 goto tilde;
6110                         }
6111                         continue;
6112                 }
6113
6114                 switch (c) {
6115                 case CTLENDVAR: /* ??? */
6116                         goto breakloop;
6117                 case CTLQUOTEMARK:
6118                         /* "$@" syntax adherence hack */
6119                         if (!inquotes
6120                          && memcmp(p, dolatstr, 4) == 0
6121                          && (  p[4] == (char)CTLQUOTEMARK
6122                             || (p[4] == (char)CTLENDVAR && p[5] == (char)CTLQUOTEMARK)
6123                             )
6124                         ) {
6125                                 p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1;
6126                                 goto start;
6127                         }
6128                         inquotes = !inquotes;
6129  addquote:
6130                         if (quotes) {
6131                                 p--;
6132                                 length++;
6133                                 startloc++;
6134                         }
6135                         break;
6136                 case CTLESC:
6137                         startloc++;
6138                         length++;
6139                         goto addquote;
6140                 case CTLVAR:
6141                         p = evalvar(p, flags, var_str_list);
6142                         goto start;
6143                 case CTLBACKQ:
6144                         c = '\0';
6145                 case CTLBACKQ|CTLQUOTE:
6146                         expbackq(argbackq->n, c, quotes);
6147                         argbackq = argbackq->next;
6148                         goto start;
6149 #if ENABLE_SH_MATH_SUPPORT
6150                 case CTLENDARI:
6151                         p--;
6152                         expari(quotes);
6153                         goto start;
6154 #endif
6155                 }
6156         }
6157  breakloop: ;
6158 }
6159
6160 static char *
6161 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6162                 char *pattern, int quotes, int zero)
6163 {
6164         char *loc, *loc2;
6165         char c;
6166
6167         loc = startp;
6168         loc2 = rmesc;
6169         do {
6170                 int match;
6171                 const char *s = loc2;
6172
6173                 c = *loc2;
6174                 if (zero) {
6175                         *loc2 = '\0';
6176                         s = rmesc;
6177                 }
6178                 match = pmatch(pattern, s);
6179
6180                 *loc2 = c;
6181                 if (match)
6182                         return loc;
6183                 if (quotes && (unsigned char)*loc == CTLESC)
6184                         loc++;
6185                 loc++;
6186                 loc2++;
6187         } while (c);
6188         return NULL;
6189 }
6190
6191 static char *
6192 scanright(char *startp, char *rmesc, char *rmescend,
6193                 char *pattern, int quotes, int match_at_start)
6194 {
6195 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6196         int try2optimize = match_at_start;
6197 #endif
6198         int esc = 0;
6199         char *loc;
6200         char *loc2;
6201
6202         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6203          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6204          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6205          * Logic:
6206          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6207          * and on each iteration they go back two/one char until they reach the beginning.
6208          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6209          */
6210         /* TODO: document in what other circumstances we are called. */
6211
6212         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6213                 int match;
6214                 char c = *loc2;
6215                 const char *s = loc2;
6216                 if (match_at_start) {
6217                         *loc2 = '\0';
6218                         s = rmesc;
6219                 }
6220                 match = pmatch(pattern, s);
6221                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6222                 *loc2 = c;
6223                 if (match)
6224                         return loc;
6225 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6226                 if (try2optimize) {
6227                         /* Maybe we can optimize this:
6228                          * if pattern ends with unescaped *, we can avoid checking
6229                          * shorter strings: if "foo*" doesnt match "raw_value_of_v",
6230                          * it wont match truncated "raw_value_of_" strings too.
6231                          */
6232                         unsigned plen = strlen(pattern);
6233                         /* Does it end with "*"? */
6234                         if (plen != 0 && pattern[--plen] == '*') {
6235                                 /* "xxxx*" is not escaped */
6236                                 /* "xxx\*" is escaped */
6237                                 /* "xx\\*" is not escaped */
6238                                 /* "x\\\*" is escaped */
6239                                 int slashes = 0;
6240                                 while (plen != 0 && pattern[--plen] == '\\')
6241                                         slashes++;
6242                                 if (!(slashes & 1))
6243                                         break; /* ends with unescaped "*" */
6244                         }
6245                         try2optimize = 0;
6246                 }
6247 #endif
6248                 loc--;
6249                 if (quotes) {
6250                         if (--esc < 0) {
6251                                 esc = esclen(startp, loc);
6252                         }
6253                         if (esc % 2) {
6254                                 esc--;
6255                                 loc--;
6256                         }
6257                 }
6258         }
6259         return NULL;
6260 }
6261
6262 static void varunset(const char *, const char *, const char *, int) NORETURN;
6263 static void
6264 varunset(const char *end, const char *var, const char *umsg, int varflags)
6265 {
6266         const char *msg;
6267         const char *tail;
6268
6269         tail = nullstr;
6270         msg = "parameter not set";
6271         if (umsg) {
6272                 if ((unsigned char)*end == CTLENDVAR) {
6273                         if (varflags & VSNUL)
6274                                 tail = " or null";
6275                 } else {
6276                         msg = umsg;
6277                 }
6278         }
6279         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6280 }
6281
6282 #if ENABLE_ASH_BASH_COMPAT
6283 static char *
6284 parse_sub_pattern(char *arg, int varflags)
6285 {
6286         char *idx, *repl = NULL;
6287         unsigned char c;
6288
6289         //char *org_arg = arg;
6290         //bb_error_msg("arg:'%s' varflags:%x", arg, varflags);
6291         idx = arg;
6292         while (1) {
6293                 c = *arg;
6294                 if (!c)
6295                         break;
6296                 if (c == '/') {
6297                         /* Only the first '/' seen is our separator */
6298                         if (!repl) {
6299                                 repl = idx + 1;
6300                                 c = '\0';
6301                         }
6302                 }
6303                 *idx++ = c;
6304                 arg++;
6305                 /*
6306                  * Example: v='ab\c'; echo ${v/\\b/_\\_\z_}
6307                  * The result is a_\_z_c (not a\_\_z_c)!
6308                  *
6309                  * Enable debug prints in this function and you'll see:
6310                  * ash: arg:'\\b/_\\_z_' varflags:d
6311                  * ash: pattern:'\\b' repl:'_\_z_'
6312                  * That is, \\b is interpreted as \\b, but \\_ as \_!
6313                  * IOW: search pattern and replace string treat backslashes
6314                  * differently! That is the reason why we check repl below:
6315                  */
6316                 if (c == '\\' && *arg == '\\' && repl && !(varflags & VSQUOTE))
6317                         arg++; /* skip both '\', not just first one */
6318         }
6319         *idx = c; /* NUL */
6320         //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl);
6321
6322         return repl;
6323 }
6324 #endif /* ENABLE_ASH_BASH_COMPAT */
6325
6326 static const char *
6327 subevalvar(char *p, char *varname, int strloc, int subtype,
6328                 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6329 {
6330         struct nodelist *saveargbackq = argbackq;
6331         char *startp;
6332         char *loc;
6333         char *rmesc, *rmescend;
6334         char *str;
6335         IF_ASH_BASH_COMPAT(const char *repl = NULL;)
6336         IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
6337         int saveherefd = herefd;
6338         int amount, workloc, resetloc;
6339         int zero;
6340         char *(*scan)(char*, char*, char*, char*, int, int);
6341
6342         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6343         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6344
6345         herefd = -1;
6346         argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6347                         var_str_list);
6348         STPUTC('\0', expdest);
6349         herefd = saveherefd;
6350         argbackq = saveargbackq;
6351         startp = (char *)stackblock() + startloc;
6352
6353         switch (subtype) {
6354         case VSASSIGN:
6355                 setvar(varname, startp, 0);
6356                 amount = startp - expdest;
6357                 STADJUST(amount, expdest);
6358                 return startp;
6359
6360         case VSQUESTION:
6361                 varunset(p, varname, startp, varflags);
6362                 /* NOTREACHED */
6363
6364 #if ENABLE_ASH_BASH_COMPAT
6365         case VSSUBSTR:
6366                 loc = str = stackblock() + strloc;
6367                 /* Read POS in ${var:POS:LEN} */
6368                 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6369                 len = str - startp - 1;
6370
6371                 /* *loc != '\0', guaranteed by parser */
6372                 if (quotes) {
6373                         char *ptr;
6374
6375                         /* Adjust the length by the number of escapes */
6376                         for (ptr = startp; ptr < (str - 1); ptr++) {
6377                                 if ((unsigned char)*ptr == CTLESC) {
6378                                         len--;
6379                                         ptr++;
6380                                 }
6381                         }
6382                 }
6383                 orig_len = len;
6384
6385                 if (*loc++ == ':') {
6386                         /* ${var::LEN} */
6387                         len = number(loc);
6388                 } else {
6389                         /* Skip POS in ${var:POS:LEN} */
6390                         len = orig_len;
6391                         while (*loc && *loc != ':') {
6392                                 /* TODO?
6393                                  * bash complains on: var=qwe; echo ${var:1a:123}
6394                                 if (!isdigit(*loc))
6395                                         ash_msg_and_raise_error(msg_illnum, str);
6396                                  */
6397                                 loc++;
6398                         }
6399                         if (*loc++ == ':') {
6400                                 len = number(loc);
6401                         }
6402                 }
6403                 if (pos >= orig_len) {
6404                         pos = 0;
6405                         len = 0;
6406                 }
6407                 if (len > (orig_len - pos))
6408                         len = orig_len - pos;
6409
6410                 for (str = startp; pos; str++, pos--) {
6411                         if (quotes && (unsigned char)*str == CTLESC)
6412                                 str++;
6413                 }
6414                 for (loc = startp; len; len--) {
6415                         if (quotes && (unsigned char)*str == CTLESC)
6416                                 *loc++ = *str++;
6417                         *loc++ = *str++;
6418                 }
6419                 *loc = '\0';
6420                 amount = loc - expdest;
6421                 STADJUST(amount, expdest);
6422                 return loc;
6423 #endif
6424         }
6425
6426         resetloc = expdest - (char *)stackblock();
6427
6428         /* We'll comeback here if we grow the stack while handling
6429          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6430          * stack will need rebasing, and we'll need to remove our work
6431          * areas each time
6432          */
6433  IF_ASH_BASH_COMPAT(restart:)
6434
6435         amount = expdest - ((char *)stackblock() + resetloc);
6436         STADJUST(-amount, expdest);
6437         startp = (char *)stackblock() + startloc;
6438
6439         rmesc = startp;
6440         rmescend = (char *)stackblock() + strloc;
6441         if (quotes) {
6442                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6443                 if (rmesc != startp) {
6444                         rmescend = expdest;
6445                         startp = (char *)stackblock() + startloc;
6446                 }
6447         }
6448         rmescend--;
6449         str = (char *)stackblock() + strloc;
6450         preglob(str, varflags & VSQUOTE, 0);
6451         workloc = expdest - (char *)stackblock();
6452
6453 #if ENABLE_ASH_BASH_COMPAT
6454         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6455                 char *idx, *end;
6456
6457                 if (!repl) {
6458                         repl = parse_sub_pattern(str, varflags);
6459                         //bb_error_msg("repl:'%s'", repl);
6460                         if (!repl)
6461                                 repl = nullstr;
6462                 }
6463
6464                 /* If there's no pattern to match, return the expansion unmolested */
6465                 if (str[0] == '\0')
6466                         return NULL;
6467
6468                 len = 0;
6469                 idx = startp;
6470                 end = str - 1;
6471                 while (idx < end) {
6472  try_to_match:
6473                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6474                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6475                         if (!loc) {
6476                                 /* No match, advance */
6477                                 char *restart_detect = stackblock();
6478  skip_matching:
6479                                 STPUTC(*idx, expdest);
6480                                 if (quotes && (unsigned char)*idx == CTLESC) {
6481                                         idx++;
6482                                         len++;
6483                                         STPUTC(*idx, expdest);
6484                                 }
6485                                 if (stackblock() != restart_detect)
6486                                         goto restart;
6487                                 idx++;
6488                                 len++;
6489                                 rmesc++;
6490                                 /* continue; - prone to quadratic behavior, smarter code: */
6491                                 if (idx >= end)
6492                                         break;
6493                                 if (str[0] == '*') {
6494                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6495                                          * it would never match "ong_string" etc, no point in trying.
6496                                          */
6497                                         goto skip_matching;
6498                                 }
6499                                 goto try_to_match;
6500                         }
6501
6502                         if (subtype == VSREPLACEALL) {
6503                                 while (idx < loc) {
6504                                         if (quotes && (unsigned char)*idx == CTLESC)
6505                                                 idx++;
6506                                         idx++;
6507                                         rmesc++;
6508                                 }
6509                         } else {
6510                                 idx = loc;
6511                         }
6512
6513                         //bb_error_msg("repl:'%s'", repl);
6514                         for (loc = (char*)repl; *loc; loc++) {
6515                                 char *restart_detect = stackblock();
6516                                 if (quotes && *loc == '\\') {
6517                                         STPUTC(CTLESC, expdest);
6518                                         len++;
6519                                 }
6520                                 STPUTC(*loc, expdest);
6521                                 if (stackblock() != restart_detect)
6522                                         goto restart;
6523                                 len++;
6524                         }
6525
6526                         if (subtype == VSREPLACE) {
6527                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6528                                 while (*idx) {
6529                                         char *restart_detect = stackblock();
6530                                         STPUTC(*idx, expdest);
6531                                         if (stackblock() != restart_detect)
6532                                                 goto restart;
6533                                         len++;
6534                                         idx++;
6535                                 }
6536                                 break;
6537                         }
6538                 }
6539
6540                 /* We've put the replaced text into a buffer at workloc, now
6541                  * move it to the right place and adjust the stack.
6542                  */
6543                 STPUTC('\0', expdest);
6544                 startp = (char *)stackblock() + startloc;
6545                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6546                 //bb_error_msg("startp:'%s'", startp);
6547                 amount = expdest - (startp + len);
6548                 STADJUST(-amount, expdest);
6549                 return startp;
6550         }
6551 #endif /* ENABLE_ASH_BASH_COMPAT */
6552
6553         subtype -= VSTRIMRIGHT;
6554 #if DEBUG
6555         if (subtype < 0 || subtype > 7)
6556                 abort();
6557 #endif
6558         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6559         zero = subtype >> 1;
6560         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6561         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6562
6563         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6564         if (loc) {
6565                 if (zero) {
6566                         memmove(startp, loc, str - loc);
6567                         loc = startp + (str - loc) - 1;
6568                 }
6569                 *loc = '\0';
6570                 amount = loc - expdest;
6571                 STADJUST(amount, expdest);
6572         }
6573         return loc;
6574 }
6575
6576 /*
6577  * Add the value of a specialized variable to the stack string.
6578  * name parameter (examples):
6579  * ash -c 'echo $1'      name:'1='
6580  * ash -c 'echo $qwe'    name:'qwe='
6581  * ash -c 'echo $$'      name:'$='
6582  * ash -c 'echo ${$}'    name:'$='
6583  * ash -c 'echo ${$##q}' name:'$=q'
6584  * ash -c 'echo ${#$}'   name:'$='
6585  * note: examples with bad shell syntax:
6586  * ash -c 'echo ${#$1}'  name:'$=1'
6587  * ash -c 'echo ${#1#}'  name:'1=#'
6588  */
6589 static NOINLINE ssize_t
6590 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6591 {
6592         const char *p;
6593         int num;
6594         int i;
6595         int sepq = 0;
6596         ssize_t len = 0;
6597         int subtype = varflags & VSTYPE;
6598         int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR);
6599         int quoted = varflags & VSQUOTE;
6600         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
6601
6602         switch (*name) {
6603         case '$':
6604                 num = rootpid;
6605                 goto numvar;
6606         case '?':
6607                 num = exitstatus;
6608                 goto numvar;
6609         case '#':
6610                 num = shellparam.nparam;
6611                 goto numvar;
6612         case '!':
6613                 num = backgndpid;
6614                 if (num == 0)
6615                         return -1;
6616  numvar:
6617                 len = cvtnum(num);
6618                 goto check_1char_name;
6619         case '-':
6620                 expdest = makestrspace(NOPTS, expdest);
6621                 for (i = NOPTS - 1; i >= 0; i--) {
6622                         if (optlist[i]) {
6623                                 USTPUTC(optletters(i), expdest);
6624                                 len++;
6625                         }
6626                 }
6627  check_1char_name:
6628 #if 0
6629                 /* handles cases similar to ${#$1} */
6630                 if (name[2] != '\0')
6631                         raise_error_syntax("bad substitution");
6632 #endif
6633                 break;
6634         case '@': {
6635                 char **ap;
6636                 int sep;
6637
6638                 if (quoted && (flags & EXP_FULL)) {
6639                         /* note: this is not meant as PEOF value */
6640                         sep = 1 << CHAR_BIT;
6641                         goto param;
6642                 }
6643                 /* fall through */
6644         case '*':
6645                 sep = ifsset() ? (unsigned char)(ifsval()[0]) : ' ';
6646                 i = SIT(sep, syntax);
6647                 if (quotes && (i == CCTL || i == CBACK))
6648                         sepq = 1;
6649  param:
6650                 ap = shellparam.p;
6651                 if (!ap)
6652                         return -1;
6653                 while ((p = *ap++) != NULL) {
6654                         size_t partlen;
6655
6656                         partlen = strlen(p);
6657                         len += partlen;
6658
6659                         if (!(subtype == VSPLUS || subtype == VSLENGTH))
6660                                 memtodest(p, partlen, syntax, quotes);
6661
6662                         if (*ap && sep) {
6663                                 char *q;
6664
6665                                 len++;
6666                                 if (subtype == VSPLUS || subtype == VSLENGTH) {
6667                                         continue;
6668                                 }
6669                                 q = expdest;
6670                                 if (sepq)
6671                                         STPUTC(CTLESC, q);
6672                                 /* note: may put NUL despite sep != 0
6673                                  * (see sep = 1 << CHAR_BIT above) */
6674                                 STPUTC(sep, q);
6675                                 expdest = q;
6676                         }
6677                 }
6678                 return len;
6679         } /* case '@' and '*' */
6680         case '0':
6681         case '1':
6682         case '2':
6683         case '3':
6684         case '4':
6685         case '5':
6686         case '6':
6687         case '7':
6688         case '8':
6689         case '9':
6690                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6691                 if (num < 0 || num > shellparam.nparam)
6692                         return -1;
6693                 p = num ? shellparam.p[num - 1] : arg0;
6694                 goto value;
6695         default:
6696                 /* NB: name has form "VAR=..." */
6697
6698                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6699                  * which should be considered before we check variables. */
6700                 if (var_str_list) {
6701                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6702                         p = NULL;
6703                         do {
6704                                 char *str, *eq;
6705                                 str = var_str_list->text;
6706                                 eq = strchr(str, '=');
6707                                 if (!eq) /* stop at first non-assignment */
6708                                         break;
6709                                 eq++;
6710                                 if (name_len == (unsigned)(eq - str)
6711                                  && strncmp(str, name, name_len) == 0
6712                                 ) {
6713                                         p = eq;
6714                                         /* goto value; - WRONG! */
6715                                         /* think "A=1 A=2 B=$A" */
6716                                 }
6717                                 var_str_list = var_str_list->next;
6718                         } while (var_str_list);
6719                         if (p)
6720                                 goto value;
6721                 }
6722                 p = lookupvar(name);
6723  value:
6724                 if (!p)
6725                         return -1;
6726
6727                 len = strlen(p);
6728                 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6729                         memtodest(p, len, syntax, quotes);
6730                 return len;
6731         }
6732
6733         if (subtype == VSPLUS || subtype == VSLENGTH)
6734                 STADJUST(-len, expdest);
6735         return len;
6736 }
6737
6738 /*
6739  * Expand a variable, and return a pointer to the next character in the
6740  * input string.
6741  */
6742 static char *
6743 evalvar(char *p, int flags, struct strlist *var_str_list)
6744 {
6745         char varflags;
6746         char subtype;
6747         char quoted;
6748         char easy;
6749         char *var;
6750         int patloc;
6751         int startloc;
6752         ssize_t varlen;
6753
6754         varflags = (unsigned char) *p++;
6755         subtype = varflags & VSTYPE;
6756         quoted = varflags & VSQUOTE;
6757         var = p;
6758         easy = (!quoted || (*var == '@' && shellparam.nparam));
6759         startloc = expdest - (char *)stackblock();
6760         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
6761
6762  again:
6763         varlen = varvalue(var, varflags, flags, var_str_list);
6764         if (varflags & VSNUL)
6765                 varlen--;
6766
6767         if (subtype == VSPLUS) {
6768                 varlen = -1 - varlen;
6769                 goto vsplus;
6770         }
6771
6772         if (subtype == VSMINUS) {
6773  vsplus:
6774                 if (varlen < 0) {
6775                         argstr(
6776                                 p,
6777                                 flags | (quoted ? EXP_TILDE|EXP_QWORD : EXP_TILDE|EXP_WORD),
6778                                 var_str_list
6779                         );
6780                         goto end;
6781                 }
6782                 if (easy)
6783                         goto record;
6784                 goto end;
6785         }
6786
6787         if (subtype == VSASSIGN || subtype == VSQUESTION) {
6788                 if (varlen < 0) {
6789                         if (subevalvar(p, var, /* strloc: */ 0,
6790                                         subtype, startloc, varflags,
6791                                         /* quotes: */ 0,
6792                                         var_str_list)
6793                         ) {
6794                                 varflags &= ~VSNUL;
6795                                 /*
6796                                  * Remove any recorded regions beyond
6797                                  * start of variable
6798                                  */
6799                                 removerecordregions(startloc);
6800                                 goto again;
6801                         }
6802                         goto end;
6803                 }
6804                 if (easy)
6805                         goto record;
6806                 goto end;
6807         }
6808
6809         if (varlen < 0 && uflag)
6810                 varunset(p, var, 0, 0);
6811
6812         if (subtype == VSLENGTH) {
6813                 cvtnum(varlen > 0 ? varlen : 0);
6814                 goto record;
6815         }
6816
6817         if (subtype == VSNORMAL) {
6818                 if (easy)
6819                         goto record;
6820                 goto end;
6821         }
6822
6823 #if DEBUG
6824         switch (subtype) {
6825         case VSTRIMLEFT:
6826         case VSTRIMLEFTMAX:
6827         case VSTRIMRIGHT:
6828         case VSTRIMRIGHTMAX:
6829 #if ENABLE_ASH_BASH_COMPAT
6830         case VSSUBSTR:
6831         case VSREPLACE:
6832         case VSREPLACEALL:
6833 #endif
6834                 break;
6835         default:
6836                 abort();
6837         }
6838 #endif
6839
6840         if (varlen >= 0) {
6841                 /*
6842                  * Terminate the string and start recording the pattern
6843                  * right after it
6844                  */
6845                 STPUTC('\0', expdest);
6846                 patloc = expdest - (char *)stackblock();
6847                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
6848                                 startloc, varflags,
6849 //TODO: | EXP_REDIR too? All other such places do it too
6850                                 /* quotes: */ flags & (EXP_FULL | EXP_CASE),
6851                                 var_str_list)
6852                 ) {
6853                         int amount = expdest - (
6854                                 (char *)stackblock() + patloc - 1
6855                         );
6856                         STADJUST(-amount, expdest);
6857                 }
6858                 /* Remove any recorded regions beyond start of variable */
6859                 removerecordregions(startloc);
6860  record:
6861                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6862         }
6863
6864  end:
6865         if (subtype != VSNORMAL) {      /* skip to end of alternative */
6866                 int nesting = 1;
6867                 for (;;) {
6868                         unsigned char c = *p++;
6869                         if (c == CTLESC)
6870                                 p++;
6871                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6872                                 if (varlen >= 0)
6873                                         argbackq = argbackq->next;
6874                         } else if (c == CTLVAR) {
6875                                 if ((*p++ & VSTYPE) != VSNORMAL)
6876                                         nesting++;
6877                         } else if (c == CTLENDVAR) {
6878                                 if (--nesting == 0)
6879                                         break;
6880                         }
6881                 }
6882         }
6883         return p;
6884 }
6885
6886 /*
6887  * Break the argument string into pieces based upon IFS and add the
6888  * strings to the argument list.  The regions of the string to be
6889  * searched for IFS characters have been stored by recordregion.
6890  */
6891 static void
6892 ifsbreakup(char *string, struct arglist *arglist)
6893 {
6894         struct ifsregion *ifsp;
6895         struct strlist *sp;
6896         char *start;
6897         char *p;
6898         char *q;
6899         const char *ifs, *realifs;
6900         int ifsspc;
6901         int nulonly;
6902
6903         start = string;
6904         if (ifslastp != NULL) {
6905                 ifsspc = 0;
6906                 nulonly = 0;
6907                 realifs = ifsset() ? ifsval() : defifs;
6908                 ifsp = &ifsfirst;
6909                 do {
6910                         p = string + ifsp->begoff;
6911                         nulonly = ifsp->nulonly;
6912                         ifs = nulonly ? nullstr : realifs;
6913                         ifsspc = 0;
6914                         while (p < string + ifsp->endoff) {
6915                                 q = p;
6916                                 if ((unsigned char)*p == CTLESC)
6917                                         p++;
6918                                 if (!strchr(ifs, *p)) {
6919                                         p++;
6920                                         continue;
6921                                 }
6922                                 if (!nulonly)
6923                                         ifsspc = (strchr(defifs, *p) != NULL);
6924                                 /* Ignore IFS whitespace at start */
6925                                 if (q == start && ifsspc) {
6926                                         p++;
6927                                         start = p;
6928                                         continue;
6929                                 }
6930                                 *q = '\0';
6931                                 sp = stzalloc(sizeof(*sp));
6932                                 sp->text = start;
6933                                 *arglist->lastp = sp;
6934                                 arglist->lastp = &sp->next;
6935                                 p++;
6936                                 if (!nulonly) {
6937                                         for (;;) {
6938                                                 if (p >= string + ifsp->endoff) {
6939                                                         break;
6940                                                 }
6941                                                 q = p;
6942                                                 if ((unsigned char)*p == CTLESC)
6943                                                         p++;
6944                                                 if (strchr(ifs, *p) == NULL) {
6945                                                         p = q;
6946                                                         break;
6947                                                 }
6948                                                 if (strchr(defifs, *p) == NULL) {
6949                                                         if (ifsspc) {
6950                                                                 p++;
6951                                                                 ifsspc = 0;
6952                                                         } else {
6953                                                                 p = q;
6954                                                                 break;
6955                                                         }
6956                                                 } else
6957                                                         p++;
6958                                         }
6959                                 }
6960                                 start = p;
6961                         } /* while */
6962                         ifsp = ifsp->next;
6963                 } while (ifsp != NULL);
6964                 if (nulonly)
6965                         goto add;
6966         }
6967
6968         if (!*start)
6969                 return;
6970
6971  add:
6972         sp = stzalloc(sizeof(*sp));
6973         sp->text = start;
6974         *arglist->lastp = sp;
6975         arglist->lastp = &sp->next;
6976 }
6977
6978 static void
6979 ifsfree(void)
6980 {
6981         struct ifsregion *p;
6982
6983         INT_OFF;
6984         p = ifsfirst.next;
6985         do {
6986                 struct ifsregion *ifsp;
6987                 ifsp = p->next;
6988                 free(p);
6989                 p = ifsp;
6990         } while (p);
6991         ifslastp = NULL;
6992         ifsfirst.next = NULL;
6993         INT_ON;
6994 }
6995
6996 /*
6997  * Add a file name to the list.
6998  */
6999 static void
7000 addfname(const char *name)
7001 {
7002         struct strlist *sp;
7003
7004         sp = stzalloc(sizeof(*sp));
7005         sp->text = ststrdup(name);
7006         *exparg.lastp = sp;
7007         exparg.lastp = &sp->next;
7008 }
7009
7010 /*
7011  * Do metacharacter (i.e. *, ?, [...]) expansion.
7012  */
7013 static void
7014 expmeta(char *expdir, char *enddir, char *name)
7015 {
7016         char *p;
7017         const char *cp;
7018         char *start;
7019         char *endname;
7020         int metaflag;
7021         struct stat statb;
7022         DIR *dirp;
7023         struct dirent *dp;
7024         int atend;
7025         int matchdot;
7026
7027         metaflag = 0;
7028         start = name;
7029         for (p = name; *p; p++) {
7030                 if (*p == '*' || *p == '?')
7031                         metaflag = 1;
7032                 else if (*p == '[') {
7033                         char *q = p + 1;
7034                         if (*q == '!')
7035                                 q++;
7036                         for (;;) {
7037                                 if (*q == '\\')
7038                                         q++;
7039                                 if (*q == '/' || *q == '\0')
7040                                         break;
7041                                 if (*++q == ']') {
7042                                         metaflag = 1;
7043                                         break;
7044                                 }
7045                         }
7046                 } else if (*p == '\\')
7047                         p++;
7048                 else if (*p == '/') {
7049                         if (metaflag)
7050                                 goto out;
7051                         start = p + 1;
7052                 }
7053         }
7054  out:
7055         if (metaflag == 0) {    /* we've reached the end of the file name */
7056                 if (enddir != expdir)
7057                         metaflag++;
7058                 p = name;
7059                 do {
7060                         if (*p == '\\')
7061                                 p++;
7062                         *enddir++ = *p;
7063                 } while (*p++);
7064                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7065                         addfname(expdir);
7066                 return;
7067         }
7068         endname = p;
7069         if (name < start) {
7070                 p = name;
7071                 do {
7072                         if (*p == '\\')
7073                                 p++;
7074                         *enddir++ = *p++;
7075                 } while (p < start);
7076         }
7077         if (enddir == expdir) {
7078                 cp = ".";
7079         } else if (enddir == expdir + 1 && *expdir == '/') {
7080                 cp = "/";
7081         } else {
7082                 cp = expdir;
7083                 enddir[-1] = '\0';
7084         }
7085         dirp = opendir(cp);
7086         if (dirp == NULL)
7087                 return;
7088         if (enddir != expdir)
7089                 enddir[-1] = '/';
7090         if (*endname == 0) {
7091                 atend = 1;
7092         } else {
7093                 atend = 0;
7094                 *endname++ = '\0';
7095         }
7096         matchdot = 0;
7097         p = start;
7098         if (*p == '\\')
7099                 p++;
7100         if (*p == '.')
7101                 matchdot++;
7102         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7103                 if (dp->d_name[0] == '.' && !matchdot)
7104                         continue;
7105                 if (pmatch(start, dp->d_name)) {
7106                         if (atend) {
7107                                 strcpy(enddir, dp->d_name);
7108                                 addfname(expdir);
7109                         } else {
7110                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7111                                         continue;
7112                                 p[-1] = '/';
7113                                 expmeta(expdir, p, endname);
7114                         }
7115                 }
7116         }
7117         closedir(dirp);
7118         if (!atend)
7119                 endname[-1] = '/';
7120 }
7121
7122 static struct strlist *
7123 msort(struct strlist *list, int len)
7124 {
7125         struct strlist *p, *q = NULL;
7126         struct strlist **lpp;
7127         int half;
7128         int n;
7129
7130         if (len <= 1)
7131                 return list;
7132         half = len >> 1;
7133         p = list;
7134         for (n = half; --n >= 0;) {
7135                 q = p;
7136                 p = p->next;
7137         }
7138         q->next = NULL;                 /* terminate first half of list */
7139         q = msort(list, half);          /* sort first half of list */
7140         p = msort(p, len - half);               /* sort second half */
7141         lpp = &list;
7142         for (;;) {
7143 #if ENABLE_LOCALE_SUPPORT
7144                 if (strcoll(p->text, q->text) < 0)
7145 #else
7146                 if (strcmp(p->text, q->text) < 0)
7147 #endif
7148                                                 {
7149                         *lpp = p;
7150                         lpp = &p->next;
7151                         p = *lpp;
7152                         if (p == NULL) {
7153                                 *lpp = q;
7154                                 break;
7155                         }
7156                 } else {
7157                         *lpp = q;
7158                         lpp = &q->next;
7159                         q = *lpp;
7160                         if (q == NULL) {
7161                                 *lpp = p;
7162                                 break;
7163                         }
7164                 }
7165         }
7166         return list;
7167 }
7168
7169 /*
7170  * Sort the results of file name expansion.  It calculates the number of
7171  * strings to sort and then calls msort (short for merge sort) to do the
7172  * work.
7173  */
7174 static struct strlist *
7175 expsort(struct strlist *str)
7176 {
7177         int len;
7178         struct strlist *sp;
7179
7180         len = 0;
7181         for (sp = str; sp; sp = sp->next)
7182                 len++;
7183         return msort(str, len);
7184 }
7185
7186 static void
7187 expandmeta(struct strlist *str /*, int flag*/)
7188 {
7189         static const char metachars[] ALIGN1 = {
7190                 '*', '?', '[', 0
7191         };
7192         /* TODO - EXP_REDIR */
7193
7194         while (str) {
7195                 char *expdir;
7196                 struct strlist **savelastp;
7197                 struct strlist *sp;
7198                 char *p;
7199
7200                 if (fflag)
7201                         goto nometa;
7202                 if (!strpbrk(str->text, metachars))
7203                         goto nometa;
7204                 savelastp = exparg.lastp;
7205
7206                 INT_OFF;
7207                 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7208                 {
7209                         int i = strlen(str->text);
7210                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
7211                 }
7212                 expmeta(expdir, expdir, p);
7213                 free(expdir);
7214                 if (p != str->text)
7215                         free(p);
7216                 INT_ON;
7217                 if (exparg.lastp == savelastp) {
7218                         /*
7219                          * no matches
7220                          */
7221  nometa:
7222                         *exparg.lastp = str;
7223                         rmescapes(str->text, 0);
7224                         exparg.lastp = &str->next;
7225                 } else {
7226                         *exparg.lastp = NULL;
7227                         *savelastp = sp = expsort(*savelastp);
7228                         while (sp->next != NULL)
7229                                 sp = sp->next;
7230                         exparg.lastp = &sp->next;
7231                 }
7232                 str = str->next;
7233         }
7234 }
7235
7236 /*
7237  * Perform variable substitution and command substitution on an argument,
7238  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7239  * perform splitting and file name expansion.  When arglist is NULL, perform
7240  * here document expansion.
7241  */
7242 static void
7243 expandarg(union node *arg, struct arglist *arglist, int flag)
7244 {
7245         struct strlist *sp;
7246         char *p;
7247
7248         argbackq = arg->narg.backquote;
7249         STARTSTACKSTR(expdest);
7250         ifsfirst.next = NULL;
7251         ifslastp = NULL;
7252         argstr(arg->narg.text, flag,
7253                         /* var_str_list: */ arglist ? arglist->list : NULL);
7254         p = _STPUTC('\0', expdest);
7255         expdest = p - 1;
7256         if (arglist == NULL) {
7257                 return;                 /* here document expanded */
7258         }
7259         p = grabstackstr(p);
7260         exparg.lastp = &exparg.list;
7261         /*
7262          * TODO - EXP_REDIR
7263          */
7264         if (flag & EXP_FULL) {
7265                 ifsbreakup(p, &exparg);
7266                 *exparg.lastp = NULL;
7267                 exparg.lastp = &exparg.list;
7268                 expandmeta(exparg.list /*, flag*/);
7269         } else {
7270                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
7271                         rmescapes(p, 0);
7272                 sp = stzalloc(sizeof(*sp));
7273                 sp->text = p;
7274                 *exparg.lastp = sp;
7275                 exparg.lastp = &sp->next;
7276         }
7277         if (ifsfirst.next)
7278                 ifsfree();
7279         *exparg.lastp = NULL;
7280         if (exparg.list) {
7281                 *arglist->lastp = exparg.list;
7282                 arglist->lastp = exparg.lastp;
7283         }
7284 }
7285
7286 /*
7287  * Expand shell variables and backquotes inside a here document.
7288  */
7289 static void
7290 expandhere(union node *arg, int fd)
7291 {
7292         herefd = fd;
7293         expandarg(arg, (struct arglist *)NULL, 0);
7294         full_write(fd, stackblock(), expdest - (char *)stackblock());
7295 }
7296
7297 /*
7298  * Returns true if the pattern matches the string.
7299  */
7300 static int
7301 patmatch(char *pattern, const char *string)
7302 {
7303         return pmatch(preglob(pattern, 0, 0), string);
7304 }
7305
7306 /*
7307  * See if a pattern matches in a case statement.
7308  */
7309 static int
7310 casematch(union node *pattern, char *val)
7311 {
7312         struct stackmark smark;
7313         int result;
7314
7315         setstackmark(&smark);
7316         argbackq = pattern->narg.backquote;
7317         STARTSTACKSTR(expdest);
7318         ifslastp = NULL;
7319         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7320                         /* var_str_list: */ NULL);
7321         STACKSTRNUL(expdest);
7322         result = patmatch(stackblock(), val);
7323         popstackmark(&smark);
7324         return result;
7325 }
7326
7327
7328 /* ============ find_command */
7329
7330 struct builtincmd {
7331         const char *name;
7332         int (*builtin)(int, char **) FAST_FUNC;
7333         /* unsigned flags; */
7334 };
7335 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7336 /* "regular" builtins always take precedence over commands,
7337  * regardless of PATH=....%builtin... position */
7338 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7339 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7340
7341 struct cmdentry {
7342         smallint cmdtype;       /* CMDxxx */
7343         union param {
7344                 int index;
7345                 /* index >= 0 for commands without path (slashes) */
7346                 /* (TODO: what exactly does the value mean? PATH position?) */
7347                 /* index == -1 for commands with slashes */
7348                 /* index == (-2 - applet_no) for NOFORK applets */
7349                 const struct builtincmd *cmd;
7350                 struct funcnode *func;
7351         } u;
7352 };
7353 /* values of cmdtype */
7354 #define CMDUNKNOWN      -1      /* no entry in table for command */
7355 #define CMDNORMAL       0       /* command is an executable program */
7356 #define CMDFUNCTION     1       /* command is a shell function */
7357 #define CMDBUILTIN      2       /* command is a shell builtin */
7358
7359 /* action to find_command() */
7360 #define DO_ERR          0x01    /* prints errors */
7361 #define DO_ABS          0x02    /* checks absolute paths */
7362 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7363 #define DO_ALTPATH      0x08    /* using alternate path */
7364 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7365
7366 static void find_command(char *, struct cmdentry *, int, const char *);
7367
7368
7369 /* ============ Hashing commands */
7370
7371 /*
7372  * When commands are first encountered, they are entered in a hash table.
7373  * This ensures that a full path search will not have to be done for them
7374  * on each invocation.
7375  *
7376  * We should investigate converting to a linear search, even though that
7377  * would make the command name "hash" a misnomer.
7378  */
7379
7380 struct tblentry {
7381         struct tblentry *next;  /* next entry in hash chain */
7382         union param param;      /* definition of builtin function */
7383         smallint cmdtype;       /* CMDxxx */
7384         char rehash;            /* if set, cd done since entry created */
7385         char cmdname[1];        /* name of command */
7386 };
7387
7388 static struct tblentry **cmdtable;
7389 #define INIT_G_cmdtable() do { \
7390         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7391 } while (0)
7392
7393 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7394
7395
7396 static void
7397 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7398 {
7399 #if ENABLE_FEATURE_SH_STANDALONE
7400         if (applet_no >= 0) {
7401                 if (APPLET_IS_NOEXEC(applet_no)) {
7402                         clearenv();
7403                         while (*envp)
7404                                 putenv(*envp++);
7405                         run_applet_no_and_exit(applet_no, argv);
7406                 }
7407                 /* re-exec ourselves with the new arguments */
7408                 execve(bb_busybox_exec_path, argv, envp);
7409                 /* If they called chroot or otherwise made the binary no longer
7410                  * executable, fall through */
7411         }
7412 #endif
7413
7414  repeat:
7415 #ifdef SYSV
7416         do {
7417                 execve(cmd, argv, envp);
7418         } while (errno == EINTR);
7419 #else
7420         execve(cmd, argv, envp);
7421 #endif
7422         if (cmd == (char*) bb_busybox_exec_path) {
7423                 /* We already visited ENOEXEC branch below, don't do it again */
7424 //TODO: try execve(initial_argv0_of_shell, argv, envp) before giving up?
7425                 free(argv);
7426                 return;
7427         }
7428         if (errno == ENOEXEC) {
7429                 /* Run "cmd" as a shell script:
7430                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7431                  * "If the execve() function fails with ENOEXEC, the shell
7432                  * shall execute a command equivalent to having a shell invoked
7433                  * with the command name as its first operand,
7434                  * with any remaining arguments passed to the new shell"
7435                  *
7436                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7437                  * just call ourselves.
7438                  */
7439                 char **ap;
7440                 char **new;
7441
7442                 for (ap = argv; *ap; ap++)
7443                         continue;
7444                 new = ckmalloc((ap - argv + 2) * sizeof(new[0]));
7445                 new[0] = (char*) "ash";
7446                 new[1] = cmd;
7447                 ap = new + 2;
7448                 while ((*ap++ = *++argv) != NULL)
7449                         continue;
7450                 cmd = (char*) bb_busybox_exec_path;
7451                 argv = new;
7452                 goto repeat;
7453         }
7454 }
7455
7456 /*
7457  * Exec a program.  Never returns.  If you change this routine, you may
7458  * have to change the find_command routine as well.
7459  */
7460 static void shellexec(char **, const char *, int) NORETURN;
7461 static void
7462 shellexec(char **argv, const char *path, int idx)
7463 {
7464         char *cmdname;
7465         int e;
7466         char **envp;
7467         int exerrno;
7468 #if ENABLE_FEATURE_SH_STANDALONE
7469         int applet_no = -1;
7470 #endif
7471
7472         clearredir(/*drop:*/ 1);
7473         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7474         if (strchr(argv[0], '/') != NULL
7475 #if ENABLE_FEATURE_SH_STANDALONE
7476          || (applet_no = find_applet_by_name(argv[0])) >= 0
7477 #endif
7478         ) {
7479                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7480                 e = errno;
7481         } else {
7482                 e = ENOENT;
7483                 while ((cmdname = path_advance(&path, argv[0])) != NULL) {
7484                         if (--idx < 0 && pathopt == NULL) {
7485                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7486                                 if (errno != ENOENT && errno != ENOTDIR)
7487                                         e = errno;
7488                         }
7489                         stunalloc(cmdname);
7490                 }
7491         }
7492
7493         /* Map to POSIX errors */
7494         switch (e) {
7495         case EACCES:
7496                 exerrno = 126;
7497                 break;
7498         case ENOENT:
7499                 exerrno = 127;
7500                 break;
7501         default:
7502                 exerrno = 2;
7503                 break;
7504         }
7505         exitstatus = exerrno;
7506         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7507                 argv[0], e, suppress_int));
7508         ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7509         /* NOTREACHED */
7510 }
7511
7512 static void
7513 printentry(struct tblentry *cmdp)
7514 {
7515         int idx;
7516         const char *path;
7517         char *name;
7518
7519         idx = cmdp->param.index;
7520         path = pathval();
7521         do {
7522                 name = path_advance(&path, cmdp->cmdname);
7523                 stunalloc(name);
7524         } while (--idx >= 0);
7525         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7526 }
7527
7528 /*
7529  * Clear out command entries.  The argument specifies the first entry in
7530  * PATH which has changed.
7531  */
7532 static void
7533 clearcmdentry(int firstchange)
7534 {
7535         struct tblentry **tblp;
7536         struct tblentry **pp;
7537         struct tblentry *cmdp;
7538
7539         INT_OFF;
7540         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7541                 pp = tblp;
7542                 while ((cmdp = *pp) != NULL) {
7543                         if ((cmdp->cmdtype == CMDNORMAL &&
7544                              cmdp->param.index >= firstchange)
7545                          || (cmdp->cmdtype == CMDBUILTIN &&
7546                              builtinloc >= firstchange)
7547                         ) {
7548                                 *pp = cmdp->next;
7549                                 free(cmdp);
7550                         } else {
7551                                 pp = &cmdp->next;
7552                         }
7553                 }
7554         }
7555         INT_ON;
7556 }
7557
7558 /*
7559  * Locate a command in the command hash table.  If "add" is nonzero,
7560  * add the command to the table if it is not already present.  The
7561  * variable "lastcmdentry" is set to point to the address of the link
7562  * pointing to the entry, so that delete_cmd_entry can delete the
7563  * entry.
7564  *
7565  * Interrupts must be off if called with add != 0.
7566  */
7567 static struct tblentry **lastcmdentry;
7568
7569 static struct tblentry *
7570 cmdlookup(const char *name, int add)
7571 {
7572         unsigned int hashval;
7573         const char *p;
7574         struct tblentry *cmdp;
7575         struct tblentry **pp;
7576
7577         p = name;
7578         hashval = (unsigned char)*p << 4;
7579         while (*p)
7580                 hashval += (unsigned char)*p++;
7581         hashval &= 0x7FFF;
7582         pp = &cmdtable[hashval % CMDTABLESIZE];
7583         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7584                 if (strcmp(cmdp->cmdname, name) == 0)
7585                         break;
7586                 pp = &cmdp->next;
7587         }
7588         if (add && cmdp == NULL) {
7589                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7590                                 + strlen(name)
7591                                 /* + 1 - already done because
7592                                  * tblentry::cmdname is char[1] */);
7593                 /*cmdp->next = NULL; - ckzalloc did it */
7594                 cmdp->cmdtype = CMDUNKNOWN;
7595                 strcpy(cmdp->cmdname, name);
7596         }
7597         lastcmdentry = pp;
7598         return cmdp;
7599 }
7600
7601 /*
7602  * Delete the command entry returned on the last lookup.
7603  */
7604 static void
7605 delete_cmd_entry(void)
7606 {
7607         struct tblentry *cmdp;
7608
7609         INT_OFF;
7610         cmdp = *lastcmdentry;
7611         *lastcmdentry = cmdp->next;
7612         if (cmdp->cmdtype == CMDFUNCTION)
7613                 freefunc(cmdp->param.func);
7614         free(cmdp);
7615         INT_ON;
7616 }
7617
7618 /*
7619  * Add a new command entry, replacing any existing command entry for
7620  * the same name - except special builtins.
7621  */
7622 static void
7623 addcmdentry(char *name, struct cmdentry *entry)
7624 {
7625         struct tblentry *cmdp;
7626
7627         cmdp = cmdlookup(name, 1);
7628         if (cmdp->cmdtype == CMDFUNCTION) {
7629                 freefunc(cmdp->param.func);
7630         }
7631         cmdp->cmdtype = entry->cmdtype;
7632         cmdp->param = entry->u;
7633         cmdp->rehash = 0;
7634 }
7635
7636 static int FAST_FUNC
7637 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7638 {
7639         struct tblentry **pp;
7640         struct tblentry *cmdp;
7641         int c;
7642         struct cmdentry entry;
7643         char *name;
7644
7645         if (nextopt("r") != '\0') {
7646                 clearcmdentry(0);
7647                 return 0;
7648         }
7649
7650         if (*argptr == NULL) {
7651                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7652                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7653                                 if (cmdp->cmdtype == CMDNORMAL)
7654                                         printentry(cmdp);
7655                         }
7656                 }
7657                 return 0;
7658         }
7659
7660         c = 0;
7661         while ((name = *argptr) != NULL) {
7662                 cmdp = cmdlookup(name, 0);
7663                 if (cmdp != NULL
7664                  && (cmdp->cmdtype == CMDNORMAL
7665                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7666                 ) {
7667                         delete_cmd_entry();
7668                 }
7669                 find_command(name, &entry, DO_ERR, pathval());
7670                 if (entry.cmdtype == CMDUNKNOWN)
7671                         c = 1;
7672                 argptr++;
7673         }
7674         return c;
7675 }
7676
7677 /*
7678  * Called when a cd is done.  Marks all commands so the next time they
7679  * are executed they will be rehashed.
7680  */
7681 static void
7682 hashcd(void)
7683 {
7684         struct tblentry **pp;
7685         struct tblentry *cmdp;
7686
7687         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7688                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7689                         if (cmdp->cmdtype == CMDNORMAL
7690                          || (cmdp->cmdtype == CMDBUILTIN
7691                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7692                              && builtinloc > 0)
7693                         ) {
7694                                 cmdp->rehash = 1;
7695                         }
7696                 }
7697         }
7698 }
7699
7700 /*
7701  * Fix command hash table when PATH changed.
7702  * Called before PATH is changed.  The argument is the new value of PATH;
7703  * pathval() still returns the old value at this point.
7704  * Called with interrupts off.
7705  */
7706 static void FAST_FUNC
7707 changepath(const char *new)
7708 {
7709         const char *old;
7710         int firstchange;
7711         int idx;
7712         int idx_bltin;
7713
7714         old = pathval();
7715         firstchange = 9999;     /* assume no change */
7716         idx = 0;
7717         idx_bltin = -1;
7718         for (;;) {
7719                 if (*old != *new) {
7720                         firstchange = idx;
7721                         if ((*old == '\0' && *new == ':')
7722                          || (*old == ':' && *new == '\0')
7723                         ) {
7724                                 firstchange++;
7725                         }
7726                         old = new;      /* ignore subsequent differences */
7727                 }
7728                 if (*new == '\0')
7729                         break;
7730                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7731                         idx_bltin = idx;
7732                 if (*new == ':')
7733                         idx++;
7734                 new++;
7735                 old++;
7736         }
7737         if (builtinloc < 0 && idx_bltin >= 0)
7738                 builtinloc = idx_bltin;             /* zap builtins */
7739         if (builtinloc >= 0 && idx_bltin < 0)
7740                 firstchange = 0;
7741         clearcmdentry(firstchange);
7742         builtinloc = idx_bltin;
7743 }
7744
7745 #define TEOF 0
7746 #define TNL 1
7747 #define TREDIR 2
7748 #define TWORD 3
7749 #define TSEMI 4
7750 #define TBACKGND 5
7751 #define TAND 6
7752 #define TOR 7
7753 #define TPIPE 8
7754 #define TLP 9
7755 #define TRP 10
7756 #define TENDCASE 11
7757 #define TENDBQUOTE 12
7758 #define TNOT 13
7759 #define TCASE 14
7760 #define TDO 15
7761 #define TDONE 16
7762 #define TELIF 17
7763 #define TELSE 18
7764 #define TESAC 19
7765 #define TFI 20
7766 #define TFOR 21
7767 #define TIF 22
7768 #define TIN 23
7769 #define TTHEN 24
7770 #define TUNTIL 25
7771 #define TWHILE 26
7772 #define TBEGIN 27
7773 #define TEND 28
7774 typedef smallint token_id_t;
7775
7776 /* first char is indicating which tokens mark the end of a list */
7777 static const char *const tokname_array[] = {
7778         "\1end of file",
7779         "\0newline",
7780         "\0redirection",
7781         "\0word",
7782         "\0;",
7783         "\0&",
7784         "\0&&",
7785         "\0||",
7786         "\0|",
7787         "\0(",
7788         "\1)",
7789         "\1;;",
7790         "\1`",
7791 #define KWDOFFSET 13
7792         /* the following are keywords */
7793         "\0!",
7794         "\0case",
7795         "\1do",
7796         "\1done",
7797         "\1elif",
7798         "\1else",
7799         "\1esac",
7800         "\1fi",
7801         "\0for",
7802         "\0if",
7803         "\0in",
7804         "\1then",
7805         "\0until",
7806         "\0while",
7807         "\0{",
7808         "\1}",
7809 };
7810
7811 /* Wrapper around strcmp for qsort/bsearch/... */
7812 static int
7813 pstrcmp(const void *a, const void *b)
7814 {
7815         return strcmp((char*) a, (*(char**) b) + 1);
7816 }
7817
7818 static const char *const *
7819 findkwd(const char *s)
7820 {
7821         return bsearch(s, tokname_array + KWDOFFSET,
7822                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
7823                         sizeof(tokname_array[0]), pstrcmp);
7824 }
7825
7826 /*
7827  * Locate and print what a word is...
7828  */
7829 static int
7830 describe_command(char *command, int describe_command_verbose)
7831 {
7832         struct cmdentry entry;
7833         struct tblentry *cmdp;
7834 #if ENABLE_ASH_ALIAS
7835         const struct alias *ap;
7836 #endif
7837         const char *path = pathval();
7838
7839         if (describe_command_verbose) {
7840                 out1str(command);
7841         }
7842
7843         /* First look at the keywords */
7844         if (findkwd(command)) {
7845                 out1str(describe_command_verbose ? " is a shell keyword" : command);
7846                 goto out;
7847         }
7848
7849 #if ENABLE_ASH_ALIAS
7850         /* Then look at the aliases */
7851         ap = lookupalias(command, 0);
7852         if (ap != NULL) {
7853                 if (!describe_command_verbose) {
7854                         out1str("alias ");
7855                         printalias(ap);
7856                         return 0;
7857                 }
7858                 out1fmt(" is an alias for %s", ap->val);
7859                 goto out;
7860         }
7861 #endif
7862         /* Then check if it is a tracked alias */
7863         cmdp = cmdlookup(command, 0);
7864         if (cmdp != NULL) {
7865                 entry.cmdtype = cmdp->cmdtype;
7866                 entry.u = cmdp->param;
7867         } else {
7868                 /* Finally use brute force */
7869                 find_command(command, &entry, DO_ABS, path);
7870         }
7871
7872         switch (entry.cmdtype) {
7873         case CMDNORMAL: {
7874                 int j = entry.u.index;
7875                 char *p;
7876                 if (j < 0) {
7877                         p = command;
7878                 } else {
7879                         do {
7880                                 p = path_advance(&path, command);
7881                                 stunalloc(p);
7882                         } while (--j >= 0);
7883                 }
7884                 if (describe_command_verbose) {
7885                         out1fmt(" is%s %s",
7886                                 (cmdp ? " a tracked alias for" : nullstr), p
7887                         );
7888                 } else {
7889                         out1str(p);
7890                 }
7891                 break;
7892         }
7893
7894         case CMDFUNCTION:
7895                 if (describe_command_verbose) {
7896                         out1str(" is a shell function");
7897                 } else {
7898                         out1str(command);
7899                 }
7900                 break;
7901
7902         case CMDBUILTIN:
7903                 if (describe_command_verbose) {
7904                         out1fmt(" is a %sshell builtin",
7905                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7906                                         "special " : nullstr
7907                         );
7908                 } else {
7909                         out1str(command);
7910                 }
7911                 break;
7912
7913         default:
7914                 if (describe_command_verbose) {
7915                         out1str(": not found\n");
7916                 }
7917                 return 127;
7918         }
7919  out:
7920         out1str("\n");
7921         return 0;
7922 }
7923
7924 static int FAST_FUNC
7925 typecmd(int argc UNUSED_PARAM, char **argv)
7926 {
7927         int i = 1;
7928         int err = 0;
7929         int verbose = 1;
7930
7931         /* type -p ... ? (we don't bother checking for 'p') */
7932         if (argv[1] && argv[1][0] == '-') {
7933                 i++;
7934                 verbose = 0;
7935         }
7936         while (argv[i]) {
7937                 err |= describe_command(argv[i++], verbose);
7938         }
7939         return err;
7940 }
7941
7942 #if ENABLE_ASH_CMDCMD
7943 static int FAST_FUNC
7944 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7945 {
7946         int c;
7947         enum {
7948                 VERIFY_BRIEF = 1,
7949                 VERIFY_VERBOSE = 2,
7950         } verify = 0;
7951
7952         while ((c = nextopt("pvV")) != '\0')
7953                 if (c == 'V')
7954                         verify |= VERIFY_VERBOSE;
7955                 else if (c == 'v')
7956                         verify |= VERIFY_BRIEF;
7957 #if DEBUG
7958                 else if (c != 'p')
7959                         abort();
7960 #endif
7961         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7962         if (verify && (*argptr != NULL)) {
7963                 return describe_command(*argptr, verify - VERIFY_BRIEF);
7964         }
7965
7966         return 0;
7967 }
7968 #endif
7969
7970
7971 /* ============ eval.c */
7972
7973 static int funcblocksize;       /* size of structures in function */
7974 static int funcstringsize;      /* size of strings in node */
7975 static void *funcblock;         /* block to allocate function from */
7976 static char *funcstring;        /* block to allocate strings from */
7977
7978 /* flags in argument to evaltree */
7979 #define EV_EXIT    01           /* exit after evaluating tree */
7980 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
7981 #define EV_BACKCMD 04           /* command executing within back quotes */
7982
7983 static const uint8_t nodesize[N_NUMBER] = {
7984         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
7985         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
7986         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
7987         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7988         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7989         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
7990         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
7991         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
7992         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
7993         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
7994         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
7995         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
7996         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
7997         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
7998         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
7999         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8000         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8001 #if ENABLE_ASH_BASH_COMPAT
8002         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8003 #endif
8004         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8005         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8006         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8007         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8008         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8009         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8010         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8011         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8012         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8013 };
8014
8015 static void calcsize(union node *n);
8016
8017 static void
8018 sizenodelist(struct nodelist *lp)
8019 {
8020         while (lp) {
8021                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8022                 calcsize(lp->n);
8023                 lp = lp->next;
8024         }
8025 }
8026
8027 static void
8028 calcsize(union node *n)
8029 {
8030         if (n == NULL)
8031                 return;
8032         funcblocksize += nodesize[n->type];
8033         switch (n->type) {
8034         case NCMD:
8035                 calcsize(n->ncmd.redirect);
8036                 calcsize(n->ncmd.args);
8037                 calcsize(n->ncmd.assign);
8038                 break;
8039         case NPIPE:
8040                 sizenodelist(n->npipe.cmdlist);
8041                 break;
8042         case NREDIR:
8043         case NBACKGND:
8044         case NSUBSHELL:
8045                 calcsize(n->nredir.redirect);
8046                 calcsize(n->nredir.n);
8047                 break;
8048         case NAND:
8049         case NOR:
8050         case NSEMI:
8051         case NWHILE:
8052         case NUNTIL:
8053                 calcsize(n->nbinary.ch2);
8054                 calcsize(n->nbinary.ch1);
8055                 break;
8056         case NIF:
8057                 calcsize(n->nif.elsepart);
8058                 calcsize(n->nif.ifpart);
8059                 calcsize(n->nif.test);
8060                 break;
8061         case NFOR:
8062                 funcstringsize += strlen(n->nfor.var) + 1;
8063                 calcsize(n->nfor.body);
8064                 calcsize(n->nfor.args);
8065                 break;
8066         case NCASE:
8067                 calcsize(n->ncase.cases);
8068                 calcsize(n->ncase.expr);
8069                 break;
8070         case NCLIST:
8071                 calcsize(n->nclist.body);
8072                 calcsize(n->nclist.pattern);
8073                 calcsize(n->nclist.next);
8074                 break;
8075         case NDEFUN:
8076         case NARG:
8077                 sizenodelist(n->narg.backquote);
8078                 funcstringsize += strlen(n->narg.text) + 1;
8079                 calcsize(n->narg.next);
8080                 break;
8081         case NTO:
8082 #if ENABLE_ASH_BASH_COMPAT
8083         case NTO2:
8084 #endif
8085         case NCLOBBER:
8086         case NFROM:
8087         case NFROMTO:
8088         case NAPPEND:
8089                 calcsize(n->nfile.fname);
8090                 calcsize(n->nfile.next);
8091                 break;
8092         case NTOFD:
8093         case NFROMFD:
8094                 calcsize(n->ndup.vname);
8095                 calcsize(n->ndup.next);
8096         break;
8097         case NHERE:
8098         case NXHERE:
8099                 calcsize(n->nhere.doc);
8100                 calcsize(n->nhere.next);
8101                 break;
8102         case NNOT:
8103                 calcsize(n->nnot.com);
8104                 break;
8105         };
8106 }
8107
8108 static char *
8109 nodeckstrdup(char *s)
8110 {
8111         char *rtn = funcstring;
8112
8113         strcpy(funcstring, s);
8114         funcstring += strlen(s) + 1;
8115         return rtn;
8116 }
8117
8118 static union node *copynode(union node *);
8119
8120 static struct nodelist *
8121 copynodelist(struct nodelist *lp)
8122 {
8123         struct nodelist *start;
8124         struct nodelist **lpp;
8125
8126         lpp = &start;
8127         while (lp) {
8128                 *lpp = funcblock;
8129                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8130                 (*lpp)->n = copynode(lp->n);
8131                 lp = lp->next;
8132                 lpp = &(*lpp)->next;
8133         }
8134         *lpp = NULL;
8135         return start;
8136 }
8137
8138 static union node *
8139 copynode(union node *n)
8140 {
8141         union node *new;
8142
8143         if (n == NULL)
8144                 return NULL;
8145         new = funcblock;
8146         funcblock = (char *) funcblock + nodesize[n->type];
8147
8148         switch (n->type) {
8149         case NCMD:
8150                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8151                 new->ncmd.args = copynode(n->ncmd.args);
8152                 new->ncmd.assign = copynode(n->ncmd.assign);
8153                 break;
8154         case NPIPE:
8155                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8156                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8157                 break;
8158         case NREDIR:
8159         case NBACKGND:
8160         case NSUBSHELL:
8161                 new->nredir.redirect = copynode(n->nredir.redirect);
8162                 new->nredir.n = copynode(n->nredir.n);
8163                 break;
8164         case NAND:
8165         case NOR:
8166         case NSEMI:
8167         case NWHILE:
8168         case NUNTIL:
8169                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8170                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8171                 break;
8172         case NIF:
8173                 new->nif.elsepart = copynode(n->nif.elsepart);
8174                 new->nif.ifpart = copynode(n->nif.ifpart);
8175                 new->nif.test = copynode(n->nif.test);
8176                 break;
8177         case NFOR:
8178                 new->nfor.var = nodeckstrdup(n->nfor.var);
8179                 new->nfor.body = copynode(n->nfor.body);
8180                 new->nfor.args = copynode(n->nfor.args);
8181                 break;
8182         case NCASE:
8183                 new->ncase.cases = copynode(n->ncase.cases);
8184                 new->ncase.expr = copynode(n->ncase.expr);
8185                 break;
8186         case NCLIST:
8187                 new->nclist.body = copynode(n->nclist.body);
8188                 new->nclist.pattern = copynode(n->nclist.pattern);
8189                 new->nclist.next = copynode(n->nclist.next);
8190                 break;
8191         case NDEFUN:
8192         case NARG:
8193                 new->narg.backquote = copynodelist(n->narg.backquote);
8194                 new->narg.text = nodeckstrdup(n->narg.text);
8195                 new->narg.next = copynode(n->narg.next);
8196                 break;
8197         case NTO:
8198 #if ENABLE_ASH_BASH_COMPAT
8199         case NTO2:
8200 #endif
8201         case NCLOBBER:
8202         case NFROM:
8203         case NFROMTO:
8204         case NAPPEND:
8205                 new->nfile.fname = copynode(n->nfile.fname);
8206                 new->nfile.fd = n->nfile.fd;
8207                 new->nfile.next = copynode(n->nfile.next);
8208                 break;
8209         case NTOFD:
8210         case NFROMFD:
8211                 new->ndup.vname = copynode(n->ndup.vname);
8212                 new->ndup.dupfd = n->ndup.dupfd;
8213                 new->ndup.fd = n->ndup.fd;
8214                 new->ndup.next = copynode(n->ndup.next);
8215                 break;
8216         case NHERE:
8217         case NXHERE:
8218                 new->nhere.doc = copynode(n->nhere.doc);
8219                 new->nhere.fd = n->nhere.fd;
8220                 new->nhere.next = copynode(n->nhere.next);
8221                 break;
8222         case NNOT:
8223                 new->nnot.com = copynode(n->nnot.com);
8224                 break;
8225         };
8226         new->type = n->type;
8227         return new;
8228 }
8229
8230 /*
8231  * Make a copy of a parse tree.
8232  */
8233 static struct funcnode *
8234 copyfunc(union node *n)
8235 {
8236         struct funcnode *f;
8237         size_t blocksize;
8238
8239         funcblocksize = offsetof(struct funcnode, n);
8240         funcstringsize = 0;
8241         calcsize(n);
8242         blocksize = funcblocksize;
8243         f = ckmalloc(blocksize + funcstringsize);
8244         funcblock = (char *) f + offsetof(struct funcnode, n);
8245         funcstring = (char *) f + blocksize;
8246         copynode(n);
8247         f->count = 0;
8248         return f;
8249 }
8250
8251 /*
8252  * Define a shell function.
8253  */
8254 static void
8255 defun(char *name, union node *func)
8256 {
8257         struct cmdentry entry;
8258
8259         INT_OFF;
8260         entry.cmdtype = CMDFUNCTION;
8261         entry.u.func = copyfunc(func);
8262         addcmdentry(name, &entry);
8263         INT_ON;
8264 }
8265
8266 /* Reasons for skipping commands (see comment on breakcmd routine) */
8267 #define SKIPBREAK      (1 << 0)
8268 #define SKIPCONT       (1 << 1)
8269 #define SKIPFUNC       (1 << 2)
8270 #define SKIPFILE       (1 << 3)
8271 #define SKIPEVAL       (1 << 4)
8272 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8273 static int skipcount;           /* number of levels to skip */
8274 static int funcnest;            /* depth of function calls */
8275 static int loopnest;            /* current loop nesting level */
8276
8277 /* Forward decl way out to parsing code - dotrap needs it */
8278 static int evalstring(char *s, int mask);
8279
8280 /* Called to execute a trap.
8281  * Single callsite - at the end of evaltree().
8282  * If we return non-zero, evaltree raises EXEXIT exception.
8283  *
8284  * Perhaps we should avoid entering new trap handlers
8285  * while we are executing a trap handler. [is it a TODO?]
8286  */
8287 static int
8288 dotrap(void)
8289 {
8290         uint8_t *g;
8291         int sig;
8292         uint8_t savestatus;
8293
8294         savestatus = exitstatus;
8295         pending_sig = 0;
8296         xbarrier();
8297
8298         TRACE(("dotrap entered\n"));
8299         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8300                 int want_exexit;
8301                 char *t;
8302
8303                 if (*g == 0)
8304                         continue;
8305                 t = trap[sig];
8306                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8307                  * don't upset it by resetting gotsig[SIGINT-1] */
8308                 if (sig == SIGINT && !t)
8309                         continue;
8310
8311                 TRACE(("sig %d is active, will run handler '%s'\n", sig, t));
8312                 *g = 0;
8313                 if (!t)
8314                         continue;
8315                 want_exexit = evalstring(t, SKIPEVAL);
8316                 exitstatus = savestatus;
8317                 if (want_exexit) {
8318                         TRACE(("dotrap returns %d\n", want_exexit));
8319                         return want_exexit;
8320                 }
8321         }
8322
8323         TRACE(("dotrap returns 0\n"));
8324         return 0;
8325 }
8326
8327 /* forward declarations - evaluation is fairly recursive business... */
8328 static void evalloop(union node *, int);
8329 static void evalfor(union node *, int);
8330 static void evalcase(union node *, int);
8331 static void evalsubshell(union node *, int);
8332 static void expredir(union node *);
8333 static void evalpipe(union node *, int);
8334 static void evalcommand(union node *, int);
8335 static int evalbltin(const struct builtincmd *, int, char **);
8336 static void prehash(union node *);
8337
8338 /*
8339  * Evaluate a parse tree.  The value is left in the global variable
8340  * exitstatus.
8341  */
8342 static void
8343 evaltree(union node *n, int flags)
8344 {
8345         struct jmploc *volatile savehandler = exception_handler;
8346         struct jmploc jmploc;
8347         int checkexit = 0;
8348         void (*evalfn)(union node *, int);
8349         int status;
8350         int int_level;
8351
8352         SAVE_INT(int_level);
8353
8354         if (n == NULL) {
8355                 TRACE(("evaltree(NULL) called\n"));
8356                 goto out1;
8357         }
8358         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8359
8360         exception_handler = &jmploc;
8361         {
8362                 int err = setjmp(jmploc.loc);
8363                 if (err) {
8364                         /* if it was a signal, check for trap handlers */
8365                         if (exception_type == EXSIG) {
8366                                 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8367                                                 exception_type, err));
8368                                 goto out;
8369                         }
8370                         /* continue on the way out */
8371                         TRACE(("exception %d in evaltree, propagating err=%d\n",
8372                                         exception_type, err));
8373                         exception_handler = savehandler;
8374                         longjmp(exception_handler->loc, err);
8375                 }
8376         }
8377
8378         switch (n->type) {
8379         default:
8380 #if DEBUG
8381                 out1fmt("Node type = %d\n", n->type);
8382                 fflush_all();
8383                 break;
8384 #endif
8385         case NNOT:
8386                 evaltree(n->nnot.com, EV_TESTED);
8387                 status = !exitstatus;
8388                 goto setstatus;
8389         case NREDIR:
8390                 expredir(n->nredir.redirect);
8391                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8392                 if (!status) {
8393                         evaltree(n->nredir.n, flags & EV_TESTED);
8394                         status = exitstatus;
8395                 }
8396                 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8397                 goto setstatus;
8398         case NCMD:
8399                 evalfn = evalcommand;
8400  checkexit:
8401                 if (eflag && !(flags & EV_TESTED))
8402                         checkexit = ~0;
8403                 goto calleval;
8404         case NFOR:
8405                 evalfn = evalfor;
8406                 goto calleval;
8407         case NWHILE:
8408         case NUNTIL:
8409                 evalfn = evalloop;
8410                 goto calleval;
8411         case NSUBSHELL:
8412         case NBACKGND:
8413                 evalfn = evalsubshell;
8414                 goto calleval;
8415         case NPIPE:
8416                 evalfn = evalpipe;
8417                 goto checkexit;
8418         case NCASE:
8419                 evalfn = evalcase;
8420                 goto calleval;
8421         case NAND:
8422         case NOR:
8423         case NSEMI: {
8424
8425 #if NAND + 1 != NOR
8426 #error NAND + 1 != NOR
8427 #endif
8428 #if NOR + 1 != NSEMI
8429 #error NOR + 1 != NSEMI
8430 #endif
8431                 unsigned is_or = n->type - NAND;
8432                 evaltree(
8433                         n->nbinary.ch1,
8434                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8435                 );
8436                 if (!exitstatus == is_or)
8437                         break;
8438                 if (!evalskip) {
8439                         n = n->nbinary.ch2;
8440  evaln:
8441                         evalfn = evaltree;
8442  calleval:
8443                         evalfn(n, flags);
8444                         break;
8445                 }
8446                 break;
8447         }
8448         case NIF:
8449                 evaltree(n->nif.test, EV_TESTED);
8450                 if (evalskip)
8451                         break;
8452                 if (exitstatus == 0) {
8453                         n = n->nif.ifpart;
8454                         goto evaln;
8455                 }
8456                 if (n->nif.elsepart) {
8457                         n = n->nif.elsepart;
8458                         goto evaln;
8459                 }
8460                 goto success;
8461         case NDEFUN:
8462                 defun(n->narg.text, n->narg.next);
8463  success:
8464                 status = 0;
8465  setstatus:
8466                 exitstatus = status;
8467                 break;
8468         }
8469
8470  out:
8471         exception_handler = savehandler;
8472
8473  out1:
8474         /* Order of checks below is important:
8475          * signal handlers trigger before exit caused by "set -e".
8476          */
8477         if (pending_sig && dotrap())
8478                 goto exexit;
8479         if (checkexit & exitstatus)
8480                 evalskip |= SKIPEVAL;
8481
8482         if (flags & EV_EXIT) {
8483  exexit:
8484                 raise_exception(EXEXIT);
8485         }
8486
8487         RESTORE_INT(int_level);
8488         TRACE(("leaving evaltree (no interrupts)\n"));
8489 }
8490
8491 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8492 static
8493 #endif
8494 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8495
8496 static void
8497 evalloop(union node *n, int flags)
8498 {
8499         int status;
8500
8501         loopnest++;
8502         status = 0;
8503         flags &= EV_TESTED;
8504         for (;;) {
8505                 int i;
8506
8507                 evaltree(n->nbinary.ch1, EV_TESTED);
8508                 if (evalskip) {
8509  skipping:
8510                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8511                                 evalskip = 0;
8512                                 continue;
8513                         }
8514                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8515                                 evalskip = 0;
8516                         break;
8517                 }
8518                 i = exitstatus;
8519                 if (n->type != NWHILE)
8520                         i = !i;
8521                 if (i != 0)
8522                         break;
8523                 evaltree(n->nbinary.ch2, flags);
8524                 status = exitstatus;
8525                 if (evalskip)
8526                         goto skipping;
8527         }
8528         loopnest--;
8529         exitstatus = status;
8530 }
8531
8532 static void
8533 evalfor(union node *n, int flags)
8534 {
8535         struct arglist arglist;
8536         union node *argp;
8537         struct strlist *sp;
8538         struct stackmark smark;
8539
8540         setstackmark(&smark);
8541         arglist.list = NULL;
8542         arglist.lastp = &arglist.list;
8543         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8544                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8545                 /* XXX */
8546                 if (evalskip)
8547                         goto out;
8548         }
8549         *arglist.lastp = NULL;
8550
8551         exitstatus = 0;
8552         loopnest++;
8553         flags &= EV_TESTED;
8554         for (sp = arglist.list; sp; sp = sp->next) {
8555                 setvar(n->nfor.var, sp->text, 0);
8556                 evaltree(n->nfor.body, flags);
8557                 if (evalskip) {
8558                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8559                                 evalskip = 0;
8560                                 continue;
8561                         }
8562                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8563                                 evalskip = 0;
8564                         break;
8565                 }
8566         }
8567         loopnest--;
8568  out:
8569         popstackmark(&smark);
8570 }
8571
8572 static void
8573 evalcase(union node *n, int flags)
8574 {
8575         union node *cp;
8576         union node *patp;
8577         struct arglist arglist;
8578         struct stackmark smark;
8579
8580         setstackmark(&smark);
8581         arglist.list = NULL;
8582         arglist.lastp = &arglist.list;
8583         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8584         exitstatus = 0;
8585         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8586                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8587                         if (casematch(patp, arglist.list->text)) {
8588                                 if (evalskip == 0) {
8589                                         evaltree(cp->nclist.body, flags);
8590                                 }
8591                                 goto out;
8592                         }
8593                 }
8594         }
8595  out:
8596         popstackmark(&smark);
8597 }
8598
8599 /*
8600  * Kick off a subshell to evaluate a tree.
8601  */
8602 static void
8603 evalsubshell(union node *n, int flags)
8604 {
8605         struct job *jp;
8606         int backgnd = (n->type == NBACKGND);
8607         int status;
8608
8609         expredir(n->nredir.redirect);
8610         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8611                 goto nofork;
8612         INT_OFF;
8613         jp = makejob(/*n,*/ 1);
8614         if (forkshell(jp, n, backgnd) == 0) {
8615                 /* child */
8616                 INT_ON;
8617                 flags |= EV_EXIT;
8618                 if (backgnd)
8619                         flags &= ~EV_TESTED;
8620  nofork:
8621                 redirect(n->nredir.redirect, 0);
8622                 evaltreenr(n->nredir.n, flags);
8623                 /* never returns */
8624         }
8625         status = 0;
8626         if (!backgnd)
8627                 status = waitforjob(jp);
8628         exitstatus = status;
8629         INT_ON;
8630 }
8631
8632 /*
8633  * Compute the names of the files in a redirection list.
8634  */
8635 static void fixredir(union node *, const char *, int);
8636 static void
8637 expredir(union node *n)
8638 {
8639         union node *redir;
8640
8641         for (redir = n; redir; redir = redir->nfile.next) {
8642                 struct arglist fn;
8643
8644                 fn.list = NULL;
8645                 fn.lastp = &fn.list;
8646                 switch (redir->type) {
8647                 case NFROMTO:
8648                 case NFROM:
8649                 case NTO:
8650 #if ENABLE_ASH_BASH_COMPAT
8651                 case NTO2:
8652 #endif
8653                 case NCLOBBER:
8654                 case NAPPEND:
8655                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8656 #if ENABLE_ASH_BASH_COMPAT
8657  store_expfname:
8658 #endif
8659                         redir->nfile.expfname = fn.list->text;
8660                         break;
8661                 case NFROMFD:
8662                 case NTOFD: /* >& */
8663                         if (redir->ndup.vname) {
8664                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8665                                 if (fn.list == NULL)
8666                                         ash_msg_and_raise_error("redir error");
8667 #if ENABLE_ASH_BASH_COMPAT
8668 //FIXME: we used expandarg with different args!
8669                                 if (!isdigit_str9(fn.list->text)) {
8670                                         /* >&file, not >&fd */
8671                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
8672                                                 ash_msg_and_raise_error("redir error");
8673                                         redir->type = NTO2;
8674                                         goto store_expfname;
8675                                 }
8676 #endif
8677                                 fixredir(redir, fn.list->text, 1);
8678                         }
8679                         break;
8680                 }
8681         }
8682 }
8683
8684 /*
8685  * Evaluate a pipeline.  All the processes in the pipeline are children
8686  * of the process creating the pipeline.  (This differs from some versions
8687  * of the shell, which make the last process in a pipeline the parent
8688  * of all the rest.)
8689  */
8690 static void
8691 evalpipe(union node *n, int flags)
8692 {
8693         struct job *jp;
8694         struct nodelist *lp;
8695         int pipelen;
8696         int prevfd;
8697         int pip[2];
8698
8699         TRACE(("evalpipe(0x%lx) called\n", (long)n));
8700         pipelen = 0;
8701         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8702                 pipelen++;
8703         flags |= EV_EXIT;
8704         INT_OFF;
8705         jp = makejob(/*n,*/ pipelen);
8706         prevfd = -1;
8707         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8708                 prehash(lp->n);
8709                 pip[1] = -1;
8710                 if (lp->next) {
8711                         if (pipe(pip) < 0) {
8712                                 close(prevfd);
8713                                 ash_msg_and_raise_error("pipe call failed");
8714                         }
8715                 }
8716                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8717                         INT_ON;
8718                         if (pip[1] >= 0) {
8719                                 close(pip[0]);
8720                         }
8721                         if (prevfd > 0) {
8722                                 dup2(prevfd, 0);
8723                                 close(prevfd);
8724                         }
8725                         if (pip[1] > 1) {
8726                                 dup2(pip[1], 1);
8727                                 close(pip[1]);
8728                         }
8729                         evaltreenr(lp->n, flags);
8730                         /* never returns */
8731                 }
8732                 if (prevfd >= 0)
8733                         close(prevfd);
8734                 prevfd = pip[0];
8735                 /* Don't want to trigger debugging */
8736                 if (pip[1] != -1)
8737                         close(pip[1]);
8738         }
8739         if (n->npipe.pipe_backgnd == 0) {
8740                 exitstatus = waitforjob(jp);
8741                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
8742         }
8743         INT_ON;
8744 }
8745
8746 /*
8747  * Controls whether the shell is interactive or not.
8748  */
8749 static void
8750 setinteractive(int on)
8751 {
8752         static smallint is_interactive;
8753
8754         if (++on == is_interactive)
8755                 return;
8756         is_interactive = on;
8757         setsignal(SIGINT);
8758         setsignal(SIGQUIT);
8759         setsignal(SIGTERM);
8760 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8761         if (is_interactive > 1) {
8762                 /* Looks like they want an interactive shell */
8763                 static smallint did_banner;
8764
8765                 if (!did_banner) {
8766                         /* note: ash and hush share this string */
8767                         out1fmt("\n\n%s %s\n"
8768                                 "Enter 'help' for a list of built-in commands."
8769                                 "\n\n",
8770                                 bb_banner,
8771                                 "built-in shell (ash)"
8772                         );
8773                         did_banner = 1;
8774                 }
8775         }
8776 #endif
8777 }
8778
8779 static void
8780 optschanged(void)
8781 {
8782 #if DEBUG
8783         opentrace();
8784 #endif
8785         setinteractive(iflag);
8786         setjobctl(mflag);
8787 #if ENABLE_FEATURE_EDITING_VI
8788         if (viflag)
8789                 line_input_state->flags |= VI_MODE;
8790         else
8791                 line_input_state->flags &= ~VI_MODE;
8792 #else
8793         viflag = 0; /* forcibly keep the option off */
8794 #endif
8795 }
8796
8797 static struct localvar *localvars;
8798
8799 /*
8800  * Called after a function returns.
8801  * Interrupts must be off.
8802  */
8803 static void
8804 poplocalvars(void)
8805 {
8806         struct localvar *lvp;
8807         struct var *vp;
8808
8809         while ((lvp = localvars) != NULL) {
8810                 localvars = lvp->next;
8811                 vp = lvp->vp;
8812                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
8813                 if (vp == NULL) {       /* $- saved */
8814                         memcpy(optlist, lvp->text, sizeof(optlist));
8815                         free((char*)lvp->text);
8816                         optschanged();
8817                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8818                         unsetvar(vp->var_text);
8819                 } else {
8820                         if (vp->var_func)
8821                                 vp->var_func(var_end(lvp->text));
8822                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8823                                 free((char*)vp->var_text);
8824                         vp->flags = lvp->flags;
8825                         vp->var_text = lvp->text;
8826                 }
8827                 free(lvp);
8828         }
8829 }
8830
8831 static int
8832 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8833 {
8834         volatile struct shparam saveparam;
8835         struct localvar *volatile savelocalvars;
8836         struct jmploc *volatile savehandler;
8837         struct jmploc jmploc;
8838         int e;
8839
8840         saveparam = shellparam;
8841         savelocalvars = localvars;
8842         e = setjmp(jmploc.loc);
8843         if (e) {
8844                 goto funcdone;
8845         }
8846         INT_OFF;
8847         savehandler = exception_handler;
8848         exception_handler = &jmploc;
8849         localvars = NULL;
8850         shellparam.malloced = 0;
8851         func->count++;
8852         funcnest++;
8853         INT_ON;
8854         shellparam.nparam = argc - 1;
8855         shellparam.p = argv + 1;
8856 #if ENABLE_ASH_GETOPTS
8857         shellparam.optind = 1;
8858         shellparam.optoff = -1;
8859 #endif
8860         evaltree(&func->n, flags & EV_TESTED);
8861  funcdone:
8862         INT_OFF;
8863         funcnest--;
8864         freefunc(func);
8865         poplocalvars();
8866         localvars = savelocalvars;
8867         freeparam(&shellparam);
8868         shellparam = saveparam;
8869         exception_handler = savehandler;
8870         INT_ON;
8871         evalskip &= ~SKIPFUNC;
8872         return e;
8873 }
8874
8875 #if ENABLE_ASH_CMDCMD
8876 static char **
8877 parse_command_args(char **argv, const char **path)
8878 {
8879         char *cp, c;
8880
8881         for (;;) {
8882                 cp = *++argv;
8883                 if (!cp)
8884                         return 0;
8885                 if (*cp++ != '-')
8886                         break;
8887                 c = *cp++;
8888                 if (!c)
8889                         break;
8890                 if (c == '-' && !*cp) {
8891                         argv++;
8892                         break;
8893                 }
8894                 do {
8895                         switch (c) {
8896                         case 'p':
8897                                 *path = bb_default_path;
8898                                 break;
8899                         default:
8900                                 /* run 'typecmd' for other options */
8901                                 return 0;
8902                         }
8903                         c = *cp++;
8904                 } while (c);
8905         }
8906         return argv;
8907 }
8908 #endif
8909
8910 /*
8911  * Make a variable a local variable.  When a variable is made local, it's
8912  * value and flags are saved in a localvar structure.  The saved values
8913  * will be restored when the shell function returns.  We handle the name
8914  * "-" as a special case.
8915  */
8916 static void
8917 mklocal(char *name)
8918 {
8919         struct localvar *lvp;
8920         struct var **vpp;
8921         struct var *vp;
8922
8923         INT_OFF;
8924         lvp = ckzalloc(sizeof(struct localvar));
8925         if (LONE_DASH(name)) {
8926                 char *p;
8927                 p = ckmalloc(sizeof(optlist));
8928                 lvp->text = memcpy(p, optlist, sizeof(optlist));
8929                 vp = NULL;
8930         } else {
8931                 char *eq;
8932
8933                 vpp = hashvar(name);
8934                 vp = *findvar(vpp, name);
8935                 eq = strchr(name, '=');
8936                 if (vp == NULL) {
8937                         if (eq)
8938                                 setvareq(name, VSTRFIXED);
8939                         else
8940                                 setvar(name, NULL, VSTRFIXED);
8941                         vp = *vpp;      /* the new variable */
8942                         lvp->flags = VUNSET;
8943                 } else {
8944                         lvp->text = vp->var_text;
8945                         lvp->flags = vp->flags;
8946                         vp->flags |= VSTRFIXED|VTEXTFIXED;
8947                         if (eq)
8948                                 setvareq(name, 0);
8949                 }
8950         }
8951         lvp->vp = vp;
8952         lvp->next = localvars;
8953         localvars = lvp;
8954         INT_ON;
8955 }
8956
8957 /*
8958  * The "local" command.
8959  */
8960 static int FAST_FUNC
8961 localcmd(int argc UNUSED_PARAM, char **argv)
8962 {
8963         char *name;
8964
8965         argv = argptr;
8966         while ((name = *argv++) != NULL) {
8967                 mklocal(name);
8968         }
8969         return 0;
8970 }
8971
8972 static int FAST_FUNC
8973 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8974 {
8975         return 1;
8976 }
8977
8978 static int FAST_FUNC
8979 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8980 {
8981         return 0;
8982 }
8983
8984 static int FAST_FUNC
8985 execcmd(int argc UNUSED_PARAM, char **argv)
8986 {
8987         if (argv[1]) {
8988                 iflag = 0;              /* exit on error */
8989                 mflag = 0;
8990                 optschanged();
8991                 shellexec(argv + 1, pathval(), 0);
8992         }
8993         return 0;
8994 }
8995
8996 /*
8997  * The return command.
8998  */
8999 static int FAST_FUNC
9000 returncmd(int argc UNUSED_PARAM, char **argv)
9001 {
9002         /*
9003          * If called outside a function, do what ksh does;
9004          * skip the rest of the file.
9005          */
9006         evalskip = funcnest ? SKIPFUNC : SKIPFILE;
9007         return argv[1] ? number(argv[1]) : exitstatus;
9008 }
9009
9010 /* Forward declarations for builtintab[] */
9011 static int breakcmd(int, char **) FAST_FUNC;
9012 static int dotcmd(int, char **) FAST_FUNC;
9013 static int evalcmd(int, char **) FAST_FUNC;
9014 static int exitcmd(int, char **) FAST_FUNC;
9015 static int exportcmd(int, char **) FAST_FUNC;
9016 #if ENABLE_ASH_GETOPTS
9017 static int getoptscmd(int, char **) FAST_FUNC;
9018 #endif
9019 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9020 static int helpcmd(int, char **) FAST_FUNC;
9021 #endif
9022 #if ENABLE_SH_MATH_SUPPORT
9023 static int letcmd(int, char **) FAST_FUNC;
9024 #endif
9025 static int readcmd(int, char **) FAST_FUNC;
9026 static int setcmd(int, char **) FAST_FUNC;
9027 static int shiftcmd(int, char **) FAST_FUNC;
9028 static int timescmd(int, char **) FAST_FUNC;
9029 static int trapcmd(int, char **) FAST_FUNC;
9030 static int umaskcmd(int, char **) FAST_FUNC;
9031 static int unsetcmd(int, char **) FAST_FUNC;
9032 static int ulimitcmd(int, char **) FAST_FUNC;
9033
9034 #define BUILTIN_NOSPEC          "0"
9035 #define BUILTIN_SPECIAL         "1"
9036 #define BUILTIN_REGULAR         "2"
9037 #define BUILTIN_SPEC_REG        "3"
9038 #define BUILTIN_ASSIGN          "4"
9039 #define BUILTIN_SPEC_ASSG       "5"
9040 #define BUILTIN_REG_ASSG        "6"
9041 #define BUILTIN_SPEC_REG_ASSG   "7"
9042
9043 /* Stubs for calling non-FAST_FUNC's */
9044 #if ENABLE_ASH_BUILTIN_ECHO
9045 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9046 #endif
9047 #if ENABLE_ASH_BUILTIN_PRINTF
9048 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9049 #endif
9050 #if ENABLE_ASH_BUILTIN_TEST
9051 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9052 #endif
9053
9054 /* Keep these in proper order since it is searched via bsearch() */
9055 static const struct builtincmd builtintab[] = {
9056         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9057         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9058 #if ENABLE_ASH_BUILTIN_TEST
9059         { BUILTIN_REGULAR       "["       , testcmd    },
9060 #if ENABLE_ASH_BASH_COMPAT
9061         { BUILTIN_REGULAR       "[["      , testcmd    },
9062 #endif
9063 #endif
9064 #if ENABLE_ASH_ALIAS
9065         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9066 #endif
9067 #if JOBS
9068         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9069 #endif
9070         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9071         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9072         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9073 #if ENABLE_ASH_CMDCMD
9074         { BUILTIN_REGULAR       "command" , commandcmd },
9075 #endif
9076         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9077 #if ENABLE_ASH_BUILTIN_ECHO
9078         { BUILTIN_REGULAR       "echo"    , echocmd    },
9079 #endif
9080         { BUILTIN_SPEC_REG      "eval"    , evalcmd    },
9081         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9082         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9083         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9084         { BUILTIN_REGULAR       "false"   , falsecmd   },
9085 #if JOBS
9086         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9087 #endif
9088 #if ENABLE_ASH_GETOPTS
9089         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9090 #endif
9091         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9092 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9093         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9094 #endif
9095 #if JOBS
9096         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9097         { BUILTIN_REGULAR       "kill"    , killcmd    },
9098 #endif
9099 #if ENABLE_SH_MATH_SUPPORT
9100         { BUILTIN_NOSPEC        "let"     , letcmd     },
9101 #endif
9102         { BUILTIN_ASSIGN        "local"   , localcmd   },
9103 #if ENABLE_ASH_BUILTIN_PRINTF
9104         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9105 #endif
9106         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9107         { BUILTIN_REGULAR       "read"    , readcmd    },
9108         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9109         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9110         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9111         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9112 #if ENABLE_ASH_BASH_COMPAT
9113         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9114 #endif
9115 #if ENABLE_ASH_BUILTIN_TEST
9116         { BUILTIN_REGULAR       "test"    , testcmd    },
9117 #endif
9118         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9119         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9120         { BUILTIN_REGULAR       "true"    , truecmd    },
9121         { BUILTIN_NOSPEC        "type"    , typecmd    },
9122         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9123         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9124 #if ENABLE_ASH_ALIAS
9125         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9126 #endif
9127         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9128         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9129 };
9130
9131 /* Should match the above table! */
9132 #define COMMANDCMD (builtintab + \
9133         2 + \
9134         1 * ENABLE_ASH_BUILTIN_TEST + \
9135         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
9136         1 * ENABLE_ASH_ALIAS + \
9137         1 * ENABLE_ASH_JOB_CONTROL + \
9138         3)
9139 #define EXECCMD (builtintab + \
9140         2 + \
9141         1 * ENABLE_ASH_BUILTIN_TEST + \
9142         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
9143         1 * ENABLE_ASH_ALIAS + \
9144         1 * ENABLE_ASH_JOB_CONTROL + \
9145         3 + \
9146         1 * ENABLE_ASH_CMDCMD + \
9147         1 + \
9148         ENABLE_ASH_BUILTIN_ECHO + \
9149         1)
9150
9151 /*
9152  * Search the table of builtin commands.
9153  */
9154 static struct builtincmd *
9155 find_builtin(const char *name)
9156 {
9157         struct builtincmd *bp;
9158
9159         bp = bsearch(
9160                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9161                 pstrcmp
9162         );
9163         return bp;
9164 }
9165
9166 /*
9167  * Execute a simple command.
9168  */
9169 static int
9170 isassignment(const char *p)
9171 {
9172         const char *q = endofname(p);
9173         if (p == q)
9174                 return 0;
9175         return *q == '=';
9176 }
9177 static int FAST_FUNC
9178 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9179 {
9180         /* Preserve exitstatus of a previous possible redirection
9181          * as POSIX mandates */
9182         return back_exitstatus;
9183 }
9184 static void
9185 evalcommand(union node *cmd, int flags)
9186 {
9187         static const struct builtincmd null_bltin = {
9188                 "\0\0", bltincmd /* why three NULs? */
9189         };
9190         struct stackmark smark;
9191         union node *argp;
9192         struct arglist arglist;
9193         struct arglist varlist;
9194         char **argv;
9195         int argc;
9196         const struct strlist *sp;
9197         struct cmdentry cmdentry;
9198         struct job *jp;
9199         char *lastarg;
9200         const char *path;
9201         int spclbltin;
9202         int status;
9203         char **nargv;
9204         struct builtincmd *bcmd;
9205         smallint cmd_is_exec;
9206         smallint pseudovarflag = 0;
9207
9208         /* First expand the arguments. */
9209         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9210         setstackmark(&smark);
9211         back_exitstatus = 0;
9212
9213         cmdentry.cmdtype = CMDBUILTIN;
9214         cmdentry.u.cmd = &null_bltin;
9215         varlist.lastp = &varlist.list;
9216         *varlist.lastp = NULL;
9217         arglist.lastp = &arglist.list;
9218         *arglist.lastp = NULL;
9219
9220         argc = 0;
9221         if (cmd->ncmd.args) {
9222                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9223                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9224         }
9225
9226         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9227                 struct strlist **spp;
9228
9229                 spp = arglist.lastp;
9230                 if (pseudovarflag && isassignment(argp->narg.text))
9231                         expandarg(argp, &arglist, EXP_VARTILDE);
9232                 else
9233                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9234
9235                 for (sp = *spp; sp; sp = sp->next)
9236                         argc++;
9237         }
9238
9239         argv = nargv = stalloc(sizeof(char *) * (argc + 1));
9240         for (sp = arglist.list; sp; sp = sp->next) {
9241                 TRACE(("evalcommand arg: %s\n", sp->text));
9242                 *nargv++ = sp->text;
9243         }
9244         *nargv = NULL;
9245
9246         lastarg = NULL;
9247         if (iflag && funcnest == 0 && argc > 0)
9248                 lastarg = nargv[-1];
9249
9250         preverrout_fd = 2;
9251         expredir(cmd->ncmd.redirect);
9252         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9253
9254         path = vpath.var_text;
9255         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9256                 struct strlist **spp;
9257                 char *p;
9258
9259                 spp = varlist.lastp;
9260                 expandarg(argp, &varlist, EXP_VARTILDE);
9261
9262                 /*
9263                  * Modify the command lookup path, if a PATH= assignment
9264                  * is present
9265                  */
9266                 p = (*spp)->text;
9267                 if (varcmp(p, path) == 0)
9268                         path = p;
9269         }
9270
9271         /* Print the command if xflag is set. */
9272         if (xflag) {
9273                 int n;
9274                 const char *p = " %s" + 1;
9275
9276                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9277                 sp = varlist.list;
9278                 for (n = 0; n < 2; n++) {
9279                         while (sp) {
9280                                 fdprintf(preverrout_fd, p, sp->text);
9281                                 sp = sp->next;
9282                                 p = " %s";
9283                         }
9284                         sp = arglist.list;
9285                 }
9286                 safe_write(preverrout_fd, "\n", 1);
9287         }
9288
9289         cmd_is_exec = 0;
9290         spclbltin = -1;
9291
9292         /* Now locate the command. */
9293         if (argc) {
9294                 const char *oldpath;
9295                 int cmd_flag = DO_ERR;
9296
9297                 path += 5;
9298                 oldpath = path;
9299                 for (;;) {
9300                         find_command(argv[0], &cmdentry, cmd_flag, path);
9301                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9302                                 flush_stdout_stderr();
9303                                 status = 127;
9304                                 goto bail;
9305                         }
9306
9307                         /* implement bltin and command here */
9308                         if (cmdentry.cmdtype != CMDBUILTIN)
9309                                 break;
9310                         if (spclbltin < 0)
9311                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9312                         if (cmdentry.u.cmd == EXECCMD)
9313                                 cmd_is_exec = 1;
9314 #if ENABLE_ASH_CMDCMD
9315                         if (cmdentry.u.cmd == COMMANDCMD) {
9316                                 path = oldpath;
9317                                 nargv = parse_command_args(argv, &path);
9318                                 if (!nargv)
9319                                         break;
9320                                 argc -= nargv - argv;
9321                                 argv = nargv;
9322                                 cmd_flag |= DO_NOFUNC;
9323                         } else
9324 #endif
9325                                 break;
9326                 }
9327         }
9328
9329         if (status) {
9330                 /* We have a redirection error. */
9331                 if (spclbltin > 0)
9332                         raise_exception(EXERROR);
9333  bail:
9334                 exitstatus = status;
9335                 goto out;
9336         }
9337
9338         /* Execute the command. */
9339         switch (cmdentry.cmdtype) {
9340         default: {
9341
9342 #if ENABLE_FEATURE_SH_NOFORK
9343 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9344  *     around run_nofork_applet() call.
9345  * (2) Should this check also be done in forkshell()?
9346  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9347  */
9348                 /* find_command() encodes applet_no as (-2 - applet_no) */
9349                 int applet_no = (- cmdentry.u.index - 2);
9350                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9351                         listsetvar(varlist.list, VEXPORT|VSTACK);
9352                         /* run <applet>_main() */
9353                         exitstatus = run_nofork_applet(applet_no, argv);
9354                         break;
9355                 }
9356 #endif
9357                 /* Can we avoid forking off? For example, very last command
9358                  * in a script or a subshell does not need forking,
9359                  * we can just exec it.
9360                  */
9361                 if (!(flags & EV_EXIT) || may_have_traps) {
9362                         /* No, forking off a child is necessary */
9363                         INT_OFF;
9364                         jp = makejob(/*cmd,*/ 1);
9365                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9366                                 /* parent */
9367                                 exitstatus = waitforjob(jp);
9368                                 INT_ON;
9369                                 TRACE(("forked child exited with %d\n", exitstatus));
9370                                 break;
9371                         }
9372                         /* child */
9373                         FORCE_INT_ON;
9374                         /* fall through to exec'ing external program */
9375                 }
9376                 listsetvar(varlist.list, VEXPORT|VSTACK);
9377                 shellexec(argv, path, cmdentry.u.index);
9378                 /* NOTREACHED */
9379         } /* default */
9380         case CMDBUILTIN:
9381                 cmdenviron = varlist.list;
9382                 if (cmdenviron) {
9383                         struct strlist *list = cmdenviron;
9384                         int i = VNOSET;
9385                         if (spclbltin > 0 || argc == 0) {
9386                                 i = 0;
9387                                 if (cmd_is_exec && argc > 1)
9388                                         i = VEXPORT;
9389                         }
9390                         listsetvar(list, i);
9391                 }
9392                 /* Tight loop with builtins only:
9393                  * "while kill -0 $child; do true; done"
9394                  * will never exit even if $child died, unless we do this
9395                  * to reap the zombie and make kill detect that it's gone: */
9396                 dowait(DOWAIT_NONBLOCK, NULL);
9397
9398                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9399                         int exit_status;
9400                         int i = exception_type;
9401                         if (i == EXEXIT)
9402                                 goto raise;
9403                         exit_status = 2;
9404                         if (i == EXINT)
9405                                 exit_status = 128 + SIGINT;
9406                         if (i == EXSIG)
9407                                 exit_status = 128 + pending_sig;
9408                         exitstatus = exit_status;
9409                         if (i == EXINT || spclbltin > 0) {
9410  raise:
9411                                 longjmp(exception_handler->loc, 1);
9412                         }
9413                         FORCE_INT_ON;
9414                 }
9415                 break;
9416
9417         case CMDFUNCTION:
9418                 listsetvar(varlist.list, 0);
9419                 /* See above for the rationale */
9420                 dowait(DOWAIT_NONBLOCK, NULL);
9421                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9422                         goto raise;
9423                 break;
9424
9425         } /* switch */
9426
9427  out:
9428         popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9429         if (lastarg) {
9430                 /* dsl: I think this is intended to be used to support
9431                  * '_' in 'vi' command mode during line editing...
9432                  * However I implemented that within libedit itself.
9433                  */
9434                 setvar("_", lastarg, 0);
9435         }
9436         popstackmark(&smark);
9437 }
9438
9439 static int
9440 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9441 {
9442         char *volatile savecmdname;
9443         struct jmploc *volatile savehandler;
9444         struct jmploc jmploc;
9445         int i;
9446
9447         savecmdname = commandname;
9448         i = setjmp(jmploc.loc);
9449         if (i)
9450                 goto cmddone;
9451         savehandler = exception_handler;
9452         exception_handler = &jmploc;
9453         commandname = argv[0];
9454         argptr = argv + 1;
9455         optptr = NULL;                  /* initialize nextopt */
9456         exitstatus = (*cmd->builtin)(argc, argv);
9457         flush_stdout_stderr();
9458  cmddone:
9459         exitstatus |= ferror(stdout);
9460         clearerr(stdout);
9461         commandname = savecmdname;
9462         exception_handler = savehandler;
9463
9464         return i;
9465 }
9466
9467 static int
9468 goodname(const char *p)
9469 {
9470         return endofname(p)[0] == '\0';
9471 }
9472
9473
9474 /*
9475  * Search for a command.  This is called before we fork so that the
9476  * location of the command will be available in the parent as well as
9477  * the child.  The check for "goodname" is an overly conservative
9478  * check that the name will not be subject to expansion.
9479  */
9480 static void
9481 prehash(union node *n)
9482 {
9483         struct cmdentry entry;
9484
9485         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9486                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9487 }
9488
9489
9490 /* ============ Builtin commands
9491  *
9492  * Builtin commands whose functions are closely tied to evaluation
9493  * are implemented here.
9494  */
9495
9496 /*
9497  * Handle break and continue commands.  Break, continue, and return are
9498  * all handled by setting the evalskip flag.  The evaluation routines
9499  * above all check this flag, and if it is set they start skipping
9500  * commands rather than executing them.  The variable skipcount is
9501  * the number of loops to break/continue, or the number of function
9502  * levels to return.  (The latter is always 1.)  It should probably
9503  * be an error to break out of more loops than exist, but it isn't
9504  * in the standard shell so we don't make it one here.
9505  */
9506 static int FAST_FUNC
9507 breakcmd(int argc UNUSED_PARAM, char **argv)
9508 {
9509         int n = argv[1] ? number(argv[1]) : 1;
9510
9511         if (n <= 0)
9512                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9513         if (n > loopnest)
9514                 n = loopnest;
9515         if (n > 0) {
9516                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9517                 skipcount = n;
9518         }
9519         return 0;
9520 }
9521
9522
9523 /* ============ input.c
9524  *
9525  * This implements the input routines used by the parser.
9526  */
9527
9528 enum {
9529         INPUT_PUSH_FILE = 1,
9530         INPUT_NOFILE_OK = 2,
9531 };
9532
9533 static smallint checkkwd;
9534 /* values of checkkwd variable */
9535 #define CHKALIAS        0x1
9536 #define CHKKWD          0x2
9537 #define CHKNL           0x4
9538
9539 /*
9540  * Push a string back onto the input at this current parsefile level.
9541  * We handle aliases this way.
9542  */
9543 #if !ENABLE_ASH_ALIAS
9544 #define pushstring(s, ap) pushstring(s)
9545 #endif
9546 static void
9547 pushstring(char *s, struct alias *ap)
9548 {
9549         struct strpush *sp;
9550         int len;
9551
9552         len = strlen(s);
9553         INT_OFF;
9554         if (g_parsefile->strpush) {
9555                 sp = ckzalloc(sizeof(*sp));
9556                 sp->prev = g_parsefile->strpush;
9557         } else {
9558                 sp = &(g_parsefile->basestrpush);
9559         }
9560         g_parsefile->strpush = sp;
9561         sp->prev_string = g_parsefile->next_to_pgetc;
9562         sp->prev_left_in_line = g_parsefile->left_in_line;
9563 #if ENABLE_ASH_ALIAS
9564         sp->ap = ap;
9565         if (ap) {
9566                 ap->flag |= ALIASINUSE;
9567                 sp->string = s;
9568         }
9569 #endif
9570         g_parsefile->next_to_pgetc = s;
9571         g_parsefile->left_in_line = len;
9572         INT_ON;
9573 }
9574
9575 static void
9576 popstring(void)
9577 {
9578         struct strpush *sp = g_parsefile->strpush;
9579
9580         INT_OFF;
9581 #if ENABLE_ASH_ALIAS
9582         if (sp->ap) {
9583                 if (g_parsefile->next_to_pgetc[-1] == ' '
9584                  || g_parsefile->next_to_pgetc[-1] == '\t'
9585                 ) {
9586                         checkkwd |= CHKALIAS;
9587                 }
9588                 if (sp->string != sp->ap->val) {
9589                         free(sp->string);
9590                 }
9591                 sp->ap->flag &= ~ALIASINUSE;
9592                 if (sp->ap->flag & ALIASDEAD) {
9593                         unalias(sp->ap->name);
9594                 }
9595         }
9596 #endif
9597         g_parsefile->next_to_pgetc = sp->prev_string;
9598         g_parsefile->left_in_line = sp->prev_left_in_line;
9599         g_parsefile->strpush = sp->prev;
9600         if (sp != &(g_parsefile->basestrpush))
9601                 free(sp);
9602         INT_ON;
9603 }
9604
9605 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9606 //it peeks whether it is &>, and then pushes back both chars.
9607 //This function needs to save last *next_to_pgetc to buf[0]
9608 //to make two pungetc() reliable. Currently,
9609 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9610 static int
9611 preadfd(void)
9612 {
9613         int nr;
9614         char *buf = g_parsefile->buf;
9615
9616         g_parsefile->next_to_pgetc = buf;
9617 #if ENABLE_FEATURE_EDITING
9618  retry:
9619         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
9620                 nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9621         else {
9622                 int timeout = -1;
9623 # if ENABLE_ASH_IDLE_TIMEOUT
9624                 if (iflag) {
9625                         const char *tmout_var = lookupvar("TMOUT");
9626                         if (tmout_var) {
9627                                 timeout = atoi(tmout_var) * 1000;
9628                                 if (timeout <= 0)
9629                                         timeout = -1;
9630                         }
9631                 }
9632 # endif
9633 # if ENABLE_FEATURE_TAB_COMPLETION
9634                 line_input_state->path_lookup = pathval();
9635 # endif
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         INT_OFF;
10286         retval = 1;
10287         if (!options(0)) { /* if no parse error... */
10288                 retval = 0;
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                                 p = '\0';
12945                 setpwd(p, 0);
12946         }
12947 }
12948
12949 /*
12950  * Process the shell command line arguments.
12951  */
12952 static void
12953 procargs(char **argv)
12954 {
12955         int i;
12956         const char *xminusc;
12957         char **xargv;
12958
12959         xargv = argv;
12960         arg0 = xargv[0];
12961         /* if (xargv[0]) - mmm, this is always true! */
12962                 xargv++;
12963         for (i = 0; i < NOPTS; i++)
12964                 optlist[i] = 2;
12965         argptr = xargv;
12966         if (options(1)) {
12967                 /* it already printed err message */
12968                 raise_exception(EXERROR);
12969         }
12970         xargv = argptr;
12971         xminusc = minusc;
12972         if (*xargv == NULL) {
12973                 if (xminusc)
12974                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12975                 sflag = 1;
12976         }
12977         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12978                 iflag = 1;
12979         if (mflag == 2)
12980                 mflag = iflag;
12981         for (i = 0; i < NOPTS; i++)
12982                 if (optlist[i] == 2)
12983                         optlist[i] = 0;
12984 #if DEBUG == 2
12985         debug = 1;
12986 #endif
12987         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12988         if (xminusc) {
12989                 minusc = *xargv++;
12990                 if (*xargv)
12991                         goto setarg0;
12992         } else if (!sflag) {
12993                 setinputfile(*xargv, 0);
12994  setarg0:
12995                 arg0 = *xargv++;
12996                 commandname = arg0;
12997         }
12998
12999         shellparam.p = xargv;
13000 #if ENABLE_ASH_GETOPTS
13001         shellparam.optind = 1;
13002         shellparam.optoff = -1;
13003 #endif
13004         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13005         while (*xargv) {
13006                 shellparam.nparam++;
13007                 xargv++;
13008         }
13009         optschanged();
13010 }
13011
13012 /*
13013  * Read /etc/profile or .profile.
13014  */
13015 static void
13016 read_profile(const char *name)
13017 {
13018         int skip;
13019
13020         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13021                 return;
13022         skip = cmdloop(0);
13023         popfile();
13024         if (skip)
13025                 exitshell();
13026 }
13027
13028 /*
13029  * This routine is called when an error or an interrupt occurs in an
13030  * interactive shell and control is returned to the main command loop.
13031  */
13032 static void
13033 reset(void)
13034 {
13035         /* from eval.c: */
13036         evalskip = 0;
13037         loopnest = 0;
13038         /* from input.c: */
13039         g_parsefile->left_in_buffer = 0;
13040         g_parsefile->left_in_line = 0;      /* clear input buffer */
13041         popallfiles();
13042         /* from parser.c: */
13043         tokpushback = 0;
13044         checkkwd = 0;
13045         /* from redir.c: */
13046         clearredir(/*drop:*/ 0);
13047 }
13048
13049 #if PROFILE
13050 static short profile_buf[16384];
13051 extern int etext();
13052 #endif
13053
13054 /*
13055  * Main routine.  We initialize things, parse the arguments, execute
13056  * profiles if we're a login shell, and then call cmdloop to execute
13057  * commands.  The setjmp call sets up the location to jump to when an
13058  * exception occurs.  When an exception occurs the variable "state"
13059  * is used to figure out how far we had gotten.
13060  */
13061 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13062 int ash_main(int argc UNUSED_PARAM, char **argv)
13063 {
13064         const char *shinit;
13065         volatile smallint state;
13066         struct jmploc jmploc;
13067         struct stackmark smark;
13068
13069         /* Initialize global data */
13070         INIT_G_misc();
13071         INIT_G_memstack();
13072         INIT_G_var();
13073 #if ENABLE_ASH_ALIAS
13074         INIT_G_alias();
13075 #endif
13076         INIT_G_cmdtable();
13077
13078 #if PROFILE
13079         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13080 #endif
13081
13082 #if ENABLE_FEATURE_EDITING
13083         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13084 #endif
13085         state = 0;
13086         if (setjmp(jmploc.loc)) {
13087                 smallint e;
13088                 smallint s;
13089
13090                 reset();
13091
13092                 e = exception_type;
13093                 if (e == EXERROR)
13094                         exitstatus = 2;
13095                 s = state;
13096                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13097                         exitshell();
13098                 }
13099                 if (e == EXINT) {
13100                         outcslow('\n', stderr);
13101                 }
13102
13103                 popstackmark(&smark);
13104                 FORCE_INT_ON; /* enable interrupts */
13105                 if (s == 1)
13106                         goto state1;
13107                 if (s == 2)
13108                         goto state2;
13109                 if (s == 3)
13110                         goto state3;
13111                 goto state4;
13112         }
13113         exception_handler = &jmploc;
13114 #if DEBUG
13115         opentrace();
13116         TRACE(("Shell args: "));
13117         trace_puts_args(argv);
13118 #endif
13119         rootpid = getpid();
13120
13121         init();
13122         setstackmark(&smark);
13123         procargs(argv);
13124
13125 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13126         if (iflag) {
13127                 const char *hp = lookupvar("HISTFILE");
13128
13129                 if (hp == NULL) {
13130                         hp = lookupvar("HOME");
13131                         if (hp != NULL) {
13132                                 char *defhp = concat_path_file(hp, ".ash_history");
13133                                 setvar("HISTFILE", defhp, 0);
13134                                 free(defhp);
13135                         }
13136                 }
13137         }
13138 #endif
13139         if (argv[0] && argv[0][0] == '-')
13140                 isloginsh = 1;
13141         if (isloginsh) {
13142                 state = 1;
13143                 read_profile("/etc/profile");
13144  state1:
13145                 state = 2;
13146                 read_profile(".profile");
13147         }
13148  state2:
13149         state = 3;
13150         if (
13151 #ifndef linux
13152          getuid() == geteuid() && getgid() == getegid() &&
13153 #endif
13154          iflag
13155         ) {
13156                 shinit = lookupvar("ENV");
13157                 if (shinit != NULL && *shinit != '\0') {
13158                         read_profile(shinit);
13159                 }
13160         }
13161  state3:
13162         state = 4;
13163         if (minusc) {
13164                 /* evalstring pushes parsefile stack.
13165                  * Ensure we don't falsely claim that 0 (stdin)
13166                  * is one of stacked source fds.
13167                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13168                 // if (!sflag) g_parsefile->pf_fd = -1;
13169                 // ^^ not necessary since now we special-case fd 0
13170                 // in is_hidden_fd() to not be considered "hidden fd"
13171                 evalstring(minusc, 0);
13172         }
13173
13174         if (sflag || minusc == NULL) {
13175 #if defined MAX_HISTORY && MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13176                 if (iflag) {
13177                         const char *hp = lookupvar("HISTFILE");
13178                         if (hp)
13179                                 line_input_state->hist_file = hp;
13180                 }
13181 #endif
13182  state4: /* XXX ??? - why isn't this before the "if" statement */
13183                 cmdloop(1);
13184         }
13185 #if PROFILE
13186         monitor(0);
13187 #endif
13188 #ifdef GPROF
13189         {
13190                 extern void _mcleanup(void);
13191                 _mcleanup();
13192         }
13193 #endif
13194         TRACE(("End of main reached\n"));
13195         exitshell();
13196         /* NOTREACHED */
13197 }
13198
13199
13200 /*-
13201  * Copyright (c) 1989, 1991, 1993, 1994
13202  *      The Regents of the University of California.  All rights reserved.
13203  *
13204  * This code is derived from software contributed to Berkeley by
13205  * Kenneth Almquist.
13206  *
13207  * Redistribution and use in source and binary forms, with or without
13208  * modification, are permitted provided that the following conditions
13209  * are met:
13210  * 1. Redistributions of source code must retain the above copyright
13211  *    notice, this list of conditions and the following disclaimer.
13212  * 2. Redistributions in binary form must reproduce the above copyright
13213  *    notice, this list of conditions and the following disclaimer in the
13214  *    documentation and/or other materials provided with the distribution.
13215  * 3. Neither the name of the University nor the names of its contributors
13216  *    may be used to endorse or promote products derived from this software
13217  *    without specific prior written permission.
13218  *
13219  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13220  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13221  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13222  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13223  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13224  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13225  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13226  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13227  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13228  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13229  * SUCH DAMAGE.
13230  */