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