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