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