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