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