ash,hush: ^C from command line should set $? to 128+SIGINT
[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                         exitstatus = 128 + SIGINT;
9880                         goto retry;
9881                 }
9882                 if (nr < 0) {
9883                         if (errno == 0) {
9884                                 /* Ctrl+D pressed */
9885                                 nr = 0;
9886                         }
9887 # if ENABLE_ASH_IDLE_TIMEOUT
9888                         else if (errno == EAGAIN && timeout > 0) {
9889                                 puts("\007timed out waiting for input: auto-logout");
9890                                 exitshell();
9891                         }
9892 # endif
9893                 }
9894         }
9895 #else
9896         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9897 #endif
9898
9899 #if 0 /* disabled: nonblock_immune_read() handles this problem */
9900         if (nr < 0) {
9901                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9902                         int flags = fcntl(0, F_GETFL);
9903                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9904                                 flags &= ~O_NONBLOCK;
9905                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9906                                         out2str("sh: turning off NDELAY mode\n");
9907                                         goto retry;
9908                                 }
9909                         }
9910                 }
9911         }
9912 #endif
9913         return nr;
9914 }
9915
9916 /*
9917  * Refill the input buffer and return the next input character:
9918  *
9919  * 1) If a string was pushed back on the input, pop it;
9920  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9921  *    or we are reading from a string so we can't refill the buffer,
9922  *    return EOF.
9923  * 3) If there is more stuff in this buffer, use it else call read to fill it.
9924  * 4) Process input up to the next newline, deleting nul characters.
9925  */
9926 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9927 #define pgetc_debug(...) ((void)0)
9928 static int pgetc(void);
9929 static int
9930 preadbuffer(void)
9931 {
9932         char *q;
9933         int more;
9934
9935         if (g_parsefile->strpush) {
9936 #if ENABLE_ASH_ALIAS
9937                 if (g_parsefile->left_in_line == -1
9938                  && g_parsefile->strpush->ap
9939                  && g_parsefile->next_to_pgetc[-1] != ' '
9940                  && g_parsefile->next_to_pgetc[-1] != '\t'
9941                 ) {
9942                         pgetc_debug("preadbuffer PEOA");
9943                         return PEOA;
9944                 }
9945 #endif
9946                 popstring();
9947                 return pgetc();
9948         }
9949         /* on both branches above g_parsefile->left_in_line < 0.
9950          * "pgetc" needs refilling.
9951          */
9952
9953         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9954          * pungetc() may increment it a few times.
9955          * Assuming it won't increment it to less than -90.
9956          */
9957         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9958                 pgetc_debug("preadbuffer PEOF1");
9959                 /* even in failure keep left_in_line and next_to_pgetc
9960                  * in lock step, for correct multi-layer pungetc.
9961                  * left_in_line was decremented before preadbuffer(),
9962                  * must inc next_to_pgetc: */
9963                 g_parsefile->next_to_pgetc++;
9964                 return PEOF;
9965         }
9966
9967         more = g_parsefile->left_in_buffer;
9968         if (more <= 0) {
9969                 flush_stdout_stderr();
9970  again:
9971                 more = preadfd();
9972                 if (more <= 0) {
9973                         /* don't try reading again */
9974                         g_parsefile->left_in_line = -99;
9975                         pgetc_debug("preadbuffer PEOF2");
9976                         g_parsefile->next_to_pgetc++;
9977                         return PEOF;
9978                 }
9979         }
9980
9981         /* Find out where's the end of line.
9982          * Set g_parsefile->left_in_line
9983          * and g_parsefile->left_in_buffer acordingly.
9984          * NUL chars are deleted.
9985          */
9986         q = g_parsefile->next_to_pgetc;
9987         for (;;) {
9988                 char c;
9989
9990                 more--;
9991
9992                 c = *q;
9993                 if (c == '\0') {
9994                         memmove(q, q + 1, more);
9995                 } else {
9996                         q++;
9997                         if (c == '\n') {
9998                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9999                                 break;
10000                         }
10001                 }
10002
10003                 if (more <= 0) {
10004                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10005                         if (g_parsefile->left_in_line < 0)
10006                                 goto again;
10007                         break;
10008                 }
10009         }
10010         g_parsefile->left_in_buffer = more;
10011
10012         if (vflag) {
10013                 char save = *q;
10014                 *q = '\0';
10015                 out2str(g_parsefile->next_to_pgetc);
10016                 *q = save;
10017         }
10018
10019         pgetc_debug("preadbuffer at %d:%p'%s'",
10020                         g_parsefile->left_in_line,
10021                         g_parsefile->next_to_pgetc,
10022                         g_parsefile->next_to_pgetc);
10023         return (unsigned char)*g_parsefile->next_to_pgetc++;
10024 }
10025
10026 static void
10027 nlprompt(void)
10028 {
10029         g_parsefile->linno++;
10030         setprompt_if(doprompt, 2);
10031 }
10032 static void
10033 nlnoprompt(void)
10034 {
10035         g_parsefile->linno++;
10036         needprompt = doprompt;
10037 }
10038
10039 static int
10040 pgetc(void)
10041 {
10042         int c;
10043
10044         pgetc_debug("pgetc at %d:%p'%s'",
10045                         g_parsefile->left_in_line,
10046                         g_parsefile->next_to_pgetc,
10047                         g_parsefile->next_to_pgetc);
10048         if (g_parsefile->unget)
10049                 return g_parsefile->lastc[--g_parsefile->unget];
10050
10051         if (--g_parsefile->left_in_line >= 0)
10052                 c = (signed char)*g_parsefile->next_to_pgetc++;
10053         else
10054                 c = preadbuffer();
10055
10056         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10057         g_parsefile->lastc[0] = c;
10058
10059         return c;
10060 }
10061
10062 #if ENABLE_ASH_ALIAS
10063 static int
10064 pgetc_without_PEOA(void)
10065 {
10066         int c;
10067         do {
10068                 pgetc_debug("pgetc at %d:%p'%s'",
10069                                 g_parsefile->left_in_line,
10070                                 g_parsefile->next_to_pgetc,
10071                                 g_parsefile->next_to_pgetc);
10072                 c = pgetc();
10073         } while (c == PEOA);
10074         return c;
10075 }
10076 #else
10077 # define pgetc_without_PEOA() pgetc()
10078 #endif
10079
10080 /*
10081  * Read a line from the script.
10082  */
10083 static char *
10084 pfgets(char *line, int len)
10085 {
10086         char *p = line;
10087         int nleft = len;
10088         int c;
10089
10090         while (--nleft > 0) {
10091                 c = pgetc_without_PEOA();
10092                 if (c == PEOF) {
10093                         if (p == line)
10094                                 return NULL;
10095                         break;
10096                 }
10097                 *p++ = c;
10098                 if (c == '\n')
10099                         break;
10100         }
10101         *p = '\0';
10102         return line;
10103 }
10104
10105 /*
10106  * Undo a call to pgetc.  Only two characters may be pushed back.
10107  * PEOF may be pushed back.
10108  */
10109 static void
10110 pungetc(void)
10111 {
10112         g_parsefile->unget++;
10113 }
10114
10115 /* This one eats backslash+newline */
10116 static int
10117 pgetc_eatbnl(void)
10118 {
10119         int c;
10120
10121         while ((c = pgetc()) == '\\') {
10122                 if (pgetc() != '\n') {
10123                         pungetc();
10124                         break;
10125                 }
10126
10127                 nlprompt();
10128         }
10129
10130         return c;
10131 }
10132
10133 /*
10134  * To handle the "." command, a stack of input files is used.  Pushfile
10135  * adds a new entry to the stack and popfile restores the previous level.
10136  */
10137 static void
10138 pushfile(void)
10139 {
10140         struct parsefile *pf;
10141
10142         pf = ckzalloc(sizeof(*pf));
10143         pf->prev = g_parsefile;
10144         pf->pf_fd = -1;
10145         /*pf->strpush = NULL; - ckzalloc did it */
10146         /*pf->basestrpush.prev = NULL;*/
10147         /*pf->unget = 0;*/
10148         g_parsefile = pf;
10149 }
10150
10151 static void
10152 popfile(void)
10153 {
10154         struct parsefile *pf = g_parsefile;
10155
10156         if (pf == &basepf)
10157                 return;
10158
10159         INT_OFF;
10160         if (pf->pf_fd >= 0)
10161                 close(pf->pf_fd);
10162         free(pf->buf);
10163         while (pf->strpush)
10164                 popstring();
10165         g_parsefile = pf->prev;
10166         free(pf);
10167         INT_ON;
10168 }
10169
10170 /*
10171  * Return to top level.
10172  */
10173 static void
10174 popallfiles(void)
10175 {
10176         while (g_parsefile != &basepf)
10177                 popfile();
10178 }
10179
10180 /*
10181  * Close the file(s) that the shell is reading commands from.  Called
10182  * after a fork is done.
10183  */
10184 static void
10185 closescript(void)
10186 {
10187         popallfiles();
10188         if (g_parsefile->pf_fd > 0) {
10189                 close(g_parsefile->pf_fd);
10190                 g_parsefile->pf_fd = 0;
10191         }
10192 }
10193
10194 /*
10195  * Like setinputfile, but takes an open file descriptor.  Call this with
10196  * interrupts off.
10197  */
10198 static void
10199 setinputfd(int fd, int push)
10200 {
10201         if (push) {
10202                 pushfile();
10203                 g_parsefile->buf = NULL;
10204         }
10205         g_parsefile->pf_fd = fd;
10206         if (g_parsefile->buf == NULL)
10207                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10208         g_parsefile->left_in_buffer = 0;
10209         g_parsefile->left_in_line = 0;
10210         g_parsefile->linno = 1;
10211 }
10212
10213 /*
10214  * Set the input to take input from a file.  If push is set, push the
10215  * old input onto the stack first.
10216  */
10217 static int
10218 setinputfile(const char *fname, int flags)
10219 {
10220         int fd;
10221
10222         INT_OFF;
10223         fd = open(fname, O_RDONLY);
10224         if (fd < 0) {
10225                 if (flags & INPUT_NOFILE_OK)
10226                         goto out;
10227                 exitstatus = 127;
10228                 ash_msg_and_raise_error("can't open '%s'", fname);
10229         }
10230         if (fd < 10)
10231                 fd = savefd(fd);
10232         else
10233                 close_on_exec_on(fd);
10234         setinputfd(fd, flags & INPUT_PUSH_FILE);
10235  out:
10236         INT_ON;
10237         return fd;
10238 }
10239
10240 /*
10241  * Like setinputfile, but takes input from a string.
10242  */
10243 static void
10244 setinputstring(char *string)
10245 {
10246         INT_OFF;
10247         pushfile();
10248         g_parsefile->next_to_pgetc = string;
10249         g_parsefile->left_in_line = strlen(string);
10250         g_parsefile->buf = NULL;
10251         g_parsefile->linno = 1;
10252         INT_ON;
10253 }
10254
10255
10256 /*
10257  * Routines to check for mail.
10258  */
10259
10260 #if ENABLE_ASH_MAIL
10261
10262 /* Hash of mtimes of mailboxes */
10263 static unsigned mailtime_hash;
10264 /* Set if MAIL or MAILPATH is changed. */
10265 static smallint mail_var_path_changed;
10266
10267 /*
10268  * Print appropriate message(s) if mail has arrived.
10269  * If mail_var_path_changed is set,
10270  * then the value of MAIL has mail_var_path_changed,
10271  * so we just update the values.
10272  */
10273 static void
10274 chkmail(void)
10275 {
10276         const char *mpath;
10277         char *p;
10278         char *q;
10279         unsigned new_hash;
10280         struct stackmark smark;
10281         struct stat statb;
10282
10283         setstackmark(&smark);
10284         mpath = mpathset() ? mpathval() : mailval();
10285         new_hash = 0;
10286         for (;;) {
10287                 p = path_advance(&mpath, nullstr);
10288                 if (p == NULL)
10289                         break;
10290                 if (*p == '\0')
10291                         continue;
10292                 for (q = p; *q; q++)
10293                         continue;
10294 #if DEBUG
10295                 if (q[-1] != '/')
10296                         abort();
10297 #endif
10298                 q[-1] = '\0';                   /* delete trailing '/' */
10299                 if (stat(p, &statb) < 0) {
10300                         continue;
10301                 }
10302                 /* Very simplistic "hash": just a sum of all mtimes */
10303                 new_hash += (unsigned)statb.st_mtime;
10304         }
10305         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10306                 if (mailtime_hash != 0)
10307                         out2str("you have mail\n");
10308                 mailtime_hash = new_hash;
10309         }
10310         mail_var_path_changed = 0;
10311         popstackmark(&smark);
10312 }
10313
10314 static void FAST_FUNC
10315 changemail(const char *val UNUSED_PARAM)
10316 {
10317         mail_var_path_changed = 1;
10318 }
10319
10320 #endif /* ASH_MAIL */
10321
10322
10323 /* ============ ??? */
10324
10325 /*
10326  * Set the shell parameters.
10327  */
10328 static void
10329 setparam(char **argv)
10330 {
10331         char **newparam;
10332         char **ap;
10333         int nparam;
10334
10335         for (nparam = 0; argv[nparam]; nparam++)
10336                 continue;
10337         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10338         while (*argv) {
10339                 *ap++ = ckstrdup(*argv++);
10340         }
10341         *ap = NULL;
10342         freeparam(&shellparam);
10343         shellparam.malloced = 1;
10344         shellparam.nparam = nparam;
10345         shellparam.p = newparam;
10346 #if ENABLE_ASH_GETOPTS
10347         shellparam.optind = 1;
10348         shellparam.optoff = -1;
10349 #endif
10350 }
10351
10352 /*
10353  * Process shell options.  The global variable argptr contains a pointer
10354  * to the argument list; we advance it past the options.
10355  *
10356  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10357  * For a non-interactive shell, an error condition encountered
10358  * by a special built-in ... shall cause the shell to write a diagnostic message
10359  * to standard error and exit as shown in the following table:
10360  * Error                                           Special Built-In
10361  * ...
10362  * Utility syntax error (option or operand error)  Shall exit
10363  * ...
10364  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10365  * we see that bash does not do that (set "finishes" with error code 1 instead,
10366  * and shell continues), and people rely on this behavior!
10367  * Testcase:
10368  * set -o barfoo 2>/dev/null
10369  * echo $?
10370  *
10371  * Oh well. Let's mimic that.
10372  */
10373 static int
10374 plus_minus_o(char *name, int val)
10375 {
10376         int i;
10377
10378         if (name) {
10379                 for (i = 0; i < NOPTS; i++) {
10380                         if (strcmp(name, optnames(i)) == 0) {
10381                                 optlist[i] = val;
10382                                 return 0;
10383                         }
10384                 }
10385                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10386                 return 1;
10387         }
10388         for (i = 0; i < NOPTS; i++) {
10389                 if (val) {
10390                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10391                 } else {
10392                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10393                 }
10394         }
10395         return 0;
10396 }
10397 static void
10398 setoption(int flag, int val)
10399 {
10400         int i;
10401
10402         for (i = 0; i < NOPTS; i++) {
10403                 if (optletters(i) == flag) {
10404                         optlist[i] = val;
10405                         return;
10406                 }
10407         }
10408         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10409         /* NOTREACHED */
10410 }
10411 static int
10412 options(int cmdline)
10413 {
10414         char *p;
10415         int val;
10416         int c;
10417
10418         if (cmdline)
10419                 minusc = NULL;
10420         while ((p = *argptr) != NULL) {
10421                 c = *p++;
10422                 if (c != '-' && c != '+')
10423                         break;
10424                 argptr++;
10425                 val = 0; /* val = 0 if c == '+' */
10426                 if (c == '-') {
10427                         val = 1;
10428                         if (p[0] == '\0' || LONE_DASH(p)) {
10429                                 if (!cmdline) {
10430                                         /* "-" means turn off -x and -v */
10431                                         if (p[0] == '\0')
10432                                                 xflag = vflag = 0;
10433                                         /* "--" means reset params */
10434                                         else if (*argptr == NULL)
10435                                                 setparam(argptr);
10436                                 }
10437                                 break;    /* "-" or "--" terminates options */
10438                         }
10439                 }
10440                 /* first char was + or - */
10441                 while ((c = *p++) != '\0') {
10442                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10443                         if (c == 'c' && cmdline) {
10444                                 minusc = p;     /* command is after shell args */
10445                         } else if (c == 'o') {
10446                                 if (plus_minus_o(*argptr, val)) {
10447                                         /* it already printed err message */
10448                                         return 1; /* error */
10449                                 }
10450                                 if (*argptr)
10451                                         argptr++;
10452                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10453                                 isloginsh = 1;
10454                         /* bash does not accept +-login, we also won't */
10455                         } else if (cmdline && val && (c == '-')) { /* long options */
10456                                 if (strcmp(p, "login") == 0)
10457                                         isloginsh = 1;
10458                                 break;
10459                         } else {
10460                                 setoption(c, val);
10461                         }
10462                 }
10463         }
10464         return 0;
10465 }
10466
10467 /*
10468  * The shift builtin command.
10469  */
10470 static int FAST_FUNC
10471 shiftcmd(int argc UNUSED_PARAM, char **argv)
10472 {
10473         int n;
10474         char **ap1, **ap2;
10475
10476         n = 1;
10477         if (argv[1])
10478                 n = number(argv[1]);
10479         if (n > shellparam.nparam)
10480                 n = 0; /* bash compat, was = shellparam.nparam; */
10481         INT_OFF;
10482         shellparam.nparam -= n;
10483         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10484                 if (shellparam.malloced)
10485                         free(*ap1);
10486         }
10487         ap2 = shellparam.p;
10488         while ((*ap2++ = *ap1++) != NULL)
10489                 continue;
10490 #if ENABLE_ASH_GETOPTS
10491         shellparam.optind = 1;
10492         shellparam.optoff = -1;
10493 #endif
10494         INT_ON;
10495         return 0;
10496 }
10497
10498 /*
10499  * POSIX requires that 'set' (but not export or readonly) output the
10500  * variables in lexicographic order - by the locale's collating order (sigh).
10501  * Maybe we could keep them in an ordered balanced binary tree
10502  * instead of hashed lists.
10503  * For now just roll 'em through qsort for printing...
10504  */
10505 static int
10506 showvars(const char *sep_prefix, int on, int off)
10507 {
10508         const char *sep;
10509         char **ep, **epend;
10510
10511         ep = listvars(on, off, &epend);
10512         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10513
10514         sep = *sep_prefix ? " " : sep_prefix;
10515
10516         for (; ep < epend; ep++) {
10517                 const char *p;
10518                 const char *q;
10519
10520                 p = strchrnul(*ep, '=');
10521                 q = nullstr;
10522                 if (*p)
10523                         q = single_quote(++p);
10524                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10525         }
10526         return 0;
10527 }
10528
10529 /*
10530  * The set command builtin.
10531  */
10532 static int FAST_FUNC
10533 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10534 {
10535         int retval;
10536
10537         if (!argv[1])
10538                 return showvars(nullstr, 0, VUNSET);
10539
10540         INT_OFF;
10541         retval = options(/*cmdline:*/ 0);
10542         if (retval == 0) { /* if no parse error... */
10543                 optschanged();
10544                 if (*argptr != NULL) {
10545                         setparam(argptr);
10546                 }
10547         }
10548         INT_ON;
10549         return retval;
10550 }
10551
10552 #if ENABLE_ASH_RANDOM_SUPPORT
10553 static void FAST_FUNC
10554 change_random(const char *value)
10555 {
10556         uint32_t t;
10557
10558         if (value == NULL) {
10559                 /* "get", generate */
10560                 t = next_random(&random_gen);
10561                 /* set without recursion */
10562                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10563                 vrandom.flags &= ~VNOFUNC;
10564         } else {
10565                 /* set/reset */
10566                 t = strtoul(value, NULL, 10);
10567                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10568         }
10569 }
10570 #endif
10571
10572 #if ENABLE_ASH_GETOPTS
10573 static int
10574 getopts(char *optstr, char *optvar, char **optfirst)
10575 {
10576         char *p, *q;
10577         char c = '?';
10578         int done = 0;
10579         char sbuf[2];
10580         char **optnext;
10581         int ind = shellparam.optind;
10582         int off = shellparam.optoff;
10583
10584         sbuf[1] = '\0';
10585
10586         shellparam.optind = -1;
10587         optnext = optfirst + ind - 1;
10588
10589         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10590                 p = NULL;
10591         else
10592                 p = optnext[-1] + off;
10593         if (p == NULL || *p == '\0') {
10594                 /* Current word is done, advance */
10595                 p = *optnext;
10596                 if (p == NULL || *p != '-' || *++p == '\0') {
10597  atend:
10598                         p = NULL;
10599                         done = 1;
10600                         goto out;
10601                 }
10602                 optnext++;
10603                 if (LONE_DASH(p))        /* check for "--" */
10604                         goto atend;
10605         }
10606
10607         c = *p++;
10608         for (q = optstr; *q != c;) {
10609                 if (*q == '\0') {
10610                         if (optstr[0] == ':') {
10611                                 sbuf[0] = c;
10612                                 /*sbuf[1] = '\0'; - already is */
10613                                 setvar0("OPTARG", sbuf);
10614                         } else {
10615                                 fprintf(stderr, "Illegal option -%c\n", c);
10616                                 unsetvar("OPTARG");
10617                         }
10618                         c = '?';
10619                         goto out;
10620                 }
10621                 if (*++q == ':')
10622                         q++;
10623         }
10624
10625         if (*++q == ':') {
10626                 if (*p == '\0' && (p = *optnext) == NULL) {
10627                         if (optstr[0] == ':') {
10628                                 sbuf[0] = c;
10629                                 /*sbuf[1] = '\0'; - already is */
10630                                 setvar0("OPTARG", sbuf);
10631                                 c = ':';
10632                         } else {
10633                                 fprintf(stderr, "No arg for -%c option\n", c);
10634                                 unsetvar("OPTARG");
10635                                 c = '?';
10636                         }
10637                         goto out;
10638                 }
10639
10640                 if (p == *optnext)
10641                         optnext++;
10642                 setvar0("OPTARG", p);
10643                 p = NULL;
10644         } else
10645                 setvar0("OPTARG", nullstr);
10646  out:
10647         ind = optnext - optfirst + 1;
10648         setvar("OPTIND", itoa(ind), VNOFUNC);
10649         sbuf[0] = c;
10650         /*sbuf[1] = '\0'; - already is */
10651         setvar0(optvar, sbuf);
10652
10653         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10654         shellparam.optind = ind;
10655
10656         return done;
10657 }
10658
10659 /*
10660  * The getopts builtin.  Shellparam.optnext points to the next argument
10661  * to be processed.  Shellparam.optptr points to the next character to
10662  * be processed in the current argument.  If shellparam.optnext is NULL,
10663  * then it's the first time getopts has been called.
10664  */
10665 static int FAST_FUNC
10666 getoptscmd(int argc, char **argv)
10667 {
10668         char **optbase;
10669
10670         if (argc < 3)
10671                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10672         if (argc == 3) {
10673                 optbase = shellparam.p;
10674                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10675                         shellparam.optind = 1;
10676                         shellparam.optoff = -1;
10677                 }
10678         } else {
10679                 optbase = &argv[3];
10680                 if ((unsigned)shellparam.optind > argc - 2) {
10681                         shellparam.optind = 1;
10682                         shellparam.optoff = -1;
10683                 }
10684         }
10685
10686         return getopts(argv[1], argv[2], optbase);
10687 }
10688 #endif /* ASH_GETOPTS */
10689
10690
10691 /* ============ Shell parser */
10692
10693 struct heredoc {
10694         struct heredoc *next;   /* next here document in list */
10695         union node *here;       /* redirection node */
10696         char *eofmark;          /* string indicating end of input */
10697         smallint striptabs;     /* if set, strip leading tabs */
10698 };
10699
10700 static smallint tokpushback;           /* last token pushed back */
10701 static smallint quoteflag;             /* set if (part of) last token was quoted */
10702 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10703 static struct heredoc *heredoclist;    /* list of here documents to read */
10704 static char *wordtext;                 /* text of last word returned by readtoken */
10705 static struct nodelist *backquotelist;
10706 static union node *redirnode;
10707 static struct heredoc *heredoc;
10708
10709 static const char *
10710 tokname(char *buf, int tok)
10711 {
10712         if (tok < TSEMI)
10713                 return tokname_array[tok];
10714         sprintf(buf, "\"%s\"", tokname_array[tok]);
10715         return buf;
10716 }
10717
10718 /* raise_error_unexpected_syntax:
10719  * Called when an unexpected token is read during the parse.  The argument
10720  * is the token that is expected, or -1 if more than one type of token can
10721  * occur at this point.
10722  */
10723 static void raise_error_unexpected_syntax(int) NORETURN;
10724 static void
10725 raise_error_unexpected_syntax(int token)
10726 {
10727         char msg[64];
10728         char buf[16];
10729         int l;
10730
10731         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10732         if (token >= 0)
10733                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10734         raise_error_syntax(msg);
10735         /* NOTREACHED */
10736 }
10737
10738 #define EOFMARKLEN 79
10739
10740 /* parsing is heavily cross-recursive, need these forward decls */
10741 static union node *andor(void);
10742 static union node *pipeline(void);
10743 static union node *parse_command(void);
10744 static void parseheredoc(void);
10745 static int peektoken(void);
10746 static int readtoken(void);
10747
10748 static union node *
10749 list(int nlflag)
10750 {
10751         union node *n1, *n2, *n3;
10752         int tok;
10753
10754         n1 = NULL;
10755         for (;;) {
10756                 switch (peektoken()) {
10757                 case TNL:
10758                         if (!(nlflag & 1))
10759                                 break;
10760                         parseheredoc();
10761                         return n1;
10762
10763                 case TEOF:
10764                         if (!n1 && (nlflag & 1))
10765                                 n1 = NODE_EOF;
10766                         parseheredoc();
10767                         return n1;
10768                 }
10769
10770                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10771                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10772                         return n1;
10773                 nlflag |= 2;
10774
10775                 n2 = andor();
10776                 tok = readtoken();
10777                 if (tok == TBACKGND) {
10778                         if (n2->type == NPIPE) {
10779                                 n2->npipe.pipe_backgnd = 1;
10780                         } else {
10781                                 if (n2->type != NREDIR) {
10782                                         n3 = stzalloc(sizeof(struct nredir));
10783                                         n3->nredir.n = n2;
10784                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10785                                         n2 = n3;
10786                                 }
10787                                 n2->type = NBACKGND;
10788                         }
10789                 }
10790                 if (n1 == NULL) {
10791                         n1 = n2;
10792                 } else {
10793                         n3 = stzalloc(sizeof(struct nbinary));
10794                         n3->type = NSEMI;
10795                         n3->nbinary.ch1 = n1;
10796                         n3->nbinary.ch2 = n2;
10797                         n1 = n3;
10798                 }
10799                 switch (tok) {
10800                 case TNL:
10801                 case TEOF:
10802                         tokpushback = 1;
10803                         /* fall through */
10804                 case TBACKGND:
10805                 case TSEMI:
10806                         break;
10807                 default:
10808                         if ((nlflag & 1))
10809                                 raise_error_unexpected_syntax(-1);
10810                         tokpushback = 1;
10811                         return n1;
10812                 }
10813         }
10814 }
10815
10816 static union node *
10817 andor(void)
10818 {
10819         union node *n1, *n2, *n3;
10820         int t;
10821
10822         n1 = pipeline();
10823         for (;;) {
10824                 t = readtoken();
10825                 if (t == TAND) {
10826                         t = NAND;
10827                 } else if (t == TOR) {
10828                         t = NOR;
10829                 } else {
10830                         tokpushback = 1;
10831                         return n1;
10832                 }
10833                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10834                 n2 = pipeline();
10835                 n3 = stzalloc(sizeof(struct nbinary));
10836                 n3->type = t;
10837                 n3->nbinary.ch1 = n1;
10838                 n3->nbinary.ch2 = n2;
10839                 n1 = n3;
10840         }
10841 }
10842
10843 static union node *
10844 pipeline(void)
10845 {
10846         union node *n1, *n2, *pipenode;
10847         struct nodelist *lp, *prev;
10848         int negate;
10849
10850         negate = 0;
10851         TRACE(("pipeline: entered\n"));
10852         if (readtoken() == TNOT) {
10853                 negate = !negate;
10854                 checkkwd = CHKKWD | CHKALIAS;
10855         } else
10856                 tokpushback = 1;
10857         n1 = parse_command();
10858         if (readtoken() == TPIPE) {
10859                 pipenode = stzalloc(sizeof(struct npipe));
10860                 pipenode->type = NPIPE;
10861                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10862                 lp = stzalloc(sizeof(struct nodelist));
10863                 pipenode->npipe.cmdlist = lp;
10864                 lp->n = n1;
10865                 do {
10866                         prev = lp;
10867                         lp = stzalloc(sizeof(struct nodelist));
10868                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10869                         lp->n = parse_command();
10870                         prev->next = lp;
10871                 } while (readtoken() == TPIPE);
10872                 lp->next = NULL;
10873                 n1 = pipenode;
10874         }
10875         tokpushback = 1;
10876         if (negate) {
10877                 n2 = stzalloc(sizeof(struct nnot));
10878                 n2->type = NNOT;
10879                 n2->nnot.com = n1;
10880                 return n2;
10881         }
10882         return n1;
10883 }
10884
10885 static union node *
10886 makename(void)
10887 {
10888         union node *n;
10889
10890         n = stzalloc(sizeof(struct narg));
10891         n->type = NARG;
10892         /*n->narg.next = NULL; - stzalloc did it */
10893         n->narg.text = wordtext;
10894         n->narg.backquote = backquotelist;
10895         return n;
10896 }
10897
10898 static void
10899 fixredir(union node *n, const char *text, int err)
10900 {
10901         int fd;
10902
10903         TRACE(("Fix redir %s %d\n", text, err));
10904         if (!err)
10905                 n->ndup.vname = NULL;
10906
10907         fd = bb_strtou(text, NULL, 10);
10908         if (!errno && fd >= 0)
10909                 n->ndup.dupfd = fd;
10910         else if (LONE_DASH(text))
10911                 n->ndup.dupfd = -1;
10912         else {
10913                 if (err)
10914                         raise_error_syntax("bad fd number");
10915                 n->ndup.vname = makename();
10916         }
10917 }
10918
10919 /*
10920  * Returns true if the text contains nothing to expand (no dollar signs
10921  * or backquotes).
10922  */
10923 static int
10924 noexpand(const char *text)
10925 {
10926         unsigned char c;
10927
10928         while ((c = *text++) != '\0') {
10929                 if (c == CTLQUOTEMARK)
10930                         continue;
10931                 if (c == CTLESC)
10932                         text++;
10933                 else if (SIT(c, BASESYNTAX) == CCTL)
10934                         return 0;
10935         }
10936         return 1;
10937 }
10938
10939 static void
10940 parsefname(void)
10941 {
10942         union node *n = redirnode;
10943
10944         if (readtoken() != TWORD)
10945                 raise_error_unexpected_syntax(-1);
10946         if (n->type == NHERE) {
10947                 struct heredoc *here = heredoc;
10948                 struct heredoc *p;
10949                 int i;
10950
10951                 if (quoteflag == 0)
10952                         n->type = NXHERE;
10953                 TRACE(("Here document %d\n", n->type));
10954                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10955                         raise_error_syntax("illegal eof marker for << redirection");
10956                 rmescapes(wordtext, 0);
10957                 here->eofmark = wordtext;
10958                 here->next = NULL;
10959                 if (heredoclist == NULL)
10960                         heredoclist = here;
10961                 else {
10962                         for (p = heredoclist; p->next; p = p->next)
10963                                 continue;
10964                         p->next = here;
10965                 }
10966         } else if (n->type == NTOFD || n->type == NFROMFD) {
10967                 fixredir(n, wordtext, 0);
10968         } else {
10969                 n->nfile.fname = makename();
10970         }
10971 }
10972
10973 static union node *
10974 simplecmd(void)
10975 {
10976         union node *args, **app;
10977         union node *n = NULL;
10978         union node *vars, **vpp;
10979         union node **rpp, *redir;
10980         int savecheckkwd;
10981 #if ENABLE_ASH_BASH_COMPAT
10982         smallint double_brackets_flag = 0;
10983         smallint function_flag = 0;
10984 #endif
10985
10986         args = NULL;
10987         app = &args;
10988         vars = NULL;
10989         vpp = &vars;
10990         redir = NULL;
10991         rpp = &redir;
10992
10993         savecheckkwd = CHKALIAS;
10994         for (;;) {
10995                 int t;
10996                 checkkwd = savecheckkwd;
10997                 t = readtoken();
10998                 switch (t) {
10999 #if ENABLE_ASH_BASH_COMPAT
11000                 case TFUNCTION:
11001                         if (peektoken() != TWORD)
11002                                 raise_error_unexpected_syntax(TWORD);
11003                         function_flag = 1;
11004                         break;
11005                 case TAND: /* "&&" */
11006                 case TOR: /* "||" */
11007                         if (!double_brackets_flag) {
11008                                 tokpushback = 1;
11009                                 goto out;
11010                         }
11011                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11012 #endif
11013                 case TWORD:
11014                         n = stzalloc(sizeof(struct narg));
11015                         n->type = NARG;
11016                         /*n->narg.next = NULL; - stzalloc did it */
11017                         n->narg.text = wordtext;
11018 #if ENABLE_ASH_BASH_COMPAT
11019                         if (strcmp("[[", wordtext) == 0)
11020                                 double_brackets_flag = 1;
11021                         else if (strcmp("]]", wordtext) == 0)
11022                                 double_brackets_flag = 0;
11023 #endif
11024                         n->narg.backquote = backquotelist;
11025                         if (savecheckkwd && isassignment(wordtext)) {
11026                                 *vpp = n;
11027                                 vpp = &n->narg.next;
11028                         } else {
11029                                 *app = n;
11030                                 app = &n->narg.next;
11031                                 savecheckkwd = 0;
11032                         }
11033 #if ENABLE_ASH_BASH_COMPAT
11034                         if (function_flag) {
11035                                 checkkwd = CHKNL | CHKKWD;
11036                                 switch (peektoken()) {
11037                                 case TBEGIN:
11038                                 case TIF:
11039                                 case TCASE:
11040                                 case TUNTIL:
11041                                 case TWHILE:
11042                                 case TFOR:
11043                                         goto do_func;
11044                                 case TLP:
11045                                         function_flag = 0;
11046                                         break;
11047                                 case TWORD:
11048                                         if (strcmp("[[", wordtext) == 0)
11049                                                 goto do_func;
11050                                         /* fall through */
11051                                 default:
11052                                         raise_error_unexpected_syntax(-1);
11053                                 }
11054                         }
11055 #endif
11056                         break;
11057                 case TREDIR:
11058                         *rpp = n = redirnode;
11059                         rpp = &n->nfile.next;
11060                         parsefname();   /* read name of redirection file */
11061                         break;
11062                 case TLP:
11063  IF_ASH_BASH_COMPAT(do_func:)
11064                         if (args && app == &args->narg.next
11065                          && !vars && !redir
11066                         ) {
11067                                 struct builtincmd *bcmd;
11068                                 const char *name;
11069
11070                                 /* We have a function */
11071                                 if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP)
11072                                         raise_error_unexpected_syntax(TRP);
11073                                 name = n->narg.text;
11074                                 if (!goodname(name)
11075                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11076                                 ) {
11077                                         raise_error_syntax("bad function name");
11078                                 }
11079                                 n->type = NDEFUN;
11080                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11081                                 n->narg.next = parse_command();
11082                                 return n;
11083                         }
11084                         IF_ASH_BASH_COMPAT(function_flag = 0;)
11085                         /* fall through */
11086                 default:
11087                         tokpushback = 1;
11088                         goto out;
11089                 }
11090         }
11091  out:
11092         *app = NULL;
11093         *vpp = NULL;
11094         *rpp = NULL;
11095         n = stzalloc(sizeof(struct ncmd));
11096         n->type = NCMD;
11097         n->ncmd.args = args;
11098         n->ncmd.assign = vars;
11099         n->ncmd.redirect = redir;
11100         return n;
11101 }
11102
11103 static union node *
11104 parse_command(void)
11105 {
11106         union node *n1, *n2;
11107         union node *ap, **app;
11108         union node *cp, **cpp;
11109         union node *redir, **rpp;
11110         union node **rpp2;
11111         int t;
11112
11113         redir = NULL;
11114         rpp2 = &redir;
11115
11116         switch (readtoken()) {
11117         default:
11118                 raise_error_unexpected_syntax(-1);
11119                 /* NOTREACHED */
11120         case TIF:
11121                 n1 = stzalloc(sizeof(struct nif));
11122                 n1->type = NIF;
11123                 n1->nif.test = list(0);
11124                 if (readtoken() != TTHEN)
11125                         raise_error_unexpected_syntax(TTHEN);
11126                 n1->nif.ifpart = list(0);
11127                 n2 = n1;
11128                 while (readtoken() == TELIF) {
11129                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11130                         n2 = n2->nif.elsepart;
11131                         n2->type = NIF;
11132                         n2->nif.test = list(0);
11133                         if (readtoken() != TTHEN)
11134                                 raise_error_unexpected_syntax(TTHEN);
11135                         n2->nif.ifpart = list(0);
11136                 }
11137                 if (lasttoken == TELSE)
11138                         n2->nif.elsepart = list(0);
11139                 else {
11140                         n2->nif.elsepart = NULL;
11141                         tokpushback = 1;
11142                 }
11143                 t = TFI;
11144                 break;
11145         case TWHILE:
11146         case TUNTIL: {
11147                 int got;
11148                 n1 = stzalloc(sizeof(struct nbinary));
11149                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11150                 n1->nbinary.ch1 = list(0);
11151                 got = readtoken();
11152                 if (got != TDO) {
11153                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11154                                         got == TWORD ? wordtext : ""));
11155                         raise_error_unexpected_syntax(TDO);
11156                 }
11157                 n1->nbinary.ch2 = list(0);
11158                 t = TDONE;
11159                 break;
11160         }
11161         case TFOR:
11162                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11163                         raise_error_syntax("bad for loop variable");
11164                 n1 = stzalloc(sizeof(struct nfor));
11165                 n1->type = NFOR;
11166                 n1->nfor.var = wordtext;
11167                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11168                 if (readtoken() == TIN) {
11169                         app = &ap;
11170                         while (readtoken() == TWORD) {
11171                                 n2 = stzalloc(sizeof(struct narg));
11172                                 n2->type = NARG;
11173                                 /*n2->narg.next = NULL; - stzalloc did it */
11174                                 n2->narg.text = wordtext;
11175                                 n2->narg.backquote = backquotelist;
11176                                 *app = n2;
11177                                 app = &n2->narg.next;
11178                         }
11179                         *app = NULL;
11180                         n1->nfor.args = ap;
11181                         if (lasttoken != TNL && lasttoken != TSEMI)
11182                                 raise_error_unexpected_syntax(-1);
11183                 } else {
11184                         n2 = stzalloc(sizeof(struct narg));
11185                         n2->type = NARG;
11186                         /*n2->narg.next = NULL; - stzalloc did it */
11187                         n2->narg.text = (char *)dolatstr;
11188                         /*n2->narg.backquote = NULL;*/
11189                         n1->nfor.args = n2;
11190                         /*
11191                          * Newline or semicolon here is optional (but note
11192                          * that the original Bourne shell only allowed NL).
11193                          */
11194                         if (lasttoken != TSEMI)
11195                                 tokpushback = 1;
11196                 }
11197                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11198                 if (readtoken() != TDO)
11199                         raise_error_unexpected_syntax(TDO);
11200                 n1->nfor.body = list(0);
11201                 t = TDONE;
11202                 break;
11203         case TCASE:
11204                 n1 = stzalloc(sizeof(struct ncase));
11205                 n1->type = NCASE;
11206                 if (readtoken() != TWORD)
11207                         raise_error_unexpected_syntax(TWORD);
11208                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11209                 n2->type = NARG;
11210                 /*n2->narg.next = NULL; - stzalloc did it */
11211                 n2->narg.text = wordtext;
11212                 n2->narg.backquote = backquotelist;
11213                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11214                 if (readtoken() != TIN)
11215                         raise_error_unexpected_syntax(TIN);
11216                 cpp = &n1->ncase.cases;
11217  next_case:
11218                 checkkwd = CHKNL | CHKKWD;
11219                 t = readtoken();
11220                 while (t != TESAC) {
11221                         if (lasttoken == TLP)
11222                                 readtoken();
11223                         *cpp = cp = stzalloc(sizeof(struct nclist));
11224                         cp->type = NCLIST;
11225                         app = &cp->nclist.pattern;
11226                         for (;;) {
11227                                 *app = ap = stzalloc(sizeof(struct narg));
11228                                 ap->type = NARG;
11229                                 /*ap->narg.next = NULL; - stzalloc did it */
11230                                 ap->narg.text = wordtext;
11231                                 ap->narg.backquote = backquotelist;
11232                                 if (readtoken() != TPIPE)
11233                                         break;
11234                                 app = &ap->narg.next;
11235                                 readtoken();
11236                         }
11237                         //ap->narg.next = NULL;
11238                         if (lasttoken != TRP)
11239                                 raise_error_unexpected_syntax(TRP);
11240                         cp->nclist.body = list(2);
11241
11242                         cpp = &cp->nclist.next;
11243
11244                         checkkwd = CHKNL | CHKKWD;
11245                         t = readtoken();
11246                         if (t != TESAC) {
11247                                 if (t != TENDCASE)
11248                                         raise_error_unexpected_syntax(TENDCASE);
11249                                 goto next_case;
11250                         }
11251                 }
11252                 *cpp = NULL;
11253                 goto redir;
11254         case TLP:
11255                 n1 = stzalloc(sizeof(struct nredir));
11256                 n1->type = NSUBSHELL;
11257                 n1->nredir.n = list(0);
11258                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11259                 t = TRP;
11260                 break;
11261         case TBEGIN:
11262                 n1 = list(0);
11263                 t = TEND;
11264                 break;
11265         IF_ASH_BASH_COMPAT(case TFUNCTION:)
11266         case TWORD:
11267         case TREDIR:
11268                 tokpushback = 1;
11269                 return simplecmd();
11270         }
11271
11272         if (readtoken() != t)
11273                 raise_error_unexpected_syntax(t);
11274
11275  redir:
11276         /* Now check for redirection which may follow command */
11277         checkkwd = CHKKWD | CHKALIAS;
11278         rpp = rpp2;
11279         while (readtoken() == TREDIR) {
11280                 *rpp = n2 = redirnode;
11281                 rpp = &n2->nfile.next;
11282                 parsefname();
11283         }
11284         tokpushback = 1;
11285         *rpp = NULL;
11286         if (redir) {
11287                 if (n1->type != NSUBSHELL) {
11288                         n2 = stzalloc(sizeof(struct nredir));
11289                         n2->type = NREDIR;
11290                         n2->nredir.n = n1;
11291                         n1 = n2;
11292                 }
11293                 n1->nredir.redirect = redir;
11294         }
11295         return n1;
11296 }
11297
11298 #if ENABLE_ASH_BASH_COMPAT
11299 static int
11300 decode_dollar_squote(void)
11301 {
11302         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11303         int c, cnt;
11304         char *p;
11305         char buf[4];
11306
11307         c = pgetc();
11308         p = strchr(C_escapes, c);
11309         if (p) {
11310                 buf[0] = c;
11311                 p = buf;
11312                 cnt = 3;
11313                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11314                         do {
11315                                 c = pgetc();
11316                                 *++p = c;
11317                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11318                         pungetc();
11319                 } else if (c == 'x') { /* \xHH */
11320                         do {
11321                                 c = pgetc();
11322                                 *++p = c;
11323                         } while (isxdigit(c) && --cnt);
11324                         pungetc();
11325                         if (cnt == 3) { /* \x but next char is "bad" */
11326                                 c = 'x';
11327                                 goto unrecognized;
11328                         }
11329                 } else { /* simple seq like \\ or \t */
11330                         p++;
11331                 }
11332                 *p = '\0';
11333                 p = buf;
11334                 c = bb_process_escape_sequence((void*)&p);
11335         } else { /* unrecognized "\z": print both chars unless ' or " */
11336                 if (c != '\'' && c != '"') {
11337  unrecognized:
11338                         c |= 0x100; /* "please encode \, then me" */
11339                 }
11340         }
11341         return c;
11342 }
11343 #endif
11344
11345 /*
11346  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11347  * is not NULL, read a here document.  In the latter case, eofmark is the
11348  * word which marks the end of the document and striptabs is true if
11349  * leading tabs should be stripped from the document.  The argument c
11350  * is the first character of the input token or document.
11351  *
11352  * Because C does not have internal subroutines, I have simulated them
11353  * using goto's to implement the subroutine linkage.  The following macros
11354  * will run code that appears at the end of readtoken1.
11355  */
11356 #define CHECKEND()      {goto checkend; checkend_return:;}
11357 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11358 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11359 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11360 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11361 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11362 static int
11363 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11364 {
11365         /* NB: syntax parameter fits into smallint */
11366         /* c parameter is an unsigned char or PEOF or PEOA */
11367         char *out;
11368         size_t len;
11369         char line[EOFMARKLEN + 1];
11370         struct nodelist *bqlist;
11371         smallint quotef;
11372         smallint dblquote;
11373         smallint oldstyle;
11374         smallint prevsyntax; /* syntax before arithmetic */
11375 #if ENABLE_ASH_EXPAND_PRMT
11376         smallint pssyntax;   /* we are expanding a prompt string */
11377 #endif
11378         int varnest;         /* levels of variables expansion */
11379         int arinest;         /* levels of arithmetic expansion */
11380         int parenlevel;      /* levels of parens in arithmetic */
11381         int dqvarnest;       /* levels of variables expansion within double quotes */
11382
11383         IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
11384
11385         startlinno = g_parsefile->linno;
11386         bqlist = NULL;
11387         quotef = 0;
11388         prevsyntax = 0;
11389 #if ENABLE_ASH_EXPAND_PRMT
11390         pssyntax = (syntax == PSSYNTAX);
11391         if (pssyntax)
11392                 syntax = DQSYNTAX;
11393 #endif
11394         dblquote = (syntax == DQSYNTAX);
11395         varnest = 0;
11396         arinest = 0;
11397         parenlevel = 0;
11398         dqvarnest = 0;
11399
11400         STARTSTACKSTR(out);
11401  loop:
11402         /* For each line, until end of word */
11403         CHECKEND();     /* set c to PEOF if at end of here document */
11404         for (;;) {      /* until end of line or end of word */
11405                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11406                 switch (SIT(c, syntax)) {
11407                 case CNL:       /* '\n' */
11408                         if (syntax == BASESYNTAX)
11409                                 goto endword;   /* exit outer loop */
11410                         USTPUTC(c, out);
11411                         nlprompt();
11412                         c = pgetc();
11413                         goto loop;              /* continue outer loop */
11414                 case CWORD:
11415                         USTPUTC(c, out);
11416                         break;
11417                 case CCTL:
11418 #if ENABLE_ASH_BASH_COMPAT
11419                         if (c == '\\' && bash_dollar_squote) {
11420                                 c = decode_dollar_squote();
11421                                 if (c == '\0') {
11422                                         /* skip $'\000', $'\x00' (like bash) */
11423                                         break;
11424                                 }
11425                                 if (c & 0x100) {
11426                                         /* Unknown escape. Encode as '\z' */
11427                                         c = (unsigned char)c;
11428                                         if (eofmark == NULL || dblquote)
11429                                                 USTPUTC(CTLESC, out);
11430                                         USTPUTC('\\', out);
11431                                 }
11432                         }
11433 #endif
11434                         if (eofmark == NULL || dblquote)
11435                                 USTPUTC(CTLESC, out);
11436                         USTPUTC(c, out);
11437                         break;
11438                 case CBACK:     /* backslash */
11439                         c = pgetc_without_PEOA();
11440                         if (c == PEOF) {
11441                                 USTPUTC(CTLESC, out);
11442                                 USTPUTC('\\', out);
11443                                 pungetc();
11444                         } else if (c == '\n') {
11445                                 nlprompt();
11446                         } else {
11447 #if ENABLE_ASH_EXPAND_PRMT
11448                                 if (c == '$' && pssyntax) {
11449                                         USTPUTC(CTLESC, out);
11450                                         USTPUTC('\\', out);
11451                                 }
11452 #endif
11453                                 /* Backslash is retained if we are in "str" and next char isn't special */
11454                                 if (dblquote
11455                                  && c != '\\'
11456                                  && c != '`'
11457                                  && c != '$'
11458                                  && (c != '"' || eofmark != NULL)
11459                                 ) {
11460                                         USTPUTC('\\', out);
11461                                 }
11462                                 USTPUTC(CTLESC, out);
11463                                 USTPUTC(c, out);
11464                                 quotef = 1;
11465                         }
11466                         break;
11467                 case CSQUOTE:
11468                         syntax = SQSYNTAX;
11469  quotemark:
11470                         if (eofmark == NULL) {
11471                                 USTPUTC(CTLQUOTEMARK, out);
11472                         }
11473                         break;
11474                 case CDQUOTE:
11475                         syntax = DQSYNTAX;
11476                         dblquote = 1;
11477                         goto quotemark;
11478                 case CENDQUOTE:
11479                         IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
11480                         if (eofmark != NULL && varnest == 0) {
11481                                 USTPUTC(c, out);
11482                         } else {
11483                                 if (dqvarnest == 0) {
11484                                         syntax = BASESYNTAX;
11485                                         dblquote = 0;
11486                                 }
11487                                 quotef = 1;
11488                                 goto quotemark;
11489                         }
11490                         break;
11491                 case CVAR:      /* '$' */
11492                         PARSESUB();             /* parse substitution */
11493                         break;
11494                 case CENDVAR:   /* '}' */
11495                         if (varnest > 0) {
11496                                 varnest--;
11497                                 if (dqvarnest > 0) {
11498                                         dqvarnest--;
11499                                 }
11500                                 c = CTLENDVAR;
11501                         }
11502                         USTPUTC(c, out);
11503                         break;
11504 #if ENABLE_SH_MATH_SUPPORT
11505                 case CLP:       /* '(' in arithmetic */
11506                         parenlevel++;
11507                         USTPUTC(c, out);
11508                         break;
11509                 case CRP:       /* ')' in arithmetic */
11510                         if (parenlevel > 0) {
11511                                 parenlevel--;
11512                         } else {
11513                                 if (pgetc_eatbnl() == ')') {
11514                                         c = CTLENDARI;
11515                                         if (--arinest == 0) {
11516                                                 syntax = prevsyntax;
11517                                         }
11518                                 } else {
11519                                         /*
11520                                          * unbalanced parens
11521                                          * (don't 2nd guess - no error)
11522                                          */
11523                                         pungetc();
11524                                 }
11525                         }
11526                         USTPUTC(c, out);
11527                         break;
11528 #endif
11529                 case CBQUOTE:   /* '`' */
11530                         PARSEBACKQOLD();
11531                         break;
11532                 case CENDFILE:
11533                         goto endword;           /* exit outer loop */
11534                 case CIGN:
11535                         break;
11536                 default:
11537                         if (varnest == 0) {
11538 #if ENABLE_ASH_BASH_COMPAT
11539                                 if (c == '&') {
11540 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11541                                         if (pgetc() == '>')
11542                                                 c = 0x100 + '>'; /* flag &> */
11543                                         pungetc();
11544                                 }
11545 #endif
11546                                 goto endword;   /* exit outer loop */
11547                         }
11548                         IF_ASH_ALIAS(if (c != PEOA))
11549                                 USTPUTC(c, out);
11550                 }
11551                 c = pgetc();
11552         } /* for (;;) */
11553  endword:
11554
11555 #if ENABLE_SH_MATH_SUPPORT
11556         if (syntax == ARISYNTAX)
11557                 raise_error_syntax("missing '))'");
11558 #endif
11559         if (syntax != BASESYNTAX && eofmark == NULL)
11560                 raise_error_syntax("unterminated quoted string");
11561         if (varnest != 0) {
11562                 startlinno = g_parsefile->linno;
11563                 /* { */
11564                 raise_error_syntax("missing '}'");
11565         }
11566         USTPUTC('\0', out);
11567         len = out - (char *)stackblock();
11568         out = stackblock();
11569         if (eofmark == NULL) {
11570                 if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>'))
11571                  && quotef == 0
11572                 ) {
11573                         if (isdigit_str9(out)) {
11574                                 PARSEREDIR(); /* passed as params: out, c */
11575                                 lasttoken = TREDIR;
11576                                 return lasttoken;
11577                         }
11578                         /* else: non-number X seen, interpret it
11579                          * as "NNNX>file" = "NNNX >file" */
11580                 }
11581                 pungetc();
11582         }
11583         quoteflag = quotef;
11584         backquotelist = bqlist;
11585         grabstackblock(len);
11586         wordtext = out;
11587         lasttoken = TWORD;
11588         return lasttoken;
11589 /* end of readtoken routine */
11590
11591 /*
11592  * Check to see whether we are at the end of the here document.  When this
11593  * is called, c is set to the first character of the next input line.  If
11594  * we are at the end of the here document, this routine sets the c to PEOF.
11595  */
11596 checkend: {
11597         if (eofmark) {
11598 #if ENABLE_ASH_ALIAS
11599                 if (c == PEOA)
11600                         c = pgetc_without_PEOA();
11601 #endif
11602                 if (striptabs) {
11603                         while (c == '\t') {
11604                                 c = pgetc_without_PEOA();
11605                         }
11606                 }
11607                 if (c == *eofmark) {
11608                         if (pfgets(line, sizeof(line)) != NULL) {
11609                                 char *p, *q;
11610                                 int cc;
11611
11612                                 p = line;
11613                                 for (q = eofmark + 1;; p++, q++) {
11614                                         cc = *p;
11615                                         if (cc == '\n')
11616                                                 cc = 0;
11617                                         if (!*q || cc != *q)
11618                                                 break;
11619                                 }
11620                                 if (cc == *q) {
11621                                         c = PEOF;
11622                                         nlnoprompt();
11623                                 } else {
11624                                         pushstring(line, NULL);
11625                                 }
11626                         }
11627                 }
11628         }
11629         goto checkend_return;
11630 }
11631
11632 /*
11633  * Parse a redirection operator.  The variable "out" points to a string
11634  * specifying the fd to be redirected.  The variable "c" contains the
11635  * first character of the redirection operator.
11636  */
11637 parseredir: {
11638         /* out is already checked to be a valid number or "" */
11639         int fd = (*out == '\0' ? -1 : atoi(out));
11640         union node *np;
11641
11642         np = stzalloc(sizeof(struct nfile));
11643         if (c == '>') {
11644                 np->nfile.fd = 1;
11645                 c = pgetc();
11646                 if (c == '>')
11647                         np->type = NAPPEND;
11648                 else if (c == '|')
11649                         np->type = NCLOBBER;
11650                 else if (c == '&')
11651                         np->type = NTOFD;
11652                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11653                 else {
11654                         np->type = NTO;
11655                         pungetc();
11656                 }
11657         }
11658 #if ENABLE_ASH_BASH_COMPAT
11659         else if (c == 0x100 + '>') { /* this flags &> redirection */
11660                 np->nfile.fd = 1;
11661                 pgetc(); /* this is '>', no need to check */
11662                 np->type = NTO2;
11663         }
11664 #endif
11665         else { /* c == '<' */
11666                 /*np->nfile.fd = 0; - stzalloc did it */
11667                 c = pgetc();
11668                 switch (c) {
11669                 case '<':
11670                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11671                                 np = stzalloc(sizeof(struct nhere));
11672                                 /*np->nfile.fd = 0; - stzalloc did it */
11673                         }
11674                         np->type = NHERE;
11675                         heredoc = stzalloc(sizeof(struct heredoc));
11676                         heredoc->here = np;
11677                         c = pgetc();
11678                         if (c == '-') {
11679                                 heredoc->striptabs = 1;
11680                         } else {
11681                                 /*heredoc->striptabs = 0; - stzalloc did it */
11682                                 pungetc();
11683                         }
11684                         break;
11685
11686                 case '&':
11687                         np->type = NFROMFD;
11688                         break;
11689
11690                 case '>':
11691                         np->type = NFROMTO;
11692                         break;
11693
11694                 default:
11695                         np->type = NFROM;
11696                         pungetc();
11697                         break;
11698                 }
11699         }
11700         if (fd >= 0)
11701                 np->nfile.fd = fd;
11702         redirnode = np;
11703         goto parseredir_return;
11704 }
11705
11706 /*
11707  * Parse a substitution.  At this point, we have read the dollar sign
11708  * and nothing else.
11709  */
11710
11711 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11712  * (assuming ascii char codes, as the original implementation did) */
11713 #define is_special(c) \
11714         (((unsigned)(c) - 33 < 32) \
11715                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11716 parsesub: {
11717         unsigned char subtype;
11718         int typeloc;
11719
11720         c = pgetc_eatbnl();
11721         if (c > 255 /* PEOA or PEOF */
11722          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11723         ) {
11724 #if ENABLE_ASH_BASH_COMPAT
11725                 if (syntax != DQSYNTAX && c == '\'')
11726                         bash_dollar_squote = 1;
11727                 else
11728 #endif
11729                         USTPUTC('$', out);
11730                 pungetc();
11731         } else if (c == '(') {
11732                 /* $(command) or $((arith)) */
11733                 if (pgetc_eatbnl() == '(') {
11734 #if ENABLE_SH_MATH_SUPPORT
11735                         PARSEARITH();
11736 #else
11737                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11738 #endif
11739                 } else {
11740                         pungetc();
11741                         PARSEBACKQNEW();
11742                 }
11743         } else {
11744                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11745                 USTPUTC(CTLVAR, out);
11746                 typeloc = out - (char *)stackblock();
11747                 STADJUST(1, out);
11748                 subtype = VSNORMAL;
11749                 if (c == '{') {
11750                         c = pgetc_eatbnl();
11751                         subtype = 0;
11752                 }
11753  varname:
11754                 if (is_name(c)) {
11755                         /* $[{[#]]NAME[}] */
11756                         do {
11757                                 STPUTC(c, out);
11758                                 c = pgetc_eatbnl();
11759                         } while (is_in_name(c));
11760                 } else if (isdigit(c)) {
11761                         /* $[{[#]]NUM[}] */
11762                         do {
11763                                 STPUTC(c, out);
11764                                 c = pgetc_eatbnl();
11765                         } while (isdigit(c));
11766                 } else if (is_special(c)) {
11767                         /* $[{[#]]<specialchar>[}] */
11768                         int cc = c;
11769
11770                         c = pgetc_eatbnl();
11771                         if (!subtype && cc == '#') {
11772                                 subtype = VSLENGTH;
11773                                 if (c == '_' || isalnum(c))
11774                                         goto varname;
11775                                 cc = c;
11776                                 c = pgetc_eatbnl();
11777                                 if (cc == '}' || c != '}') {
11778                                         pungetc();
11779                                         subtype = 0;
11780                                         c = cc;
11781                                         cc = '#';
11782                                 }
11783                         }
11784                         USTPUTC(cc, out);
11785                 } else {
11786                         goto badsub;
11787                 }
11788                 if (c != '}' && subtype == VSLENGTH) {
11789                         /* ${#VAR didn't end with } */
11790                         goto badsub;
11791                 }
11792
11793                 if (subtype == 0) {
11794                         static const char types[] ALIGN1 = "}-+?=";
11795                         /* ${VAR...} but not $VAR or ${#VAR} */
11796                         /* c == first char after VAR */
11797                         switch (c) {
11798                         case ':':
11799                                 c = pgetc_eatbnl();
11800 #if ENABLE_ASH_BASH_COMPAT
11801                                 /* This check is only needed to not misinterpret
11802                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11803                                  * constructs.
11804                                  */
11805                                 if (!strchr(types, c)) {
11806                                         subtype = VSSUBSTR;
11807                                         pungetc();
11808                                         break; /* "goto badsub" is bigger (!) */
11809                                 }
11810 #endif
11811                                 subtype = VSNUL;
11812                                 /*FALLTHROUGH*/
11813                         default: {
11814                                 const char *p = strchr(types, c);
11815                                 if (p == NULL)
11816                                         break;
11817                                 subtype |= p - types + VSNORMAL;
11818                                 break;
11819                         }
11820                         case '%':
11821                         case '#': {
11822                                 int cc = c;
11823                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11824                                 c = pgetc_eatbnl();
11825                                 if (c != cc)
11826                                         goto badsub;
11827                                 subtype++;
11828                                 break;
11829                         }
11830 #if ENABLE_ASH_BASH_COMPAT
11831                         case '/':
11832                                 /* ${v/[/]pattern/repl} */
11833 //TODO: encode pattern and repl separately.
11834 // Currently ${v/$var_with_slash/repl} is horribly broken
11835                                 subtype = VSREPLACE;
11836                                 c = pgetc_eatbnl();
11837                                 if (c != '/')
11838                                         goto badsub;
11839                                 subtype++; /* VSREPLACEALL */
11840                                 break;
11841 #endif
11842                         }
11843                 } else {
11844  badsub:
11845                         pungetc();
11846                 }
11847                 ((unsigned char *)stackblock())[typeloc] = subtype;
11848                 if (subtype != VSNORMAL) {
11849                         varnest++;
11850                         if (dblquote)
11851                                 dqvarnest++;
11852                 }
11853                 STPUTC('=', out);
11854         }
11855         goto parsesub_return;
11856 }
11857
11858 /*
11859  * Called to parse command substitutions.  Newstyle is set if the command
11860  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11861  * list of commands (passed by reference), and savelen is the number of
11862  * characters on the top of the stack which must be preserved.
11863  */
11864 parsebackq: {
11865         struct nodelist **nlpp;
11866         union node *n;
11867         char *str;
11868         size_t savelen;
11869         smallint saveprompt = 0;
11870
11871         str = NULL;
11872         savelen = out - (char *)stackblock();
11873         if (savelen > 0) {
11874                 /*
11875                  * FIXME: this can allocate very large block on stack and SEGV.
11876                  * Example:
11877                  * echo "..<100kbytes>..`true` $(true) `true` ..."
11878                  * allocates 100kb for every command subst. With about
11879                  * a hundred command substitutions stack overflows.
11880                  * With larger prepended string, SEGV happens sooner.
11881                  */
11882                 str = alloca(savelen);
11883                 memcpy(str, stackblock(), savelen);
11884         }
11885
11886         if (oldstyle) {
11887                 /* We must read until the closing backquote, giving special
11888                  * treatment to some slashes, and then push the string and
11889                  * reread it as input, interpreting it normally.
11890                  */
11891                 char *pout;
11892                 size_t psavelen;
11893                 char *pstr;
11894
11895                 STARTSTACKSTR(pout);
11896                 for (;;) {
11897                         int pc;
11898
11899                         setprompt_if(needprompt, 2);
11900                         pc = pgetc();
11901                         switch (pc) {
11902                         case '`':
11903                                 goto done;
11904
11905                         case '\\':
11906                                 pc = pgetc();
11907                                 if (pc == '\n') {
11908                                         nlprompt();
11909                                         /*
11910                                          * If eating a newline, avoid putting
11911                                          * the newline into the new character
11912                                          * stream (via the STPUTC after the
11913                                          * switch).
11914                                          */
11915                                         continue;
11916                                 }
11917                                 if (pc != '\\' && pc != '`' && pc != '$'
11918                                  && (!dblquote || pc != '"')
11919                                 ) {
11920                                         STPUTC('\\', pout);
11921                                 }
11922                                 if (pc <= 255 /* not PEOA or PEOF */) {
11923                                         break;
11924                                 }
11925                                 /* fall through */
11926
11927                         case PEOF:
11928                         IF_ASH_ALIAS(case PEOA:)
11929                                 startlinno = g_parsefile->linno;
11930                                 raise_error_syntax("EOF in backquote substitution");
11931
11932                         case '\n':
11933                                 nlnoprompt();
11934                                 break;
11935
11936                         default:
11937                                 break;
11938                         }
11939                         STPUTC(pc, pout);
11940                 }
11941  done:
11942                 STPUTC('\0', pout);
11943                 psavelen = pout - (char *)stackblock();
11944                 if (psavelen > 0) {
11945                         pstr = grabstackstr(pout);
11946                         setinputstring(pstr);
11947                 }
11948         }
11949         nlpp = &bqlist;
11950         while (*nlpp)
11951                 nlpp = &(*nlpp)->next;
11952         *nlpp = stzalloc(sizeof(**nlpp));
11953         /* (*nlpp)->next = NULL; - stzalloc did it */
11954
11955         if (oldstyle) {
11956                 saveprompt = doprompt;
11957                 doprompt = 0;
11958         }
11959
11960         n = list(2);
11961
11962         if (oldstyle)
11963                 doprompt = saveprompt;
11964         else if (readtoken() != TRP)
11965                 raise_error_unexpected_syntax(TRP);
11966
11967         (*nlpp)->n = n;
11968         if (oldstyle) {
11969                 /*
11970                  * Start reading from old file again, ignoring any pushed back
11971                  * tokens left from the backquote parsing
11972                  */
11973                 popfile();
11974                 tokpushback = 0;
11975         }
11976         while (stackblocksize() <= savelen)
11977                 growstackblock();
11978         STARTSTACKSTR(out);
11979         if (str) {
11980                 memcpy(out, str, savelen);
11981                 STADJUST(savelen, out);
11982         }
11983         USTPUTC(CTLBACKQ, out);
11984         if (oldstyle)
11985                 goto parsebackq_oldreturn;
11986         goto parsebackq_newreturn;
11987 }
11988
11989 #if ENABLE_SH_MATH_SUPPORT
11990 /*
11991  * Parse an arithmetic expansion (indicate start of one and set state)
11992  */
11993 parsearith: {
11994         if (++arinest == 1) {
11995                 prevsyntax = syntax;
11996                 syntax = ARISYNTAX;
11997         }
11998         USTPUTC(CTLARI, out);
11999         goto parsearith_return;
12000 }
12001 #endif
12002 } /* end of readtoken */
12003
12004 /*
12005  * Read the next input token.
12006  * If the token is a word, we set backquotelist to the list of cmds in
12007  *      backquotes.  We set quoteflag to true if any part of the word was
12008  *      quoted.
12009  * If the token is TREDIR, then we set redirnode to a structure containing
12010  *      the redirection.
12011  * In all cases, the variable startlinno is set to the number of the line
12012  *      on which the token starts.
12013  *
12014  * [Change comment:  here documents and internal procedures]
12015  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12016  *  word parsing code into a separate routine.  In this case, readtoken
12017  *  doesn't need to have any internal procedures, but parseword does.
12018  *  We could also make parseoperator in essence the main routine, and
12019  *  have parseword (readtoken1?) handle both words and redirection.]
12020  */
12021 #define NEW_xxreadtoken
12022 #ifdef NEW_xxreadtoken
12023 /* singles must be first! */
12024 static const char xxreadtoken_chars[7] ALIGN1 = {
12025         '\n', '(', ')', /* singles */
12026         '&', '|', ';',  /* doubles */
12027         0
12028 };
12029
12030 #define xxreadtoken_singles 3
12031 #define xxreadtoken_doubles 3
12032
12033 static const char xxreadtoken_tokens[] ALIGN1 = {
12034         TNL, TLP, TRP,          /* only single occurrence allowed */
12035         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12036         TEOF,                   /* corresponds to trailing nul */
12037         TAND, TOR, TENDCASE     /* if double occurrence */
12038 };
12039
12040 static int
12041 xxreadtoken(void)
12042 {
12043         int c;
12044
12045         if (tokpushback) {
12046                 tokpushback = 0;
12047                 return lasttoken;
12048         }
12049         setprompt_if(needprompt, 2);
12050         startlinno = g_parsefile->linno;
12051         for (;;) {                      /* until token or start of word found */
12052                 c = pgetc();
12053                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12054                         continue;
12055
12056                 if (c == '#') {
12057                         while ((c = pgetc()) != '\n' && c != PEOF)
12058                                 continue;
12059                         pungetc();
12060                 } else if (c == '\\') {
12061                         if (pgetc() != '\n') {
12062                                 pungetc();
12063                                 break; /* return readtoken1(...) */
12064                         }
12065                         nlprompt();
12066                 } else {
12067                         const char *p;
12068
12069                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12070                         if (c != PEOF) {
12071                                 if (c == '\n') {
12072                                         nlnoprompt();
12073                                 }
12074
12075                                 p = strchr(xxreadtoken_chars, c);
12076                                 if (p == NULL)
12077                                         break; /* return readtoken1(...) */
12078
12079                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12080                                         int cc = pgetc();
12081                                         if (cc == c) {    /* double occurrence? */
12082                                                 p += xxreadtoken_doubles + 1;
12083                                         } else {
12084                                                 pungetc();
12085 #if ENABLE_ASH_BASH_COMPAT
12086                                                 if (c == '&' && cc == '>') /* &> */
12087                                                         break; /* return readtoken1(...) */
12088 #endif
12089                                         }
12090                                 }
12091                         }
12092                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12093                         return lasttoken;
12094                 }
12095         } /* for (;;) */
12096
12097         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12098 }
12099 #else /* old xxreadtoken */
12100 #define RETURN(token)   return lasttoken = token
12101 static int
12102 xxreadtoken(void)
12103 {
12104         int c;
12105
12106         if (tokpushback) {
12107                 tokpushback = 0;
12108                 return lasttoken;
12109         }
12110         setprompt_if(needprompt, 2);
12111         startlinno = g_parsefile->linno;
12112         for (;;) {      /* until token or start of word found */
12113                 c = pgetc();
12114                 switch (c) {
12115                 case ' ': case '\t':
12116                 IF_ASH_ALIAS(case PEOA:)
12117                         continue;
12118                 case '#':
12119                         while ((c = pgetc()) != '\n' && c != PEOF)
12120                                 continue;
12121                         pungetc();
12122                         continue;
12123                 case '\\':
12124                         if (pgetc() == '\n') {
12125                                 nlprompt();
12126                                 continue;
12127                         }
12128                         pungetc();
12129                         goto breakloop;
12130                 case '\n':
12131                         nlnoprompt();
12132                         RETURN(TNL);
12133                 case PEOF:
12134                         RETURN(TEOF);
12135                 case '&':
12136                         if (pgetc() == '&')
12137                                 RETURN(TAND);
12138                         pungetc();
12139                         RETURN(TBACKGND);
12140                 case '|':
12141                         if (pgetc() == '|')
12142                                 RETURN(TOR);
12143                         pungetc();
12144                         RETURN(TPIPE);
12145                 case ';':
12146                         if (pgetc() == ';')
12147                                 RETURN(TENDCASE);
12148                         pungetc();
12149                         RETURN(TSEMI);
12150                 case '(':
12151                         RETURN(TLP);
12152                 case ')':
12153                         RETURN(TRP);
12154                 default:
12155                         goto breakloop;
12156                 }
12157         }
12158  breakloop:
12159         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12160 #undef RETURN
12161 }
12162 #endif /* old xxreadtoken */
12163
12164 static int
12165 readtoken(void)
12166 {
12167         int t;
12168         int kwd = checkkwd;
12169 #if DEBUG
12170         smallint alreadyseen = tokpushback;
12171 #endif
12172
12173 #if ENABLE_ASH_ALIAS
12174  top:
12175 #endif
12176
12177         t = xxreadtoken();
12178
12179         /*
12180          * eat newlines
12181          */
12182         if (kwd & CHKNL) {
12183                 while (t == TNL) {
12184                         parseheredoc();
12185                         t = xxreadtoken();
12186                 }
12187         }
12188
12189         if (t != TWORD || quoteflag) {
12190                 goto out;
12191         }
12192
12193         /*
12194          * check for keywords
12195          */
12196         if (kwd & CHKKWD) {
12197                 const char *const *pp;
12198
12199                 pp = findkwd(wordtext);
12200                 if (pp) {
12201                         lasttoken = t = pp - tokname_array;
12202                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12203                         goto out;
12204                 }
12205         }
12206
12207         if (checkkwd & CHKALIAS) {
12208 #if ENABLE_ASH_ALIAS
12209                 struct alias *ap;
12210                 ap = lookupalias(wordtext, 1);
12211                 if (ap != NULL) {
12212                         if (*ap->val) {
12213                                 pushstring(ap->val, ap);
12214                         }
12215                         goto top;
12216                 }
12217 #endif
12218         }
12219  out:
12220         checkkwd = 0;
12221 #if DEBUG
12222         if (!alreadyseen)
12223                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12224         else
12225                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12226 #endif
12227         return t;
12228 }
12229
12230 static int
12231 peektoken(void)
12232 {
12233         int t;
12234
12235         t = readtoken();
12236         tokpushback = 1;
12237         return t;
12238 }
12239
12240 /*
12241  * Read and parse a command.  Returns NODE_EOF on end of file.
12242  * (NULL is a valid parse tree indicating a blank line.)
12243  */
12244 static union node *
12245 parsecmd(int interact)
12246 {
12247         tokpushback = 0;
12248         checkkwd = 0;
12249         heredoclist = 0;
12250         doprompt = interact;
12251         setprompt_if(doprompt, doprompt);
12252         needprompt = 0;
12253         return list(1);
12254 }
12255
12256 /*
12257  * Input any here documents.
12258  */
12259 static void
12260 parseheredoc(void)
12261 {
12262         struct heredoc *here;
12263         union node *n;
12264
12265         here = heredoclist;
12266         heredoclist = NULL;
12267
12268         while (here) {
12269                 setprompt_if(needprompt, 2);
12270                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12271                                 here->eofmark, here->striptabs);
12272                 n = stzalloc(sizeof(struct narg));
12273                 n->narg.type = NARG;
12274                 /*n->narg.next = NULL; - stzalloc did it */
12275                 n->narg.text = wordtext;
12276                 n->narg.backquote = backquotelist;
12277                 here->here->nhere.doc = n;
12278                 here = here->next;
12279         }
12280 }
12281
12282
12283 /*
12284  * called by editline -- any expansions to the prompt should be added here.
12285  */
12286 #if ENABLE_ASH_EXPAND_PRMT
12287 static const char *
12288 expandstr(const char *ps)
12289 {
12290         union node n;
12291         int saveprompt;
12292
12293         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12294          * and token processing _can_ alter it (delete NULs etc). */
12295         setinputstring((char *)ps);
12296
12297         saveprompt = doprompt;
12298         doprompt = 0;
12299         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12300         doprompt = saveprompt;
12301
12302         popfile();
12303
12304         n.narg.type = NARG;
12305         n.narg.next = NULL;
12306         n.narg.text = wordtext;
12307         n.narg.backquote = backquotelist;
12308
12309         expandarg(&n, NULL, EXP_QUOTED);
12310         return stackblock();
12311 }
12312 #endif
12313
12314 /*
12315  * Execute a command or commands contained in a string.
12316  */
12317 static int
12318 evalstring(char *s, int flags)
12319 {
12320         struct jmploc *volatile savehandler;
12321         struct jmploc jmploc;
12322         int ex;
12323
12324         union node *n;
12325         struct stackmark smark;
12326         int status;
12327
12328         s = sstrdup(s);
12329         setinputstring(s);
12330         setstackmark(&smark);
12331
12332         status = 0;
12333         /* On exception inside execution loop, we must popfile().
12334          * Try interactively:
12335          *      readonly a=a
12336          *      command eval "a=b"  # throws "is read only" error
12337          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12338          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12339          */
12340         savehandler = exception_handler;
12341         ex = setjmp(jmploc.loc);
12342         if (ex)
12343                 goto out;
12344         exception_handler = &jmploc;
12345
12346         while ((n = parsecmd(0)) != NODE_EOF) {
12347                 int i;
12348
12349                 i = evaltree(n, flags);
12350                 if (n)
12351                         status = i;
12352                 popstackmark(&smark);
12353                 if (evalskip)
12354                         break;
12355         }
12356  out:
12357         popstackmark(&smark);
12358         popfile();
12359         stunalloc(s);
12360
12361         exception_handler = savehandler;
12362         if (ex)
12363                 longjmp(exception_handler->loc, ex);
12364
12365         return status;
12366 }
12367
12368 /*
12369  * The eval command.
12370  */
12371 static int FAST_FUNC
12372 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12373 {
12374         char *p;
12375         char *concat;
12376
12377         if (argv[1]) {
12378                 p = argv[1];
12379                 argv += 2;
12380                 if (argv[0]) {
12381                         STARTSTACKSTR(concat);
12382                         for (;;) {
12383                                 concat = stack_putstr(p, concat);
12384                                 p = *argv++;
12385                                 if (p == NULL)
12386                                         break;
12387                                 STPUTC(' ', concat);
12388                         }
12389                         STPUTC('\0', concat);
12390                         p = grabstackstr(concat);
12391                 }
12392                 return evalstring(p, flags & EV_TESTED);
12393         }
12394         return 0;
12395 }
12396
12397 /*
12398  * Read and execute commands.
12399  * "Top" is nonzero for the top level command loop;
12400  * it turns on prompting if the shell is interactive.
12401  */
12402 static int
12403 cmdloop(int top)
12404 {
12405         union node *n;
12406         struct stackmark smark;
12407         int inter;
12408         int status = 0;
12409         int numeof = 0;
12410
12411         TRACE(("cmdloop(%d) called\n", top));
12412         for (;;) {
12413                 int skip;
12414
12415                 setstackmark(&smark);
12416 #if JOBS
12417                 if (doing_jobctl)
12418                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12419 #endif
12420                 inter = 0;
12421                 if (iflag && top) {
12422                         inter++;
12423                         chkmail();
12424                 }
12425                 n = parsecmd(inter);
12426 #if DEBUG
12427                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12428                         showtree(n);
12429 #endif
12430                 if (n == NODE_EOF) {
12431                         if (!top || numeof >= 50)
12432                                 break;
12433                         if (!stoppedjobs()) {
12434                                 if (!Iflag)
12435                                         break;
12436                                 out2str("\nUse \"exit\" to leave shell.\n");
12437                         }
12438                         numeof++;
12439                 } else if (nflag == 0) {
12440                         int i;
12441
12442                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12443                         job_warning >>= 1;
12444                         numeof = 0;
12445                         i = evaltree(n, 0);
12446                         if (n)
12447                                 status = i;
12448                 }
12449                 popstackmark(&smark);
12450                 skip = evalskip;
12451
12452                 if (skip) {
12453                         evalskip &= ~SKIPFUNC;
12454                         break;
12455                 }
12456         }
12457         return status;
12458 }
12459
12460 /*
12461  * Take commands from a file.  To be compatible we should do a path
12462  * search for the file, which is necessary to find sub-commands.
12463  */
12464 static char *
12465 find_dot_file(char *name)
12466 {
12467         char *fullname;
12468         const char *path = pathval();
12469         struct stat statb;
12470
12471         /* don't try this for absolute or relative paths */
12472         if (strchr(name, '/'))
12473                 return name;
12474
12475         /* IIRC standards do not say whether . is to be searched.
12476          * And it is even smaller this way, making it unconditional for now:
12477          */
12478         if (1) { /* ENABLE_ASH_BASH_COMPAT */
12479                 fullname = name;
12480                 goto try_cur_dir;
12481         }
12482
12483         while ((fullname = path_advance(&path, name)) != NULL) {
12484  try_cur_dir:
12485                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12486                         /*
12487                          * Don't bother freeing here, since it will
12488                          * be freed by the caller.
12489                          */
12490                         return fullname;
12491                 }
12492                 if (fullname != name)
12493                         stunalloc(fullname);
12494         }
12495
12496         /* not found in the PATH */
12497         ash_msg_and_raise_error("%s: not found", name);
12498         /* NOTREACHED */
12499 }
12500
12501 static int FAST_FUNC
12502 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12503 {
12504         /* "false; . empty_file; echo $?" should print 0, not 1: */
12505         int status = 0;
12506         char *fullname;
12507         char **argv;
12508         struct strlist *sp;
12509         volatile struct shparam saveparam;
12510
12511         for (sp = cmdenviron; sp; sp = sp->next)
12512                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12513
12514         nextopt(nullstr); /* handle possible "--" */
12515         argv = argptr;
12516
12517         if (!argv[0]) {
12518                 /* bash says: "bash: .: filename argument required" */
12519                 return 2; /* bash compat */
12520         }
12521
12522         /* This aborts if file isn't found, which is POSIXly correct.
12523          * bash returns exitcode 1 instead.
12524          */
12525         fullname = find_dot_file(argv[0]);
12526         argv++;
12527         if (argv[0]) { /* . FILE ARGS, ARGS exist */
12528                 int argc;
12529                 saveparam = shellparam;
12530                 shellparam.malloced = 0;
12531                 argc = 1;
12532                 while (argv[argc])
12533                         argc++;
12534                 shellparam.nparam = argc;
12535                 shellparam.p = argv;
12536         };
12537
12538         /* This aborts if file can't be opened, which is POSIXly correct.
12539          * bash returns exitcode 1 instead.
12540          */
12541         setinputfile(fullname, INPUT_PUSH_FILE);
12542         commandname = fullname;
12543         status = cmdloop(0);
12544         popfile();
12545
12546         if (argv[0]) {
12547                 freeparam(&shellparam);
12548                 shellparam = saveparam;
12549         };
12550
12551         return status;
12552 }
12553
12554 static int FAST_FUNC
12555 exitcmd(int argc UNUSED_PARAM, char **argv)
12556 {
12557         if (stoppedjobs())
12558                 return 0;
12559         if (argv[1])
12560                 exitstatus = number(argv[1]);
12561         raise_exception(EXEXIT);
12562         /* NOTREACHED */
12563 }
12564
12565 /*
12566  * Read a file containing shell functions.
12567  */
12568 static void
12569 readcmdfile(char *name)
12570 {
12571         setinputfile(name, INPUT_PUSH_FILE);
12572         cmdloop(0);
12573         popfile();
12574 }
12575
12576
12577 /* ============ find_command inplementation */
12578
12579 /*
12580  * Resolve a command name.  If you change this routine, you may have to
12581  * change the shellexec routine as well.
12582  */
12583 static void
12584 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12585 {
12586         struct tblentry *cmdp;
12587         int idx;
12588         int prev;
12589         char *fullname;
12590         struct stat statb;
12591         int e;
12592         int updatetbl;
12593         struct builtincmd *bcmd;
12594
12595         /* If name contains a slash, don't use PATH or hash table */
12596         if (strchr(name, '/') != NULL) {
12597                 entry->u.index = -1;
12598                 if (act & DO_ABS) {
12599                         while (stat(name, &statb) < 0) {
12600 #ifdef SYSV
12601                                 if (errno == EINTR)
12602                                         continue;
12603 #endif
12604                                 entry->cmdtype = CMDUNKNOWN;
12605                                 return;
12606                         }
12607                 }
12608                 entry->cmdtype = CMDNORMAL;
12609                 return;
12610         }
12611
12612 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12613
12614         updatetbl = (path == pathval());
12615         if (!updatetbl) {
12616                 act |= DO_ALTPATH;
12617                 if (strstr(path, "%builtin") != NULL)
12618                         act |= DO_ALTBLTIN;
12619         }
12620
12621         /* If name is in the table, check answer will be ok */
12622         cmdp = cmdlookup(name, 0);
12623         if (cmdp != NULL) {
12624                 int bit;
12625
12626                 switch (cmdp->cmdtype) {
12627                 default:
12628 #if DEBUG
12629                         abort();
12630 #endif
12631                 case CMDNORMAL:
12632                         bit = DO_ALTPATH;
12633                         break;
12634                 case CMDFUNCTION:
12635                         bit = DO_NOFUNC;
12636                         break;
12637                 case CMDBUILTIN:
12638                         bit = DO_ALTBLTIN;
12639                         break;
12640                 }
12641                 if (act & bit) {
12642                         updatetbl = 0;
12643                         cmdp = NULL;
12644                 } else if (cmdp->rehash == 0)
12645                         /* if not invalidated by cd, we're done */
12646                         goto success;
12647         }
12648
12649         /* If %builtin not in path, check for builtin next */
12650         bcmd = find_builtin(name);
12651         if (bcmd) {
12652                 if (IS_BUILTIN_REGULAR(bcmd))
12653                         goto builtin_success;
12654                 if (act & DO_ALTPATH) {
12655                         if (!(act & DO_ALTBLTIN))
12656                                 goto builtin_success;
12657                 } else if (builtinloc <= 0) {
12658                         goto builtin_success;
12659                 }
12660         }
12661
12662 #if ENABLE_FEATURE_SH_STANDALONE
12663         {
12664                 int applet_no = find_applet_by_name(name);
12665                 if (applet_no >= 0) {
12666                         entry->cmdtype = CMDNORMAL;
12667                         entry->u.index = -2 - applet_no;
12668                         return;
12669                 }
12670         }
12671 #endif
12672
12673         /* We have to search path. */
12674         prev = -1;              /* where to start */
12675         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12676                 if (cmdp->cmdtype == CMDBUILTIN)
12677                         prev = builtinloc;
12678                 else
12679                         prev = cmdp->param.index;
12680         }
12681
12682         e = ENOENT;
12683         idx = -1;
12684  loop:
12685         while ((fullname = path_advance(&path, name)) != NULL) {
12686                 stunalloc(fullname);
12687                 /* NB: code below will still use fullname
12688                  * despite it being "unallocated" */
12689                 idx++;
12690                 if (pathopt) {
12691                         if (prefix(pathopt, "builtin")) {
12692                                 if (bcmd)
12693                                         goto builtin_success;
12694                                 continue;
12695                         }
12696                         if ((act & DO_NOFUNC)
12697                          || !prefix(pathopt, "func")
12698                         ) {     /* ignore unimplemented options */
12699                                 continue;
12700                         }
12701                 }
12702                 /* if rehash, don't redo absolute path names */
12703                 if (fullname[0] == '/' && idx <= prev) {
12704                         if (idx < prev)
12705                                 continue;
12706                         TRACE(("searchexec \"%s\": no change\n", name));
12707                         goto success;
12708                 }
12709                 while (stat(fullname, &statb) < 0) {
12710 #ifdef SYSV
12711                         if (errno == EINTR)
12712                                 continue;
12713 #endif
12714                         if (errno != ENOENT && errno != ENOTDIR)
12715                                 e = errno;
12716                         goto loop;
12717                 }
12718                 e = EACCES;     /* if we fail, this will be the error */
12719                 if (!S_ISREG(statb.st_mode))
12720                         continue;
12721                 if (pathopt) {          /* this is a %func directory */
12722                         stalloc(strlen(fullname) + 1);
12723                         /* NB: stalloc will return space pointed by fullname
12724                          * (because we don't have any intervening allocations
12725                          * between stunalloc above and this stalloc) */
12726                         readcmdfile(fullname);
12727                         cmdp = cmdlookup(name, 0);
12728                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12729                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12730                         stunalloc(fullname);
12731                         goto success;
12732                 }
12733                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12734                 if (!updatetbl) {
12735                         entry->cmdtype = CMDNORMAL;
12736                         entry->u.index = idx;
12737                         return;
12738                 }
12739                 INT_OFF;
12740                 cmdp = cmdlookup(name, 1);
12741                 cmdp->cmdtype = CMDNORMAL;
12742                 cmdp->param.index = idx;
12743                 INT_ON;
12744                 goto success;
12745         }
12746
12747         /* We failed.  If there was an entry for this command, delete it */
12748         if (cmdp && updatetbl)
12749                 delete_cmd_entry();
12750         if (act & DO_ERR)
12751                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12752         entry->cmdtype = CMDUNKNOWN;
12753         return;
12754
12755  builtin_success:
12756         if (!updatetbl) {
12757                 entry->cmdtype = CMDBUILTIN;
12758                 entry->u.cmd = bcmd;
12759                 return;
12760         }
12761         INT_OFF;
12762         cmdp = cmdlookup(name, 1);
12763         cmdp->cmdtype = CMDBUILTIN;
12764         cmdp->param.cmd = bcmd;
12765         INT_ON;
12766  success:
12767         cmdp->rehash = 0;
12768         entry->cmdtype = cmdp->cmdtype;
12769         entry->u = cmdp->param;
12770 }
12771
12772
12773 /*
12774  * The trap builtin.
12775  */
12776 static int FAST_FUNC
12777 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12778 {
12779         char *action;
12780         char **ap;
12781         int signo, exitcode;
12782
12783         nextopt(nullstr);
12784         ap = argptr;
12785         if (!*ap) {
12786                 for (signo = 0; signo < NSIG; signo++) {
12787                         char *tr = trap_ptr[signo];
12788                         if (tr) {
12789                                 /* note: bash adds "SIG", but only if invoked
12790                                  * as "bash". If called as "sh", or if set -o posix,
12791                                  * then it prints short signal names.
12792                                  * We are printing short names: */
12793                                 out1fmt("trap -- %s %s\n",
12794                                                 single_quote(tr),
12795                                                 get_signame(signo));
12796                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12797                  * In this case, we will exit very soon, no need to free(). */
12798                                 /* if (trap_ptr != trap && tp[0]) */
12799                                 /*      free(tr); */
12800                         }
12801                 }
12802                 /*
12803                 if (trap_ptr != trap) {
12804                         free(trap_ptr);
12805                         trap_ptr = trap;
12806                 }
12807                 */
12808                 return 0;
12809         }
12810
12811         action = NULL;
12812         if (ap[1])
12813                 action = *ap++;
12814         exitcode = 0;
12815         while (*ap) {
12816                 signo = get_signum(*ap);
12817                 if (signo < 0) {
12818                         /* Mimic bash message exactly */
12819                         ash_msg("%s: invalid signal specification", *ap);
12820                         exitcode = 1;
12821                         goto next;
12822                 }
12823                 INT_OFF;
12824                 if (action) {
12825                         if (LONE_DASH(action))
12826                                 action = NULL;
12827                         else {
12828                                 if (action[0]) /* not NULL and not "" and not "-" */
12829                                         may_have_traps = 1;
12830                                 action = ckstrdup(action);
12831                         }
12832                 }
12833                 free(trap[signo]);
12834                 trap[signo] = action;
12835                 if (signo != 0)
12836                         setsignal(signo);
12837                 INT_ON;
12838  next:
12839                 ap++;
12840         }
12841         return exitcode;
12842 }
12843
12844
12845 /* ============ Builtins */
12846
12847 #if ENABLE_ASH_HELP
12848 static int FAST_FUNC
12849 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12850 {
12851         unsigned col;
12852         unsigned i;
12853
12854         out1fmt(
12855                 "Built-in commands:\n"
12856                 "------------------\n");
12857         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12858                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12859                                         builtintab[i].name + 1);
12860                 if (col > 60) {
12861                         out1fmt("\n");
12862                         col = 0;
12863                 }
12864         }
12865 # if ENABLE_FEATURE_SH_STANDALONE
12866         {
12867                 const char *a = applet_names;
12868                 while (*a) {
12869                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12870                         if (col > 60) {
12871                                 out1fmt("\n");
12872                                 col = 0;
12873                         }
12874                         while (*a++ != '\0')
12875                                 continue;
12876                 }
12877         }
12878 # endif
12879         newline_and_flush(stdout);
12880         return EXIT_SUCCESS;
12881 }
12882 #endif
12883
12884 #if MAX_HISTORY
12885 static int FAST_FUNC
12886 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12887 {
12888         show_history(line_input_state);
12889         return EXIT_SUCCESS;
12890 }
12891 #endif
12892
12893 /*
12894  * The export and readonly commands.
12895  */
12896 static int FAST_FUNC
12897 exportcmd(int argc UNUSED_PARAM, char **argv)
12898 {
12899         struct var *vp;
12900         char *name;
12901         const char *p;
12902         char **aptr;
12903         char opt;
12904         int flag;
12905         int flag_off;
12906
12907         /* "readonly" in bash accepts, but ignores -n.
12908          * We do the same: it saves a conditional in nextopt's param.
12909          */
12910         flag_off = 0;
12911         while ((opt = nextopt("np")) != '\0') {
12912                 if (opt == 'n')
12913                         flag_off = VEXPORT;
12914         }
12915         flag = VEXPORT;
12916         if (argv[0][0] == 'r') {
12917                 flag = VREADONLY;
12918                 flag_off = 0; /* readonly ignores -n */
12919         }
12920         flag_off = ~flag_off;
12921
12922         /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
12923         {
12924                 aptr = argptr;
12925                 name = *aptr;
12926                 if (name) {
12927                         do {
12928                                 p = strchr(name, '=');
12929                                 if (p != NULL) {
12930                                         p++;
12931                                 } else {
12932                                         vp = *findvar(hashvar(name), name);
12933                                         if (vp) {
12934                                                 vp->flags = ((vp->flags | flag) & flag_off);
12935                                                 continue;
12936                                         }
12937                                 }
12938                                 setvar(name, p, (flag & flag_off));
12939                         } while ((name = *++aptr) != NULL);
12940                         return 0;
12941                 }
12942         }
12943
12944         /* No arguments. Show the list of exported or readonly vars.
12945          * -n is ignored.
12946          */
12947         showvars(argv[0], flag, 0);
12948         return 0;
12949 }
12950
12951 /*
12952  * Delete a function if it exists.
12953  */
12954 static void
12955 unsetfunc(const char *name)
12956 {
12957         struct tblentry *cmdp;
12958
12959         cmdp = cmdlookup(name, 0);
12960         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
12961                 delete_cmd_entry();
12962 }
12963
12964 /*
12965  * The unset builtin command.  We unset the function before we unset the
12966  * variable to allow a function to be unset when there is a readonly variable
12967  * with the same name.
12968  */
12969 static int FAST_FUNC
12970 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12971 {
12972         char **ap;
12973         int i;
12974         int flag = 0;
12975         int ret = 0;
12976
12977         while ((i = nextopt("vf")) != 0) {
12978                 flag = i;
12979         }
12980
12981         for (ap = argptr; *ap; ap++) {
12982                 if (flag != 'f') {
12983                         i = unsetvar(*ap);
12984                         ret |= i;
12985                         if (!(i & 2))
12986                                 continue;
12987                 }
12988                 if (flag != 'v')
12989                         unsetfunc(*ap);
12990         }
12991         return ret & 1;
12992 }
12993
12994 static const unsigned char timescmd_str[] ALIGN1 = {
12995         ' ',  offsetof(struct tms, tms_utime),
12996         '\n', offsetof(struct tms, tms_stime),
12997         ' ',  offsetof(struct tms, tms_cutime),
12998         '\n', offsetof(struct tms, tms_cstime),
12999         0
13000 };
13001 static int FAST_FUNC
13002 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13003 {
13004         unsigned long clk_tck, s, t;
13005         const unsigned char *p;
13006         struct tms buf;
13007
13008         clk_tck = bb_clk_tck();
13009         times(&buf);
13010
13011         p = timescmd_str;
13012         do {
13013                 t = *(clock_t *)(((char *) &buf) + p[1]);
13014                 s = t / clk_tck;
13015                 t = t % clk_tck;
13016                 out1fmt("%lum%lu.%03lus%c",
13017                         s / 60, s % 60,
13018                         (t * 1000) / clk_tck,
13019                         p[0]);
13020                 p += 2;
13021         } while (*p);
13022
13023         return 0;
13024 }
13025
13026 #if ENABLE_SH_MATH_SUPPORT
13027 /*
13028  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13029  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13030  *
13031  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13032  */
13033 static int FAST_FUNC
13034 letcmd(int argc UNUSED_PARAM, char **argv)
13035 {
13036         arith_t i;
13037
13038         argv++;
13039         if (!*argv)
13040                 ash_msg_and_raise_error("expression expected");
13041         do {
13042                 i = ash_arith(*argv);
13043         } while (*++argv);
13044
13045         return !i;
13046 }
13047 #endif
13048
13049 /*
13050  * The read builtin. Options:
13051  *      -r              Do not interpret '\' specially
13052  *      -s              Turn off echo (tty only)
13053  *      -n NCHARS       Read NCHARS max
13054  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13055  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13056  *      -u FD           Read from given FD instead of fd 0
13057  * This uses unbuffered input, which may be avoidable in some cases.
13058  * TODO: bash also has:
13059  *      -a ARRAY        Read into array[0],[1],etc
13060  *      -d DELIM        End on DELIM char, not newline
13061  *      -e              Use line editing (tty only)
13062  */
13063 static int FAST_FUNC
13064 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13065 {
13066         char *opt_n = NULL;
13067         char *opt_p = NULL;
13068         char *opt_t = NULL;
13069         char *opt_u = NULL;
13070         int read_flags = 0;
13071         const char *r;
13072         int i;
13073
13074         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13075                 switch (i) {
13076                 case 'p':
13077                         opt_p = optionarg;
13078                         break;
13079                 case 'n':
13080                         opt_n = optionarg;
13081                         break;
13082                 case 's':
13083                         read_flags |= BUILTIN_READ_SILENT;
13084                         break;
13085                 case 't':
13086                         opt_t = optionarg;
13087                         break;
13088                 case 'r':
13089                         read_flags |= BUILTIN_READ_RAW;
13090                         break;
13091                 case 'u':
13092                         opt_u = optionarg;
13093                         break;
13094                 default:
13095                         break;
13096                 }
13097         }
13098
13099         /* "read -s" needs to save/restore termios, can't allow ^C
13100          * to jump out of it.
13101          */
13102         INT_OFF;
13103         r = shell_builtin_read(setvar0,
13104                 argptr,
13105                 bltinlookup("IFS"), /* can be NULL */
13106                 read_flags,
13107                 opt_n,
13108                 opt_p,
13109                 opt_t,
13110                 opt_u
13111         );
13112         INT_ON;
13113
13114         if ((uintptr_t)r > 1)
13115                 ash_msg_and_raise_error(r);
13116
13117         return (uintptr_t)r;
13118 }
13119
13120 static int FAST_FUNC
13121 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13122 {
13123         static const char permuser[3] ALIGN1 = "ogu";
13124
13125         mode_t mask;
13126         int symbolic_mode = 0;
13127
13128         while (nextopt("S") != '\0') {
13129                 symbolic_mode = 1;
13130         }
13131
13132         INT_OFF;
13133         mask = umask(0);
13134         umask(mask);
13135         INT_ON;
13136
13137         if (*argptr == NULL) {
13138                 if (symbolic_mode) {
13139                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13140                         char *p = buf;
13141                         int i;
13142
13143                         i = 2;
13144                         for (;;) {
13145                                 *p++ = ',';
13146                                 *p++ = permuser[i];
13147                                 *p++ = '=';
13148                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13149                                 if (!(mask & 0400)) *p++ = 'r';
13150                                 if (!(mask & 0200)) *p++ = 'w';
13151                                 if (!(mask & 0100)) *p++ = 'x';
13152                                 mask <<= 3;
13153                                 if (--i < 0)
13154                                         break;
13155                         }
13156                         *p = '\0';
13157                         puts(buf + 1);
13158                 } else {
13159                         out1fmt("%04o\n", mask);
13160                 }
13161         } else {
13162                 char *modestr = *argptr;
13163                 /* numeric umasks are taken as-is */
13164                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13165                 if (!isdigit(modestr[0]))
13166                         mask ^= 0777;
13167                 mask = bb_parse_mode(modestr, mask);
13168                 if ((unsigned)mask > 0777) {
13169                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13170                 }
13171                 if (!isdigit(modestr[0]))
13172                         mask ^= 0777;
13173                 umask(mask);
13174         }
13175         return 0;
13176 }
13177
13178 static int FAST_FUNC
13179 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13180 {
13181         return shell_builtin_ulimit(argv);
13182 }
13183
13184 /* ============ main() and helpers */
13185
13186 /*
13187  * Called to exit the shell.
13188  */
13189 static void
13190 exitshell(void)
13191 {
13192         struct jmploc loc;
13193         char *p;
13194         int status;
13195
13196 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13197         save_history(line_input_state);
13198 #endif
13199         status = exitstatus;
13200         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13201         if (setjmp(loc.loc)) {
13202                 if (exception_type == EXEXIT)
13203                         status = exitstatus;
13204                 goto out;
13205         }
13206         exception_handler = &loc;
13207         p = trap[0];
13208         if (p) {
13209                 trap[0] = NULL;
13210                 evalskip = 0;
13211                 evalstring(p, 0);
13212                 /*free(p); - we'll exit soon */
13213         }
13214  out:
13215         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13216          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13217          */
13218         setjobctl(0);
13219         flush_stdout_stderr();
13220         _exit(status);
13221         /* NOTREACHED */
13222 }
13223
13224 static void
13225 init(void)
13226 {
13227         /* we will never free this */
13228         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13229
13230         sigmode[SIGCHLD - 1] = S_DFL;
13231         setsignal(SIGCHLD);
13232
13233         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13234          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13235          */
13236         signal(SIGHUP, SIG_DFL);
13237
13238         {
13239                 char **envp;
13240                 const char *p;
13241                 struct stat st1, st2;
13242
13243                 initvar();
13244                 for (envp = environ; envp && *envp; envp++) {
13245                         p = endofname(*envp);
13246                         if (p != *envp && *p == '=') {
13247                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13248                         }
13249                 }
13250
13251                 setvareq((char*)defoptindvar, VTEXTFIXED);
13252
13253                 setvar0("PPID", utoa(getppid()));
13254 #if ENABLE_ASH_BASH_COMPAT
13255                 p = lookupvar("SHLVL");
13256                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13257                 if (!lookupvar("HOSTNAME")) {
13258                         struct utsname uts;
13259                         uname(&uts);
13260                         setvar0("HOSTNAME", uts.nodename);
13261                 }
13262 #endif
13263                 p = lookupvar("PWD");
13264                 if (p) {
13265                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13266                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13267                         ) {
13268                                 p = NULL;
13269                         }
13270                 }
13271                 setpwd(p, 0);
13272         }
13273 }
13274
13275
13276 //usage:#define ash_trivial_usage
13277 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13278 //usage:#define ash_full_usage "\n\n"
13279 //usage:        "Unix shell interpreter"
13280
13281 //usage:#if ENABLE_FEATURE_SH_IS_ASH
13282 //usage:# define sh_trivial_usage ash_trivial_usage
13283 //usage:# define sh_full_usage    ash_full_usage
13284 //usage:#endif
13285 //usage:#if ENABLE_FEATURE_BASH_IS_ASH
13286 //usage:# define bash_trivial_usage ash_trivial_usage
13287 //usage:# define bash_full_usage    ash_full_usage
13288 //usage:#endif
13289
13290 /*
13291  * Process the shell command line arguments.
13292  */
13293 static void
13294 procargs(char **argv)
13295 {
13296         int i;
13297         const char *xminusc;
13298         char **xargv;
13299
13300         xargv = argv;
13301         arg0 = xargv[0];
13302         /* if (xargv[0]) - mmm, this is always true! */
13303                 xargv++;
13304         for (i = 0; i < NOPTS; i++)
13305                 optlist[i] = 2;
13306         argptr = xargv;
13307         if (options(/*cmdline:*/ 1)) {
13308                 /* it already printed err message */
13309                 raise_exception(EXERROR);
13310         }
13311         xargv = argptr;
13312         xminusc = minusc;
13313         if (*xargv == NULL) {
13314                 if (xminusc)
13315                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13316                 sflag = 1;
13317         }
13318         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13319                 iflag = 1;
13320         if (mflag == 2)
13321                 mflag = iflag;
13322         for (i = 0; i < NOPTS; i++)
13323                 if (optlist[i] == 2)
13324                         optlist[i] = 0;
13325 #if DEBUG == 2
13326         debug = 1;
13327 #endif
13328         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13329         if (xminusc) {
13330                 minusc = *xargv++;
13331                 if (*xargv)
13332                         goto setarg0;
13333         } else if (!sflag) {
13334                 setinputfile(*xargv, 0);
13335  setarg0:
13336                 arg0 = *xargv++;
13337                 commandname = arg0;
13338         }
13339
13340         shellparam.p = xargv;
13341 #if ENABLE_ASH_GETOPTS
13342         shellparam.optind = 1;
13343         shellparam.optoff = -1;
13344 #endif
13345         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13346         while (*xargv) {
13347                 shellparam.nparam++;
13348                 xargv++;
13349         }
13350         optschanged();
13351 }
13352
13353 /*
13354  * Read /etc/profile, ~/.profile, $ENV.
13355  */
13356 static void
13357 read_profile(const char *name)
13358 {
13359         name = expandstr(name);
13360         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13361                 return;
13362         cmdloop(0);
13363         popfile();
13364 }
13365
13366 /*
13367  * This routine is called when an error or an interrupt occurs in an
13368  * interactive shell and control is returned to the main command loop.
13369  * (In dash, this function is auto-generated by build machinery).
13370  */
13371 static void
13372 reset(void)
13373 {
13374         /* from eval.c: */
13375         evalskip = 0;
13376         loopnest = 0;
13377
13378         /* from expand.c: */
13379         ifsfree();
13380
13381         /* from input.c: */
13382         g_parsefile->left_in_buffer = 0;
13383         g_parsefile->left_in_line = 0;      /* clear input buffer */
13384         popallfiles();
13385
13386         /* from redir.c: */
13387         while (redirlist)
13388                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13389 }
13390
13391 #if PROFILE
13392 static short profile_buf[16384];
13393 extern int etext();
13394 #endif
13395
13396 /*
13397  * Main routine.  We initialize things, parse the arguments, execute
13398  * profiles if we're a login shell, and then call cmdloop to execute
13399  * commands.  The setjmp call sets up the location to jump to when an
13400  * exception occurs.  When an exception occurs the variable "state"
13401  * is used to figure out how far we had gotten.
13402  */
13403 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13404 int ash_main(int argc UNUSED_PARAM, char **argv)
13405 {
13406         volatile smallint state;
13407         struct jmploc jmploc;
13408         struct stackmark smark;
13409
13410         /* Initialize global data */
13411         INIT_G_misc();
13412         INIT_G_memstack();
13413         INIT_G_var();
13414 #if ENABLE_ASH_ALIAS
13415         INIT_G_alias();
13416 #endif
13417         INIT_G_cmdtable();
13418
13419 #if PROFILE
13420         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13421 #endif
13422
13423 #if ENABLE_FEATURE_EDITING
13424         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13425 #endif
13426         state = 0;
13427         if (setjmp(jmploc.loc)) {
13428                 smallint e;
13429                 smallint s;
13430
13431                 reset();
13432
13433                 e = exception_type;
13434                 s = state;
13435                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13436                         exitshell();
13437                 }
13438                 if (e == EXINT) {
13439                         newline_and_flush(stderr);
13440                 }
13441
13442                 popstackmark(&smark);
13443                 FORCE_INT_ON; /* enable interrupts */
13444                 if (s == 1)
13445                         goto state1;
13446                 if (s == 2)
13447                         goto state2;
13448                 if (s == 3)
13449                         goto state3;
13450                 goto state4;
13451         }
13452         exception_handler = &jmploc;
13453         rootpid = getpid();
13454
13455         init();
13456         setstackmark(&smark);
13457         procargs(argv);
13458 #if DEBUG
13459         TRACE(("Shell args: "));
13460         trace_puts_args(argv);
13461 #endif
13462
13463         if (argv[0] && argv[0][0] == '-')
13464                 isloginsh = 1;
13465         if (isloginsh) {
13466                 const char *hp;
13467
13468                 state = 1;
13469                 read_profile("/etc/profile");
13470  state1:
13471                 state = 2;
13472                 hp = lookupvar("HOME");
13473                 if (hp)
13474                         read_profile("$HOME/.profile");
13475         }
13476  state2:
13477         state = 3;
13478         if (
13479 #ifndef linux
13480          getuid() == geteuid() && getgid() == getegid() &&
13481 #endif
13482          iflag
13483         ) {
13484                 const char *shinit = lookupvar("ENV");
13485                 if (shinit != NULL && *shinit != '\0')
13486                         read_profile(shinit);
13487         }
13488         popstackmark(&smark);
13489  state3:
13490         state = 4;
13491         if (minusc) {
13492                 /* evalstring pushes parsefile stack.
13493                  * Ensure we don't falsely claim that 0 (stdin)
13494                  * is one of stacked source fds.
13495                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13496                 // if (!sflag) g_parsefile->pf_fd = -1;
13497                 // ^^ not necessary since now we special-case fd 0
13498                 // in is_hidden_fd() to not be considered "hidden fd"
13499                 evalstring(minusc, 0);
13500         }
13501
13502         if (sflag || minusc == NULL) {
13503 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13504                 if (iflag) {
13505                         const char *hp = lookupvar("HISTFILE");
13506                         if (!hp) {
13507                                 hp = lookupvar("HOME");
13508                                 if (hp) {
13509                                         hp = concat_path_file(hp, ".ash_history");
13510                                         setvar0("HISTFILE", hp);
13511                                         free((char*)hp);
13512                                         hp = lookupvar("HISTFILE");
13513                                 }
13514                         }
13515                         if (hp)
13516                                 line_input_state->hist_file = hp;
13517 # if ENABLE_FEATURE_SH_HISTFILESIZE
13518                         hp = lookupvar("HISTFILESIZE");
13519                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13520 # endif
13521                 }
13522 #endif
13523  state4: /* XXX ??? - why isn't this before the "if" statement */
13524                 cmdloop(1);
13525         }
13526 #if PROFILE
13527         monitor(0);
13528 #endif
13529 #ifdef GPROF
13530         {
13531                 extern void _mcleanup(void);
13532                 _mcleanup();
13533         }
13534 #endif
13535         TRACE(("End of main reached\n"));
13536         exitshell();
13537         /* NOTREACHED */
13538 }
13539
13540
13541 /*-
13542  * Copyright (c) 1989, 1991, 1993, 1994
13543  *      The Regents of the University of California.  All rights reserved.
13544  *
13545  * This code is derived from software contributed to Berkeley by
13546  * Kenneth Almquist.
13547  *
13548  * Redistribution and use in source and binary forms, with or without
13549  * modification, are permitted provided that the following conditions
13550  * are met:
13551  * 1. Redistributions of source code must retain the above copyright
13552  *    notice, this list of conditions and the following disclaimer.
13553  * 2. Redistributions in binary form must reproduce the above copyright
13554  *    notice, this list of conditions and the following disclaimer in the
13555  *    documentation and/or other materials provided with the distribution.
13556  * 3. Neither the name of the University nor the names of its contributors
13557  *    may be used to endorse or promote products derived from this software
13558  *    without specific prior written permission.
13559  *
13560  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13561  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13562  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13563  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13564  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13565  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13566  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13567  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13568  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13569  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13570  * SUCH DAMAGE.
13571  */