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