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