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