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