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