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