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