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