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