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