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