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