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