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