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