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