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