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