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