Fix compiling with musl's utmp stubs
[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 permenantly */
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[] = {
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[] = {
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                 loc = str = stackblock() + strloc;
6327                 /* Read POS in ${var:POS:LEN} */
6328                 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6329                 len = str - startp - 1;
6330
6331                 /* *loc != '\0', guaranteed by parser */
6332                 if (quotes) {
6333                         char *ptr;
6334
6335                         /* Adjust the length by the number of escapes */
6336                         for (ptr = startp; ptr < (str - 1); ptr++) {
6337                                 if ((unsigned char)*ptr == CTLESC) {
6338                                         len--;
6339                                         ptr++;
6340                                 }
6341                         }
6342                 }
6343                 orig_len = len;
6344
6345                 if (*loc++ == ':') {
6346                         /* ${var::LEN} */
6347                         len = number(loc);
6348                 } else {
6349                         /* Skip POS in ${var:POS:LEN} */
6350                         len = orig_len;
6351                         while (*loc && *loc != ':') {
6352                                 /* TODO?
6353                                  * bash complains on: var=qwe; echo ${var:1a:123}
6354                                 if (!isdigit(*loc))
6355                                         ash_msg_and_raise_error(msg_illnum, str);
6356                                  */
6357                                 loc++;
6358                         }
6359                         if (*loc++ == ':') {
6360                                 len = number(loc);
6361                         }
6362                 }
6363                 if (pos < 0) {
6364                         /* ${VAR:$((-n)):l} starts n chars from the end */
6365                         pos = orig_len + pos;
6366                 }
6367                 if ((unsigned)pos >= orig_len) {
6368                         /* apart from obvious ${VAR:999999:l},
6369                          * covers ${VAR:$((-9999999)):l} - result is ""
6370                          * (bash-compat)
6371                          */
6372                         pos = 0;
6373                         len = 0;
6374                 }
6375                 if (len > (orig_len - pos))
6376                         len = orig_len - pos;
6377
6378                 for (str = startp; pos; str++, pos--) {
6379                         if (quotes && (unsigned char)*str == CTLESC)
6380                                 str++;
6381                 }
6382                 for (loc = startp; len; len--) {
6383                         if (quotes && (unsigned char)*str == CTLESC)
6384                                 *loc++ = *str++;
6385                         *loc++ = *str++;
6386                 }
6387                 *loc = '\0';
6388                 amount = loc - expdest;
6389                 STADJUST(amount, expdest);
6390                 return loc;
6391 #endif
6392         }
6393
6394         resetloc = expdest - (char *)stackblock();
6395
6396         /* We'll comeback here if we grow the stack while handling
6397          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6398          * stack will need rebasing, and we'll need to remove our work
6399          * areas each time
6400          */
6401  IF_ASH_BASH_COMPAT(restart:)
6402
6403         amount = expdest - ((char *)stackblock() + resetloc);
6404         STADJUST(-amount, expdest);
6405         startp = (char *)stackblock() + startloc;
6406
6407         rmesc = startp;
6408         rmescend = (char *)stackblock() + strloc;
6409         if (quotes) {
6410                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6411                 if (rmesc != startp) {
6412                         rmescend = expdest;
6413                         startp = (char *)stackblock() + startloc;
6414                 }
6415         }
6416         rmescend--;
6417         str = (char *)stackblock() + strloc;
6418         /*
6419          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6420          * The result is a_\_z_c (not a\_\_z_c)!
6421          *
6422          * The search pattern and replace string treat backslashes differently!
6423          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6424          * and string.  It's only used on the first call.
6425          */
6426         preglob(str, IF_ASH_BASH_COMPAT(
6427                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6428                         RMESCAPE_SLASH :) 0);
6429
6430 #if ENABLE_ASH_BASH_COMPAT
6431         workloc = expdest - (char *)stackblock();
6432         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6433                 char *idx, *end;
6434
6435                 if (!repl) {
6436                         if ((repl=strchr(str, CTLESC)))
6437                                 *repl++ = '\0';
6438                         else
6439                                 repl = nullstr;
6440                 }
6441                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6442
6443                 /* If there's no pattern to match, return the expansion unmolested */
6444                 if (str[0] == '\0')
6445                         return NULL;
6446
6447                 len = 0;
6448                 idx = startp;
6449                 end = str - 1;
6450                 while (idx < end) {
6451  try_to_match:
6452                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6453                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6454                         if (!loc) {
6455                                 /* No match, advance */
6456                                 char *restart_detect = stackblock();
6457  skip_matching:
6458                                 STPUTC(*idx, expdest);
6459                                 if (quotes && (unsigned char)*idx == CTLESC) {
6460                                         idx++;
6461                                         len++;
6462                                         STPUTC(*idx, expdest);
6463                                 }
6464                                 if (stackblock() != restart_detect)
6465                                         goto restart;
6466                                 idx++;
6467                                 len++;
6468                                 rmesc++;
6469                                 /* continue; - prone to quadratic behavior, smarter code: */
6470                                 if (idx >= end)
6471                                         break;
6472                                 if (str[0] == '*') {
6473                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6474                                          * it would never match "ong_string" etc, no point in trying.
6475                                          */
6476                                         goto skip_matching;
6477                                 }
6478                                 goto try_to_match;
6479                         }
6480
6481                         if (subtype == VSREPLACEALL) {
6482                                 while (idx < loc) {
6483                                         if (quotes && (unsigned char)*idx == CTLESC)
6484                                                 idx++;
6485                                         idx++;
6486                                         rmesc++;
6487                                 }
6488                         } else {
6489                                 idx = loc;
6490                         }
6491
6492                         //bb_error_msg("repl:'%s'", repl);
6493                         for (loc = (char*)repl; *loc; loc++) {
6494                                 char *restart_detect = stackblock();
6495                                 if (quotes && *loc == '\\') {
6496                                         STPUTC(CTLESC, expdest);
6497                                         len++;
6498                                 }
6499                                 STPUTC(*loc, expdest);
6500                                 if (stackblock() != restart_detect)
6501                                         goto restart;
6502                                 len++;
6503                         }
6504
6505                         if (subtype == VSREPLACE) {
6506                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6507                                 while (*idx) {
6508                                         char *restart_detect = stackblock();
6509                                         STPUTC(*idx, expdest);
6510                                         if (stackblock() != restart_detect)
6511                                                 goto restart;
6512                                         len++;
6513                                         idx++;
6514                                 }
6515                                 break;
6516                         }
6517                 }
6518
6519                 /* We've put the replaced text into a buffer at workloc, now
6520                  * move it to the right place and adjust the stack.
6521                  */
6522                 STPUTC('\0', expdest);
6523                 startp = (char *)stackblock() + startloc;
6524                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6525                 //bb_error_msg("startp:'%s'", startp);
6526                 amount = expdest - (startp + len);
6527                 STADJUST(-amount, expdest);
6528                 return startp;
6529         }
6530 #endif /* ENABLE_ASH_BASH_COMPAT */
6531
6532         subtype -= VSTRIMRIGHT;
6533 #if DEBUG
6534         if (subtype < 0 || subtype > 7)
6535                 abort();
6536 #endif
6537         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6538         zero = subtype >> 1;
6539         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6540         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6541
6542         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6543         if (loc) {
6544                 if (zero) {
6545                         memmove(startp, loc, str - loc);
6546                         loc = startp + (str - loc) - 1;
6547                 }
6548                 *loc = '\0';
6549                 amount = loc - expdest;
6550                 STADJUST(amount, expdest);
6551         }
6552         return loc;
6553 }
6554
6555 /*
6556  * Add the value of a specialized variable to the stack string.
6557  * name parameter (examples):
6558  * ash -c 'echo $1'      name:'1='
6559  * ash -c 'echo $qwe'    name:'qwe='
6560  * ash -c 'echo $$'      name:'$='
6561  * ash -c 'echo ${$}'    name:'$='
6562  * ash -c 'echo ${$##q}' name:'$=q'
6563  * ash -c 'echo ${#$}'   name:'$='
6564  * note: examples with bad shell syntax:
6565  * ash -c 'echo ${#$1}'  name:'$=1'
6566  * ash -c 'echo ${#1#}'  name:'1=#'
6567  */
6568 static NOINLINE ssize_t
6569 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6570 {
6571         const char *p;
6572         int num;
6573         int i;
6574         ssize_t len = 0;
6575         int sep;
6576         int quoted = flags & EXP_QUOTED;
6577         int subtype = varflags & VSTYPE;
6578         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6579         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6580         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
6581
6582         sep = quoted ? ((flags & EXP_FULL) << CHAR_BIT) : 0;
6583
6584         switch (*name) {
6585         case '$':
6586                 num = rootpid;
6587                 goto numvar;
6588         case '?':
6589                 num = exitstatus;
6590                 goto numvar;
6591         case '#':
6592                 num = shellparam.nparam;
6593                 goto numvar;
6594         case '!':
6595                 num = backgndpid;
6596                 if (num == 0)
6597                         return -1;
6598  numvar:
6599                 len = cvtnum(num);
6600                 goto check_1char_name;
6601         case '-':
6602                 expdest = makestrspace(NOPTS, expdest);
6603                 for (i = NOPTS - 1; i >= 0; i--) {
6604                         if (optlist[i]) {
6605                                 USTPUTC(optletters(i), expdest);
6606                                 len++;
6607                         }
6608                 }
6609  check_1char_name:
6610 #if 0
6611                 /* handles cases similar to ${#$1} */
6612                 if (name[2] != '\0')
6613                         raise_error_syntax("bad substitution");
6614 #endif
6615                 break;
6616         case '@': {
6617                 char **ap;
6618                 char sepc;
6619
6620                 if (quoted && (flags & EXP_FULL)) {
6621                         /* note: this is not meant as PEOF value */
6622                         sep = 1 << CHAR_BIT;
6623                         goto param;
6624                 }
6625                 /* fall through */
6626         case '*':
6627                 sep = ifsset() ? (unsigned char)(ifsval()[0]) : ' ';
6628  param:
6629                 ap = shellparam.p;
6630                 sepc = sep;
6631                 if (!ap)
6632                         return -1;
6633                 while ((p = *ap++) != NULL) {
6634                         len += strtodest(p, syntax, quotes);
6635
6636                         if (*ap && sep) {
6637                                 len++;
6638                                 memtodest(&sepc, 1, syntax, quotes);
6639                         }
6640                 }
6641                 break;
6642         } /* case '@' and '*' */
6643         case '0':
6644         case '1':
6645         case '2':
6646         case '3':
6647         case '4':
6648         case '5':
6649         case '6':
6650         case '7':
6651         case '8':
6652         case '9':
6653                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6654                 if (num < 0 || num > shellparam.nparam)
6655                         return -1;
6656                 p = num ? shellparam.p[num - 1] : arg0;
6657                 goto value;
6658         default:
6659                 /* NB: name has form "VAR=..." */
6660
6661                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6662                  * which should be considered before we check variables. */
6663                 if (var_str_list) {
6664                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6665                         p = NULL;
6666                         do {
6667                                 char *str, *eq;
6668                                 str = var_str_list->text;
6669                                 eq = strchr(str, '=');
6670                                 if (!eq) /* stop at first non-assignment */
6671                                         break;
6672                                 eq++;
6673                                 if (name_len == (unsigned)(eq - str)
6674                                  && strncmp(str, name, name_len) == 0
6675                                 ) {
6676                                         p = eq;
6677                                         /* goto value; - WRONG! */
6678                                         /* think "A=1 A=2 B=$A" */
6679                                 }
6680                                 var_str_list = var_str_list->next;
6681                         } while (var_str_list);
6682                         if (p)
6683                                 goto value;
6684                 }
6685                 p = lookupvar(name);
6686  value:
6687                 if (!p)
6688                         return -1;
6689
6690                 len = strtodest(p, syntax, quotes);
6691 #if ENABLE_UNICODE_SUPPORT
6692                 if (subtype == VSLENGTH && len > 0) {
6693                         reinit_unicode_for_ash();
6694                         if (unicode_status == UNICODE_ON) {
6695                                 len = unicode_strlen(p);
6696                         }
6697                 }
6698 #endif
6699                 break;
6700         }
6701
6702         if (discard)
6703                 STADJUST(-len, expdest);
6704         return len;
6705 }
6706
6707 /*
6708  * Expand a variable, and return a pointer to the next character in the
6709  * input string.
6710  */
6711 static char *
6712 evalvar(char *p, int flags, struct strlist *var_str_list)
6713 {
6714         char varflags;
6715         char subtype;
6716         int quoted;
6717         char easy;
6718         char *var;
6719         int patloc;
6720         int startloc;
6721         ssize_t varlen;
6722
6723         varflags = (unsigned char) *p++;
6724         subtype = varflags & VSTYPE;
6725         quoted = flags & EXP_QUOTED;
6726         var = p;
6727         easy = (!quoted || (*var == '@' && shellparam.nparam));
6728         startloc = expdest - (char *)stackblock();
6729         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
6730
6731  again:
6732         varlen = varvalue(var, varflags, flags, var_str_list);
6733         if (varflags & VSNUL)
6734                 varlen--;
6735
6736         if (subtype == VSPLUS) {
6737                 varlen = -1 - varlen;
6738                 goto vsplus;
6739         }
6740
6741         if (subtype == VSMINUS) {
6742  vsplus:
6743                 if (varlen < 0) {
6744                         argstr(
6745                                 p,
6746                                 flags | EXP_TILDE | EXP_WORD,
6747                                 var_str_list
6748                         );
6749                         goto end;
6750                 }
6751                 if (easy)
6752                         goto record;
6753                 goto end;
6754         }
6755
6756         if (subtype == VSASSIGN || subtype == VSQUESTION) {
6757                 if (varlen < 0) {
6758                         if (subevalvar(p, var, /* strloc: */ 0,
6759                                         subtype, startloc, varflags,
6760                                         /* quotes: */ flags & ~QUOTES_ESC,
6761                                         var_str_list)
6762                         ) {
6763                                 varflags &= ~VSNUL;
6764                                 /*
6765                                  * Remove any recorded regions beyond
6766                                  * start of variable
6767                                  */
6768                                 removerecordregions(startloc);
6769                                 goto again;
6770                         }
6771                         goto end;
6772                 }
6773                 if (easy)
6774                         goto record;
6775                 goto end;
6776         }
6777
6778         if (varlen < 0 && uflag)
6779                 varunset(p, var, 0, 0);
6780
6781         if (subtype == VSLENGTH) {
6782                 cvtnum(varlen > 0 ? varlen : 0);
6783                 goto record;
6784         }
6785
6786         if (subtype == VSNORMAL) {
6787                 if (easy)
6788                         goto record;
6789                 goto end;
6790         }
6791
6792 #if DEBUG
6793         switch (subtype) {
6794         case VSTRIMLEFT:
6795         case VSTRIMLEFTMAX:
6796         case VSTRIMRIGHT:
6797         case VSTRIMRIGHTMAX:
6798 #if ENABLE_ASH_BASH_COMPAT
6799         case VSSUBSTR:
6800         case VSREPLACE:
6801         case VSREPLACEALL:
6802 #endif
6803                 break;
6804         default:
6805                 abort();
6806         }
6807 #endif
6808
6809         if (varlen >= 0) {
6810                 /*
6811                  * Terminate the string and start recording the pattern
6812                  * right after it
6813                  */
6814                 STPUTC('\0', expdest);
6815                 patloc = expdest - (char *)stackblock();
6816                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
6817                                 startloc, varflags, flags, var_str_list)) {
6818                         int amount = expdest - (
6819                                 (char *)stackblock() + patloc - 1
6820                         );
6821                         STADJUST(-amount, expdest);
6822                 }
6823                 /* Remove any recorded regions beyond start of variable */
6824                 removerecordregions(startloc);
6825  record:
6826                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6827         }
6828
6829  end:
6830         if (subtype != VSNORMAL) {      /* skip to end of alternative */
6831                 int nesting = 1;
6832                 for (;;) {
6833                         unsigned char c = *p++;
6834                         if (c == CTLESC)
6835                                 p++;
6836                         else if (c == CTLBACKQ) {
6837                                 if (varlen >= 0)
6838                                         argbackq = argbackq->next;
6839                         } else if (c == CTLVAR) {
6840                                 if ((*p++ & VSTYPE) != VSNORMAL)
6841                                         nesting++;
6842                         } else if (c == CTLENDVAR) {
6843                                 if (--nesting == 0)
6844                                         break;
6845                         }
6846                 }
6847         }
6848         return p;
6849 }
6850
6851 /*
6852  * Break the argument string into pieces based upon IFS and add the
6853  * strings to the argument list.  The regions of the string to be
6854  * searched for IFS characters have been stored by recordregion.
6855  */
6856 static void
6857 ifsbreakup(char *string, struct arglist *arglist)
6858 {
6859         struct ifsregion *ifsp;
6860         struct strlist *sp;
6861         char *start;
6862         char *p;
6863         char *q;
6864         const char *ifs, *realifs;
6865         int ifsspc;
6866         int nulonly;
6867
6868         start = string;
6869         if (ifslastp != NULL) {
6870                 ifsspc = 0;
6871                 nulonly = 0;
6872                 realifs = ifsset() ? ifsval() : defifs;
6873                 ifsp = &ifsfirst;
6874                 do {
6875                         p = string + ifsp->begoff;
6876                         nulonly = ifsp->nulonly;
6877                         ifs = nulonly ? nullstr : realifs;
6878                         ifsspc = 0;
6879                         while (p < string + ifsp->endoff) {
6880                                 q = p;
6881                                 if ((unsigned char)*p == CTLESC)
6882                                         p++;
6883                                 if (!strchr(ifs, *p)) {
6884                                         p++;
6885                                         continue;
6886                                 }
6887                                 if (!nulonly)
6888                                         ifsspc = (strchr(defifs, *p) != NULL);
6889                                 /* Ignore IFS whitespace at start */
6890                                 if (q == start && ifsspc) {
6891                                         p++;
6892                                         start = p;
6893                                         continue;
6894                                 }
6895                                 *q = '\0';
6896                                 sp = stzalloc(sizeof(*sp));
6897                                 sp->text = start;
6898                                 *arglist->lastp = sp;
6899                                 arglist->lastp = &sp->next;
6900                                 p++;
6901                                 if (!nulonly) {
6902                                         for (;;) {
6903                                                 if (p >= string + ifsp->endoff) {
6904                                                         break;
6905                                                 }
6906                                                 q = p;
6907                                                 if ((unsigned char)*p == CTLESC)
6908                                                         p++;
6909                                                 if (strchr(ifs, *p) == NULL) {
6910                                                         p = q;
6911                                                         break;
6912                                                 }
6913                                                 if (strchr(defifs, *p) == NULL) {
6914                                                         if (ifsspc) {
6915                                                                 p++;
6916                                                                 ifsspc = 0;
6917                                                         } else {
6918                                                                 p = q;
6919                                                                 break;
6920                                                         }
6921                                                 } else
6922                                                         p++;
6923                                         }
6924                                 }
6925                                 start = p;
6926                         } /* while */
6927                         ifsp = ifsp->next;
6928                 } while (ifsp != NULL);
6929                 if (nulonly)
6930                         goto add;
6931         }
6932
6933         if (!*start)
6934                 return;
6935
6936  add:
6937         sp = stzalloc(sizeof(*sp));
6938         sp->text = start;
6939         *arglist->lastp = sp;
6940         arglist->lastp = &sp->next;
6941 }
6942
6943 static void
6944 ifsfree(void)
6945 {
6946         struct ifsregion *p;
6947
6948         INT_OFF;
6949         p = ifsfirst.next;
6950         do {
6951                 struct ifsregion *ifsp;
6952                 ifsp = p->next;
6953                 free(p);
6954                 p = ifsp;
6955         } while (p);
6956         ifslastp = NULL;
6957         ifsfirst.next = NULL;
6958         INT_ON;
6959 }
6960
6961 /*
6962  * Add a file name to the list.
6963  */
6964 static void
6965 addfname(const char *name)
6966 {
6967         struct strlist *sp;
6968
6969         sp = stzalloc(sizeof(*sp));
6970         sp->text = ststrdup(name);
6971         *exparg.lastp = sp;
6972         exparg.lastp = &sp->next;
6973 }
6974
6975 /*
6976  * Do metacharacter (i.e. *, ?, [...]) expansion.
6977  */
6978 static void
6979 expmeta(char *expdir, char *enddir, char *name)
6980 {
6981         char *p;
6982         const char *cp;
6983         char *start;
6984         char *endname;
6985         int metaflag;
6986         struct stat statb;
6987         DIR *dirp;
6988         struct dirent *dp;
6989         int atend;
6990         int matchdot;
6991         int esc;
6992
6993         metaflag = 0;
6994         start = name;
6995         for (p = name; esc = 0, *p; p += esc + 1) {
6996                 if (*p == '*' || *p == '?')
6997                         metaflag = 1;
6998                 else if (*p == '[') {
6999                         char *q = p + 1;
7000                         if (*q == '!')
7001                                 q++;
7002                         for (;;) {
7003                                 if (*q == '\\')
7004                                         q++;
7005                                 if (*q == '/' || *q == '\0')
7006                                         break;
7007                                 if (*++q == ']') {
7008                                         metaflag = 1;
7009                                         break;
7010                                 }
7011                         }
7012                 } else {
7013                         if (*p == '\\')
7014                                 esc++;
7015                         if (p[esc] == '/') {
7016                                 if (metaflag)
7017                                         break;
7018                                 start = p + esc + 1;
7019                         }
7020                 }
7021         }
7022         if (metaflag == 0) {    /* we've reached the end of the file name */
7023                 if (enddir != expdir)
7024                         metaflag++;
7025                 p = name;
7026                 do {
7027                         if (*p == '\\')
7028                                 p++;
7029                         *enddir++ = *p;
7030                 } while (*p++);
7031                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7032                         addfname(expdir);
7033                 return;
7034         }
7035         endname = p;
7036         if (name < start) {
7037                 p = name;
7038                 do {
7039                         if (*p == '\\')
7040                                 p++;
7041                         *enddir++ = *p++;
7042                 } while (p < start);
7043         }
7044         if (enddir == expdir) {
7045                 cp = ".";
7046         } else if (enddir == expdir + 1 && *expdir == '/') {
7047                 cp = "/";
7048         } else {
7049                 cp = expdir;
7050                 enddir[-1] = '\0';
7051         }
7052         dirp = opendir(cp);
7053         if (dirp == NULL)
7054                 return;
7055         if (enddir != expdir)
7056                 enddir[-1] = '/';
7057         if (*endname == 0) {
7058                 atend = 1;
7059         } else {
7060                 atend = 0;
7061                 *endname = '\0';
7062                 endname += esc + 1;
7063         }
7064         matchdot = 0;
7065         p = start;
7066         if (*p == '\\')
7067                 p++;
7068         if (*p == '.')
7069                 matchdot++;
7070         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7071                 if (dp->d_name[0] == '.' && !matchdot)
7072                         continue;
7073                 if (pmatch(start, dp->d_name)) {
7074                         if (atend) {
7075                                 strcpy(enddir, dp->d_name);
7076                                 addfname(expdir);
7077                         } else {
7078                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7079                                         continue;
7080                                 p[-1] = '/';
7081                                 expmeta(expdir, p, endname);
7082                         }
7083                 }
7084         }
7085         closedir(dirp);
7086         if (!atend)
7087                 endname[-esc - 1] = esc ? '\\' : '/';
7088 }
7089
7090 static struct strlist *
7091 msort(struct strlist *list, int len)
7092 {
7093         struct strlist *p, *q = NULL;
7094         struct strlist **lpp;
7095         int half;
7096         int n;
7097
7098         if (len <= 1)
7099                 return list;
7100         half = len >> 1;
7101         p = list;
7102         for (n = half; --n >= 0;) {
7103                 q = p;
7104                 p = p->next;
7105         }
7106         q->next = NULL;                 /* terminate first half of list */
7107         q = msort(list, half);          /* sort first half of list */
7108         p = msort(p, len - half);               /* sort second half */
7109         lpp = &list;
7110         for (;;) {
7111 #if ENABLE_LOCALE_SUPPORT
7112                 if (strcoll(p->text, q->text) < 0)
7113 #else
7114                 if (strcmp(p->text, q->text) < 0)
7115 #endif
7116                                                 {
7117                         *lpp = p;
7118                         lpp = &p->next;
7119                         p = *lpp;
7120                         if (p == NULL) {
7121                                 *lpp = q;
7122                                 break;
7123                         }
7124                 } else {
7125                         *lpp = q;
7126                         lpp = &q->next;
7127                         q = *lpp;
7128                         if (q == NULL) {
7129                                 *lpp = p;
7130                                 break;
7131                         }
7132                 }
7133         }
7134         return list;
7135 }
7136
7137 /*
7138  * Sort the results of file name expansion.  It calculates the number of
7139  * strings to sort and then calls msort (short for merge sort) to do the
7140  * work.
7141  */
7142 static struct strlist *
7143 expsort(struct strlist *str)
7144 {
7145         int len;
7146         struct strlist *sp;
7147
7148         len = 0;
7149         for (sp = str; sp; sp = sp->next)
7150                 len++;
7151         return msort(str, len);
7152 }
7153
7154 static void
7155 expandmeta(struct strlist *str /*, int flag*/)
7156 {
7157         static const char metachars[] ALIGN1 = {
7158                 '*', '?', '[', 0
7159         };
7160         /* TODO - EXP_REDIR */
7161
7162         while (str) {
7163                 char *expdir;
7164                 struct strlist **savelastp;
7165                 struct strlist *sp;
7166                 char *p;
7167
7168                 if (fflag)
7169                         goto nometa;
7170                 if (!strpbrk(str->text, metachars))
7171                         goto nometa;
7172                 savelastp = exparg.lastp;
7173
7174                 INT_OFF;
7175                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7176                 {
7177                         int i = strlen(str->text);
7178                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
7179                 }
7180                 expmeta(expdir, expdir, p);
7181                 free(expdir);
7182                 if (p != str->text)
7183                         free(p);
7184                 INT_ON;
7185                 if (exparg.lastp == savelastp) {
7186                         /*
7187                          * no matches
7188                          */
7189  nometa:
7190                         *exparg.lastp = str;
7191                         rmescapes(str->text, 0);
7192                         exparg.lastp = &str->next;
7193                 } else {
7194                         *exparg.lastp = NULL;
7195                         *savelastp = sp = expsort(*savelastp);
7196                         while (sp->next != NULL)
7197                                 sp = sp->next;
7198                         exparg.lastp = &sp->next;
7199                 }
7200                 str = str->next;
7201         }
7202 }
7203
7204 /*
7205  * Perform variable substitution and command substitution on an argument,
7206  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7207  * perform splitting and file name expansion.  When arglist is NULL, perform
7208  * here document expansion.
7209  */
7210 static void
7211 expandarg(union node *arg, struct arglist *arglist, int flag)
7212 {
7213         struct strlist *sp;
7214         char *p;
7215
7216         argbackq = arg->narg.backquote;
7217         STARTSTACKSTR(expdest);
7218         ifsfirst.next = NULL;
7219         ifslastp = NULL;
7220         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7221         argstr(arg->narg.text, flag,
7222                         /* var_str_list: */ arglist ? arglist->list : NULL);
7223         p = _STPUTC('\0', expdest);
7224         expdest = p - 1;
7225         if (arglist == NULL) {
7226                 return;                 /* here document expanded */
7227         }
7228         p = grabstackstr(p);
7229         TRACE(("expandarg: p:'%s'\n", p));
7230         exparg.lastp = &exparg.list;
7231         /*
7232          * TODO - EXP_REDIR
7233          */
7234         if (flag & EXP_FULL) {
7235                 ifsbreakup(p, &exparg);
7236                 *exparg.lastp = NULL;
7237                 exparg.lastp = &exparg.list;
7238                 expandmeta(exparg.list /*, flag*/);
7239         } else {
7240                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7241                         rmescapes(p, 0);
7242                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7243                 }
7244                 sp = stzalloc(sizeof(*sp));
7245                 sp->text = p;
7246                 *exparg.lastp = sp;
7247                 exparg.lastp = &sp->next;
7248         }
7249         if (ifsfirst.next)
7250                 ifsfree();
7251         *exparg.lastp = NULL;
7252         if (exparg.list) {
7253                 *arglist->lastp = exparg.list;
7254                 arglist->lastp = exparg.lastp;
7255         }
7256 }
7257
7258 /*
7259  * Expand shell variables and backquotes inside a here document.
7260  */
7261 static void
7262 expandhere(union node *arg, int fd)
7263 {
7264         herefd = fd;
7265         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7266         full_write(fd, stackblock(), expdest - (char *)stackblock());
7267 }
7268
7269 /*
7270  * Returns true if the pattern matches the string.
7271  */
7272 static int
7273 patmatch(char *pattern, const char *string)
7274 {
7275         return pmatch(preglob(pattern, 0), string);
7276 }
7277
7278 /*
7279  * See if a pattern matches in a case statement.
7280  */
7281 static int
7282 casematch(union node *pattern, char *val)
7283 {
7284         struct stackmark smark;
7285         int result;
7286
7287         setstackmark(&smark);
7288         argbackq = pattern->narg.backquote;
7289         STARTSTACKSTR(expdest);
7290         ifslastp = NULL;
7291         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7292                         /* var_str_list: */ NULL);
7293         STACKSTRNUL(expdest);
7294         result = patmatch(stackblock(), val);
7295         popstackmark(&smark);
7296         return result;
7297 }
7298
7299
7300 /* ============ find_command */
7301
7302 struct builtincmd {
7303         const char *name;
7304         int (*builtin)(int, char **) FAST_FUNC;
7305         /* unsigned flags; */
7306 };
7307 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7308 /* "regular" builtins always take precedence over commands,
7309  * regardless of PATH=....%builtin... position */
7310 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7311 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7312
7313 struct cmdentry {
7314         smallint cmdtype;       /* CMDxxx */
7315         union param {
7316                 int index;
7317                 /* index >= 0 for commands without path (slashes) */
7318                 /* (TODO: what exactly does the value mean? PATH position?) */
7319                 /* index == -1 for commands with slashes */
7320                 /* index == (-2 - applet_no) for NOFORK applets */
7321                 const struct builtincmd *cmd;
7322                 struct funcnode *func;
7323         } u;
7324 };
7325 /* values of cmdtype */
7326 #define CMDUNKNOWN      -1      /* no entry in table for command */
7327 #define CMDNORMAL       0       /* command is an executable program */
7328 #define CMDFUNCTION     1       /* command is a shell function */
7329 #define CMDBUILTIN      2       /* command is a shell builtin */
7330
7331 /* action to find_command() */
7332 #define DO_ERR          0x01    /* prints errors */
7333 #define DO_ABS          0x02    /* checks absolute paths */
7334 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7335 #define DO_ALTPATH      0x08    /* using alternate path */
7336 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7337
7338 static void find_command(char *, struct cmdentry *, int, const char *);
7339
7340
7341 /* ============ Hashing commands */
7342
7343 /*
7344  * When commands are first encountered, they are entered in a hash table.
7345  * This ensures that a full path search will not have to be done for them
7346  * on each invocation.
7347  *
7348  * We should investigate converting to a linear search, even though that
7349  * would make the command name "hash" a misnomer.
7350  */
7351
7352 struct tblentry {
7353         struct tblentry *next;  /* next entry in hash chain */
7354         union param param;      /* definition of builtin function */
7355         smallint cmdtype;       /* CMDxxx */
7356         char rehash;            /* if set, cd done since entry created */
7357         char cmdname[1];        /* name of command */
7358 };
7359
7360 static struct tblentry **cmdtable;
7361 #define INIT_G_cmdtable() do { \
7362         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7363 } while (0)
7364
7365 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7366
7367
7368 static void
7369 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7370 {
7371 #if ENABLE_FEATURE_SH_STANDALONE
7372         if (applet_no >= 0) {
7373                 if (APPLET_IS_NOEXEC(applet_no)) {
7374                         clearenv();
7375                         while (*envp)
7376                                 putenv(*envp++);
7377                         run_applet_no_and_exit(applet_no, argv);
7378                 }
7379                 /* re-exec ourselves with the new arguments */
7380                 execve(bb_busybox_exec_path, argv, envp);
7381                 /* If they called chroot or otherwise made the binary no longer
7382                  * executable, fall through */
7383         }
7384 #endif
7385
7386  repeat:
7387 #ifdef SYSV
7388         do {
7389                 execve(cmd, argv, envp);
7390         } while (errno == EINTR);
7391 #else
7392         execve(cmd, argv, envp);
7393 #endif
7394         if (cmd == (char*) bb_busybox_exec_path) {
7395                 /* We already visited ENOEXEC branch below, don't do it again */
7396 //TODO: try execve(initial_argv0_of_shell, argv, envp) before giving up?
7397                 free(argv);
7398                 return;
7399         }
7400         if (errno == ENOEXEC) {
7401                 /* Run "cmd" as a shell script:
7402                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7403                  * "If the execve() function fails with ENOEXEC, the shell
7404                  * shall execute a command equivalent to having a shell invoked
7405                  * with the command name as its first operand,
7406                  * with any remaining arguments passed to the new shell"
7407                  *
7408                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7409                  * just call ourselves.
7410                  *
7411                  * Note that bash reads ~80 chars of the file, and if it sees
7412                  * a zero byte before it sees newline, it doesn't try to
7413                  * interpret it, but fails with "cannot execute binary file"
7414                  * message and exit code 126. For one, this prevents attempts
7415                  * to interpret foreign ELF binaries as shell scripts.
7416                  */
7417                 char **ap;
7418                 char **new;
7419
7420                 for (ap = argv; *ap; ap++)
7421                         continue;
7422                 new = ckmalloc((ap - argv + 2) * sizeof(new[0]));
7423                 new[0] = (char*) "ash";
7424                 new[1] = cmd;
7425                 ap = new + 2;
7426                 while ((*ap++ = *++argv) != NULL)
7427                         continue;
7428                 cmd = (char*) bb_busybox_exec_path;
7429                 argv = new;
7430                 goto repeat;
7431         }
7432 }
7433
7434 /*
7435  * Exec a program.  Never returns.  If you change this routine, you may
7436  * have to change the find_command routine as well.
7437  */
7438 static void shellexec(char **, const char *, int) NORETURN;
7439 static void
7440 shellexec(char **argv, const char *path, int idx)
7441 {
7442         char *cmdname;
7443         int e;
7444         char **envp;
7445         int exerrno;
7446         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7447
7448         clearredir(/*drop:*/ 1);
7449         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7450         if (strchr(argv[0], '/') != NULL
7451 #if ENABLE_FEATURE_SH_STANDALONE
7452          || (applet_no = find_applet_by_name(argv[0])) >= 0
7453 #endif
7454         ) {
7455                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7456                 if (applet_no >= 0) {
7457                         /* We tried execing ourself, but it didn't work.
7458                          * Maybe /proc/self/exe doesn't exist?
7459                          * Try $PATH search.
7460                          */
7461                         goto try_PATH;
7462                 }
7463                 e = errno;
7464         } else {
7465  try_PATH:
7466                 e = ENOENT;
7467                 while ((cmdname = path_advance(&path, argv[0])) != NULL) {
7468                         if (--idx < 0 && pathopt == NULL) {
7469                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7470                                 if (errno != ENOENT && errno != ENOTDIR)
7471                                         e = errno;
7472                         }
7473                         stunalloc(cmdname);
7474                 }
7475         }
7476
7477         /* Map to POSIX errors */
7478         switch (e) {
7479         case EACCES:
7480                 exerrno = 126;
7481                 break;
7482         case ENOENT:
7483                 exerrno = 127;
7484                 break;
7485         default:
7486                 exerrno = 2;
7487                 break;
7488         }
7489         exitstatus = exerrno;
7490         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7491                 argv[0], e, suppress_int));
7492         ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7493         /* NOTREACHED */
7494 }
7495
7496 static void
7497 printentry(struct tblentry *cmdp)
7498 {
7499         int idx;
7500         const char *path;
7501         char *name;
7502
7503         idx = cmdp->param.index;
7504         path = pathval();
7505         do {
7506                 name = path_advance(&path, cmdp->cmdname);
7507                 stunalloc(name);
7508         } while (--idx >= 0);
7509         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7510 }
7511
7512 /*
7513  * Clear out command entries.  The argument specifies the first entry in
7514  * PATH which has changed.
7515  */
7516 static void
7517 clearcmdentry(int firstchange)
7518 {
7519         struct tblentry **tblp;
7520         struct tblentry **pp;
7521         struct tblentry *cmdp;
7522
7523         INT_OFF;
7524         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7525                 pp = tblp;
7526                 while ((cmdp = *pp) != NULL) {
7527                         if ((cmdp->cmdtype == CMDNORMAL &&
7528                              cmdp->param.index >= firstchange)
7529                          || (cmdp->cmdtype == CMDBUILTIN &&
7530                              builtinloc >= firstchange)
7531                         ) {
7532                                 *pp = cmdp->next;
7533                                 free(cmdp);
7534                         } else {
7535                                 pp = &cmdp->next;
7536                         }
7537                 }
7538         }
7539         INT_ON;
7540 }
7541
7542 /*
7543  * Locate a command in the command hash table.  If "add" is nonzero,
7544  * add the command to the table if it is not already present.  The
7545  * variable "lastcmdentry" is set to point to the address of the link
7546  * pointing to the entry, so that delete_cmd_entry can delete the
7547  * entry.
7548  *
7549  * Interrupts must be off if called with add != 0.
7550  */
7551 static struct tblentry **lastcmdentry;
7552
7553 static struct tblentry *
7554 cmdlookup(const char *name, int add)
7555 {
7556         unsigned int hashval;
7557         const char *p;
7558         struct tblentry *cmdp;
7559         struct tblentry **pp;
7560
7561         p = name;
7562         hashval = (unsigned char)*p << 4;
7563         while (*p)
7564                 hashval += (unsigned char)*p++;
7565         hashval &= 0x7FFF;
7566         pp = &cmdtable[hashval % CMDTABLESIZE];
7567         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7568                 if (strcmp(cmdp->cmdname, name) == 0)
7569                         break;
7570                 pp = &cmdp->next;
7571         }
7572         if (add && cmdp == NULL) {
7573                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7574                                 + strlen(name)
7575                                 /* + 1 - already done because
7576                                  * tblentry::cmdname is char[1] */);
7577                 /*cmdp->next = NULL; - ckzalloc did it */
7578                 cmdp->cmdtype = CMDUNKNOWN;
7579                 strcpy(cmdp->cmdname, name);
7580         }
7581         lastcmdentry = pp;
7582         return cmdp;
7583 }
7584
7585 /*
7586  * Delete the command entry returned on the last lookup.
7587  */
7588 static void
7589 delete_cmd_entry(void)
7590 {
7591         struct tblentry *cmdp;
7592
7593         INT_OFF;
7594         cmdp = *lastcmdentry;
7595         *lastcmdentry = cmdp->next;
7596         if (cmdp->cmdtype == CMDFUNCTION)
7597                 freefunc(cmdp->param.func);
7598         free(cmdp);
7599         INT_ON;
7600 }
7601
7602 /*
7603  * Add a new command entry, replacing any existing command entry for
7604  * the same name - except special builtins.
7605  */
7606 static void
7607 addcmdentry(char *name, struct cmdentry *entry)
7608 {
7609         struct tblentry *cmdp;
7610
7611         cmdp = cmdlookup(name, 1);
7612         if (cmdp->cmdtype == CMDFUNCTION) {
7613                 freefunc(cmdp->param.func);
7614         }
7615         cmdp->cmdtype = entry->cmdtype;
7616         cmdp->param = entry->u;
7617         cmdp->rehash = 0;
7618 }
7619
7620 static int FAST_FUNC
7621 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7622 {
7623         struct tblentry **pp;
7624         struct tblentry *cmdp;
7625         int c;
7626         struct cmdentry entry;
7627         char *name;
7628
7629         if (nextopt("r") != '\0') {
7630                 clearcmdentry(0);
7631                 return 0;
7632         }
7633
7634         if (*argptr == NULL) {
7635                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7636                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7637                                 if (cmdp->cmdtype == CMDNORMAL)
7638                                         printentry(cmdp);
7639                         }
7640                 }
7641                 return 0;
7642         }
7643
7644         c = 0;
7645         while ((name = *argptr) != NULL) {
7646                 cmdp = cmdlookup(name, 0);
7647                 if (cmdp != NULL
7648                  && (cmdp->cmdtype == CMDNORMAL
7649                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7650                 ) {
7651                         delete_cmd_entry();
7652                 }
7653                 find_command(name, &entry, DO_ERR, pathval());
7654                 if (entry.cmdtype == CMDUNKNOWN)
7655                         c = 1;
7656                 argptr++;
7657         }
7658         return c;
7659 }
7660
7661 /*
7662  * Called when a cd is done.  Marks all commands so the next time they
7663  * are executed they will be rehashed.
7664  */
7665 static void
7666 hashcd(void)
7667 {
7668         struct tblentry **pp;
7669         struct tblentry *cmdp;
7670
7671         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7672                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7673                         if (cmdp->cmdtype == CMDNORMAL
7674                          || (cmdp->cmdtype == CMDBUILTIN
7675                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7676                              && builtinloc > 0)
7677                         ) {
7678                                 cmdp->rehash = 1;
7679                         }
7680                 }
7681         }
7682 }
7683
7684 /*
7685  * Fix command hash table when PATH changed.
7686  * Called before PATH is changed.  The argument is the new value of PATH;
7687  * pathval() still returns the old value at this point.
7688  * Called with interrupts off.
7689  */
7690 static void FAST_FUNC
7691 changepath(const char *new)
7692 {
7693         const char *old;
7694         int firstchange;
7695         int idx;
7696         int idx_bltin;
7697
7698         old = pathval();
7699         firstchange = 9999;     /* assume no change */
7700         idx = 0;
7701         idx_bltin = -1;
7702         for (;;) {
7703                 if (*old != *new) {
7704                         firstchange = idx;
7705                         if ((*old == '\0' && *new == ':')
7706                          || (*old == ':' && *new == '\0')
7707                         ) {
7708                                 firstchange++;
7709                         }
7710                         old = new;      /* ignore subsequent differences */
7711                 }
7712                 if (*new == '\0')
7713                         break;
7714                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7715                         idx_bltin = idx;
7716                 if (*new == ':')
7717                         idx++;
7718                 new++;
7719                 old++;
7720         }
7721         if (builtinloc < 0 && idx_bltin >= 0)
7722                 builtinloc = idx_bltin;             /* zap builtins */
7723         if (builtinloc >= 0 && idx_bltin < 0)
7724                 firstchange = 0;
7725         clearcmdentry(firstchange);
7726         builtinloc = idx_bltin;
7727 }
7728 enum {
7729         TEOF,
7730         TNL,
7731         TREDIR,
7732         TWORD,
7733         TSEMI,
7734         TBACKGND,
7735         TAND,
7736         TOR,
7737         TPIPE,
7738         TLP,
7739         TRP,
7740         TENDCASE,
7741         TENDBQUOTE,
7742         TNOT,
7743         TCASE,
7744         TDO,
7745         TDONE,
7746         TELIF,
7747         TELSE,
7748         TESAC,
7749         TFI,
7750         TFOR,
7751 #if ENABLE_ASH_BASH_COMPAT
7752         TFUNCTION,
7753 #endif
7754         TIF,
7755         TIN,
7756         TTHEN,
7757         TUNTIL,
7758         TWHILE,
7759         TBEGIN,
7760         TEND
7761 };
7762 typedef smallint token_id_t;
7763
7764 /* first char is indicating which tokens mark the end of a list */
7765 static const char *const tokname_array[] = {
7766         "\1end of file",
7767         "\0newline",
7768         "\0redirection",
7769         "\0word",
7770         "\0;",
7771         "\0&",
7772         "\0&&",
7773         "\0||",
7774         "\0|",
7775         "\0(",
7776         "\1)",
7777         "\1;;",
7778         "\1`",
7779 #define KWDOFFSET 13
7780         /* the following are keywords */
7781         "\0!",
7782         "\0case",
7783         "\1do",
7784         "\1done",
7785         "\1elif",
7786         "\1else",
7787         "\1esac",
7788         "\1fi",
7789         "\0for",
7790 #if ENABLE_ASH_BASH_COMPAT
7791         "\0function",
7792 #endif
7793         "\0if",
7794         "\0in",
7795         "\1then",
7796         "\0until",
7797         "\0while",
7798         "\0{",
7799         "\1}",
7800 };
7801
7802 /* Wrapper around strcmp for qsort/bsearch/... */
7803 static int
7804 pstrcmp(const void *a, const void *b)
7805 {
7806         return strcmp((char*) a, (*(char**) b) + 1);
7807 }
7808
7809 static const char *const *
7810 findkwd(const char *s)
7811 {
7812         return bsearch(s, tokname_array + KWDOFFSET,
7813                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
7814                         sizeof(tokname_array[0]), pstrcmp);
7815 }
7816
7817 /*
7818  * Locate and print what a word is...
7819  */
7820 static int
7821 describe_command(char *command, const char *path, int describe_command_verbose)
7822 {
7823         struct cmdentry entry;
7824         struct tblentry *cmdp;
7825 #if ENABLE_ASH_ALIAS
7826         const struct alias *ap;
7827 #endif
7828
7829         path = path ? path : pathval();
7830
7831         if (describe_command_verbose) {
7832                 out1str(command);
7833         }
7834
7835         /* First look at the keywords */
7836         if (findkwd(command)) {
7837                 out1str(describe_command_verbose ? " is a shell keyword" : command);
7838                 goto out;
7839         }
7840
7841 #if ENABLE_ASH_ALIAS
7842         /* Then look at the aliases */
7843         ap = lookupalias(command, 0);
7844         if (ap != NULL) {
7845                 if (!describe_command_verbose) {
7846                         out1str("alias ");
7847                         printalias(ap);
7848                         return 0;
7849                 }
7850                 out1fmt(" is an alias for %s", ap->val);
7851                 goto out;
7852         }
7853 #endif
7854         /* Then check if it is a tracked alias */
7855         cmdp = cmdlookup(command, 0);
7856         if (cmdp != NULL) {
7857                 entry.cmdtype = cmdp->cmdtype;
7858                 entry.u = cmdp->param;
7859         } else {
7860                 /* Finally use brute force */
7861                 find_command(command, &entry, DO_ABS, path);
7862         }
7863
7864         switch (entry.cmdtype) {
7865         case CMDNORMAL: {
7866                 int j = entry.u.index;
7867                 char *p;
7868                 if (j < 0) {
7869                         p = command;
7870                 } else {
7871                         do {
7872                                 p = path_advance(&path, command);
7873                                 stunalloc(p);
7874                         } while (--j >= 0);
7875                 }
7876                 if (describe_command_verbose) {
7877                         out1fmt(" is%s %s",
7878                                 (cmdp ? " a tracked alias for" : nullstr), p
7879                         );
7880                 } else {
7881                         out1str(p);
7882                 }
7883                 break;
7884         }
7885
7886         case CMDFUNCTION:
7887                 if (describe_command_verbose) {
7888                         out1str(" is a shell function");
7889                 } else {
7890                         out1str(command);
7891                 }
7892                 break;
7893
7894         case CMDBUILTIN:
7895                 if (describe_command_verbose) {
7896                         out1fmt(" is a %sshell builtin",
7897                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7898                                         "special " : nullstr
7899                         );
7900                 } else {
7901                         out1str(command);
7902                 }
7903                 break;
7904
7905         default:
7906                 if (describe_command_verbose) {
7907                         out1str(": not found\n");
7908                 }
7909                 return 127;
7910         }
7911  out:
7912         out1str("\n");
7913         return 0;
7914 }
7915
7916 static int FAST_FUNC
7917 typecmd(int argc UNUSED_PARAM, char **argv)
7918 {
7919         int i = 1;
7920         int err = 0;
7921         int verbose = 1;
7922
7923         /* type -p ... ? (we don't bother checking for 'p') */
7924         if (argv[1] && argv[1][0] == '-') {
7925                 i++;
7926                 verbose = 0;
7927         }
7928         while (argv[i]) {
7929                 err |= describe_command(argv[i++], NULL, verbose);
7930         }
7931         return err;
7932 }
7933
7934 #if ENABLE_ASH_CMDCMD
7935 static int FAST_FUNC
7936 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7937 {
7938         int c;
7939         enum {
7940                 VERIFY_BRIEF = 1,
7941                 VERIFY_VERBOSE = 2,
7942         } verify = 0;
7943         const char *path = NULL;
7944
7945         while ((c = nextopt("pvV")) != '\0')
7946                 if (c == 'V')
7947                         verify |= VERIFY_VERBOSE;
7948                 else if (c == 'v')
7949                         verify |= VERIFY_BRIEF;
7950 #if DEBUG
7951                 else if (c != 'p')
7952                         abort();
7953 #endif
7954                 else
7955                         path = bb_default_path;
7956         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7957         if (verify && (*argptr != NULL)) {
7958                 return describe_command(*argptr, path, verify - VERIFY_BRIEF);
7959         }
7960
7961         return 0;
7962 }
7963 #endif
7964
7965
7966 /* ============ eval.c */
7967
7968 static int funcblocksize;       /* size of structures in function */
7969 static int funcstringsize;      /* size of strings in node */
7970 static void *funcblock;         /* block to allocate function from */
7971 static char *funcstring;        /* block to allocate strings from */
7972
7973 /* flags in argument to evaltree */
7974 #define EV_EXIT    01           /* exit after evaluating tree */
7975 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
7976 #define EV_BACKCMD 04           /* command executing within back quotes */
7977
7978 static const uint8_t nodesize[N_NUMBER] = {
7979         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
7980         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
7981         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
7982         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7983         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7984         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
7985         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
7986         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
7987         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
7988         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
7989         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
7990         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
7991         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
7992         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
7993         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
7994         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
7995         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
7996 #if ENABLE_ASH_BASH_COMPAT
7997         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
7998 #endif
7999         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8000         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8001         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8002         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8003         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8004         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8005         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8006         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8007         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8008 };
8009
8010 static void calcsize(union node *n);
8011
8012 static void
8013 sizenodelist(struct nodelist *lp)
8014 {
8015         while (lp) {
8016                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8017                 calcsize(lp->n);
8018                 lp = lp->next;
8019         }
8020 }
8021
8022 static void
8023 calcsize(union node *n)
8024 {
8025         if (n == NULL)
8026                 return;
8027         funcblocksize += nodesize[n->type];
8028         switch (n->type) {
8029         case NCMD:
8030                 calcsize(n->ncmd.redirect);
8031                 calcsize(n->ncmd.args);
8032                 calcsize(n->ncmd.assign);
8033                 break;
8034         case NPIPE:
8035                 sizenodelist(n->npipe.cmdlist);
8036                 break;
8037         case NREDIR:
8038         case NBACKGND:
8039         case NSUBSHELL:
8040                 calcsize(n->nredir.redirect);
8041                 calcsize(n->nredir.n);
8042                 break;
8043         case NAND:
8044         case NOR:
8045         case NSEMI:
8046         case NWHILE:
8047         case NUNTIL:
8048                 calcsize(n->nbinary.ch2);
8049                 calcsize(n->nbinary.ch1);
8050                 break;
8051         case NIF:
8052                 calcsize(n->nif.elsepart);
8053                 calcsize(n->nif.ifpart);
8054                 calcsize(n->nif.test);
8055                 break;
8056         case NFOR:
8057                 funcstringsize += strlen(n->nfor.var) + 1;
8058                 calcsize(n->nfor.body);
8059                 calcsize(n->nfor.args);
8060                 break;
8061         case NCASE:
8062                 calcsize(n->ncase.cases);
8063                 calcsize(n->ncase.expr);
8064                 break;
8065         case NCLIST:
8066                 calcsize(n->nclist.body);
8067                 calcsize(n->nclist.pattern);
8068                 calcsize(n->nclist.next);
8069                 break;
8070         case NDEFUN:
8071         case NARG:
8072                 sizenodelist(n->narg.backquote);
8073                 funcstringsize += strlen(n->narg.text) + 1;
8074                 calcsize(n->narg.next);
8075                 break;
8076         case NTO:
8077 #if ENABLE_ASH_BASH_COMPAT
8078         case NTO2:
8079 #endif
8080         case NCLOBBER:
8081         case NFROM:
8082         case NFROMTO:
8083         case NAPPEND:
8084                 calcsize(n->nfile.fname);
8085                 calcsize(n->nfile.next);
8086                 break;
8087         case NTOFD:
8088         case NFROMFD:
8089                 calcsize(n->ndup.vname);
8090                 calcsize(n->ndup.next);
8091         break;
8092         case NHERE:
8093         case NXHERE:
8094                 calcsize(n->nhere.doc);
8095                 calcsize(n->nhere.next);
8096                 break;
8097         case NNOT:
8098                 calcsize(n->nnot.com);
8099                 break;
8100         };
8101 }
8102
8103 static char *
8104 nodeckstrdup(char *s)
8105 {
8106         char *rtn = funcstring;
8107
8108         strcpy(funcstring, s);
8109         funcstring += strlen(s) + 1;
8110         return rtn;
8111 }
8112
8113 static union node *copynode(union node *);
8114
8115 static struct nodelist *
8116 copynodelist(struct nodelist *lp)
8117 {
8118         struct nodelist *start;
8119         struct nodelist **lpp;
8120
8121         lpp = &start;
8122         while (lp) {
8123                 *lpp = funcblock;
8124                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8125                 (*lpp)->n = copynode(lp->n);
8126                 lp = lp->next;
8127                 lpp = &(*lpp)->next;
8128         }
8129         *lpp = NULL;
8130         return start;
8131 }
8132
8133 static union node *
8134 copynode(union node *n)
8135 {
8136         union node *new;
8137
8138         if (n == NULL)
8139                 return NULL;
8140         new = funcblock;
8141         funcblock = (char *) funcblock + nodesize[n->type];
8142
8143         switch (n->type) {
8144         case NCMD:
8145                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8146                 new->ncmd.args = copynode(n->ncmd.args);
8147                 new->ncmd.assign = copynode(n->ncmd.assign);
8148                 break;
8149         case NPIPE:
8150                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8151                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8152                 break;
8153         case NREDIR:
8154         case NBACKGND:
8155         case NSUBSHELL:
8156                 new->nredir.redirect = copynode(n->nredir.redirect);
8157                 new->nredir.n = copynode(n->nredir.n);
8158                 break;
8159         case NAND:
8160         case NOR:
8161         case NSEMI:
8162         case NWHILE:
8163         case NUNTIL:
8164                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8165                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8166                 break;
8167         case NIF:
8168                 new->nif.elsepart = copynode(n->nif.elsepart);
8169                 new->nif.ifpart = copynode(n->nif.ifpart);
8170                 new->nif.test = copynode(n->nif.test);
8171                 break;
8172         case NFOR:
8173                 new->nfor.var = nodeckstrdup(n->nfor.var);
8174                 new->nfor.body = copynode(n->nfor.body);
8175                 new->nfor.args = copynode(n->nfor.args);
8176                 break;
8177         case NCASE:
8178                 new->ncase.cases = copynode(n->ncase.cases);
8179                 new->ncase.expr = copynode(n->ncase.expr);
8180                 break;
8181         case NCLIST:
8182                 new->nclist.body = copynode(n->nclist.body);
8183                 new->nclist.pattern = copynode(n->nclist.pattern);
8184                 new->nclist.next = copynode(n->nclist.next);
8185                 break;
8186         case NDEFUN:
8187         case NARG:
8188                 new->narg.backquote = copynodelist(n->narg.backquote);
8189                 new->narg.text = nodeckstrdup(n->narg.text);
8190                 new->narg.next = copynode(n->narg.next);
8191                 break;
8192         case NTO:
8193 #if ENABLE_ASH_BASH_COMPAT
8194         case NTO2:
8195 #endif
8196         case NCLOBBER:
8197         case NFROM:
8198         case NFROMTO:
8199         case NAPPEND:
8200                 new->nfile.fname = copynode(n->nfile.fname);
8201                 new->nfile.fd = n->nfile.fd;
8202                 new->nfile.next = copynode(n->nfile.next);
8203                 break;
8204         case NTOFD:
8205         case NFROMFD:
8206                 new->ndup.vname = copynode(n->ndup.vname);
8207                 new->ndup.dupfd = n->ndup.dupfd;
8208                 new->ndup.fd = n->ndup.fd;
8209                 new->ndup.next = copynode(n->ndup.next);
8210                 break;
8211         case NHERE:
8212         case NXHERE:
8213                 new->nhere.doc = copynode(n->nhere.doc);
8214                 new->nhere.fd = n->nhere.fd;
8215                 new->nhere.next = copynode(n->nhere.next);
8216                 break;
8217         case NNOT:
8218                 new->nnot.com = copynode(n->nnot.com);
8219                 break;
8220         };
8221         new->type = n->type;
8222         return new;
8223 }
8224
8225 /*
8226  * Make a copy of a parse tree.
8227  */
8228 static struct funcnode *
8229 copyfunc(union node *n)
8230 {
8231         struct funcnode *f;
8232         size_t blocksize;
8233
8234         funcblocksize = offsetof(struct funcnode, n);
8235         funcstringsize = 0;
8236         calcsize(n);
8237         blocksize = funcblocksize;
8238         f = ckmalloc(blocksize + funcstringsize);
8239         funcblock = (char *) f + offsetof(struct funcnode, n);
8240         funcstring = (char *) f + blocksize;
8241         copynode(n);
8242         f->count = 0;
8243         return f;
8244 }
8245
8246 /*
8247  * Define a shell function.
8248  */
8249 static void
8250 defun(char *name, union node *func)
8251 {
8252         struct cmdentry entry;
8253
8254         INT_OFF;
8255         entry.cmdtype = CMDFUNCTION;
8256         entry.u.func = copyfunc(func);
8257         addcmdentry(name, &entry);
8258         INT_ON;
8259 }
8260
8261 /* Reasons for skipping commands (see comment on breakcmd routine) */
8262 #define SKIPBREAK      (1 << 0)
8263 #define SKIPCONT       (1 << 1)
8264 #define SKIPFUNC       (1 << 2)
8265 #define SKIPFILE       (1 << 3)
8266 #define SKIPEVAL       (1 << 4)
8267 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8268 static int skipcount;           /* number of levels to skip */
8269 static int funcnest;            /* depth of function calls */
8270 static int loopnest;            /* current loop nesting level */
8271
8272 /* Forward decl way out to parsing code - dotrap needs it */
8273 static int evalstring(char *s, int mask);
8274
8275 /* Called to execute a trap.
8276  * Single callsite - at the end of evaltree().
8277  * If we return non-zero, evaltree raises EXEXIT exception.
8278  *
8279  * Perhaps we should avoid entering new trap handlers
8280  * while we are executing a trap handler. [is it a TODO?]
8281  */
8282 static int
8283 dotrap(void)
8284 {
8285         uint8_t *g;
8286         int sig;
8287         uint8_t savestatus;
8288
8289         savestatus = exitstatus;
8290         pending_sig = 0;
8291         xbarrier();
8292
8293         TRACE(("dotrap entered\n"));
8294         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8295                 int want_exexit;
8296                 char *t;
8297
8298                 if (*g == 0)
8299                         continue;
8300                 t = trap[sig];
8301                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8302                  * don't upset it by resetting gotsig[SIGINT-1] */
8303                 if (sig == SIGINT && !t)
8304                         continue;
8305
8306                 TRACE(("sig %d is active, will run handler '%s'\n", sig, t));
8307                 *g = 0;
8308                 if (!t)
8309                         continue;
8310                 want_exexit = evalstring(t, SKIPEVAL);
8311                 exitstatus = savestatus;
8312                 if (want_exexit) {
8313                         TRACE(("dotrap returns %d\n", want_exexit));
8314                         return want_exexit;
8315                 }
8316         }
8317
8318         TRACE(("dotrap returns 0\n"));
8319         return 0;
8320 }
8321
8322 /* forward declarations - evaluation is fairly recursive business... */
8323 static void evalloop(union node *, int);
8324 static void evalfor(union node *, int);
8325 static void evalcase(union node *, int);
8326 static void evalsubshell(union node *, int);
8327 static void expredir(union node *);
8328 static void evalpipe(union node *, int);
8329 static void evalcommand(union node *, int);
8330 static int evalbltin(const struct builtincmd *, int, char **);
8331 static void prehash(union node *);
8332
8333 /*
8334  * Evaluate a parse tree.  The value is left in the global variable
8335  * exitstatus.
8336  */
8337 static void
8338 evaltree(union node *n, int flags)
8339 {
8340         struct jmploc *volatile savehandler = exception_handler;
8341         struct jmploc jmploc;
8342         int checkexit = 0;
8343         void (*evalfn)(union node *, int);
8344         int status;
8345         int int_level;
8346
8347         SAVE_INT(int_level);
8348
8349         if (n == NULL) {
8350                 TRACE(("evaltree(NULL) called\n"));
8351                 goto out1;
8352         }
8353         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8354
8355         exception_handler = &jmploc;
8356         {
8357                 int err = setjmp(jmploc.loc);
8358                 if (err) {
8359                         /* if it was a signal, check for trap handlers */
8360                         if (exception_type == EXSIG) {
8361                                 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8362                                                 exception_type, err));
8363                                 goto out;
8364                         }
8365                         /* continue on the way out */
8366                         TRACE(("exception %d in evaltree, propagating err=%d\n",
8367                                         exception_type, err));
8368                         exception_handler = savehandler;
8369                         longjmp(exception_handler->loc, err);
8370                 }
8371         }
8372
8373         switch (n->type) {
8374         default:
8375 #if DEBUG
8376                 out1fmt("Node type = %d\n", n->type);
8377                 fflush_all();
8378                 break;
8379 #endif
8380         case NNOT:
8381                 evaltree(n->nnot.com, EV_TESTED);
8382                 status = !exitstatus;
8383                 goto setstatus;
8384         case NREDIR:
8385                 expredir(n->nredir.redirect);
8386                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8387                 if (!status) {
8388                         evaltree(n->nredir.n, flags & EV_TESTED);
8389                         status = exitstatus;
8390                 }
8391                 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8392                 goto setstatus;
8393         case NCMD:
8394                 evalfn = evalcommand;
8395  checkexit:
8396                 if (eflag && !(flags & EV_TESTED))
8397                         checkexit = ~0;
8398                 goto calleval;
8399         case NFOR:
8400                 evalfn = evalfor;
8401                 goto calleval;
8402         case NWHILE:
8403         case NUNTIL:
8404                 evalfn = evalloop;
8405                 goto calleval;
8406         case NSUBSHELL:
8407         case NBACKGND:
8408                 evalfn = evalsubshell;
8409                 goto calleval;
8410         case NPIPE:
8411                 evalfn = evalpipe;
8412                 goto checkexit;
8413         case NCASE:
8414                 evalfn = evalcase;
8415                 goto calleval;
8416         case NAND:
8417         case NOR:
8418         case NSEMI: {
8419
8420 #if NAND + 1 != NOR
8421 #error NAND + 1 != NOR
8422 #endif
8423 #if NOR + 1 != NSEMI
8424 #error NOR + 1 != NSEMI
8425 #endif
8426                 unsigned is_or = n->type - NAND;
8427                 evaltree(
8428                         n->nbinary.ch1,
8429                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8430                 );
8431                 if ((!exitstatus) == is_or)
8432                         break;
8433                 if (!evalskip) {
8434                         n = n->nbinary.ch2;
8435  evaln:
8436                         evalfn = evaltree;
8437  calleval:
8438                         evalfn(n, flags);
8439                         break;
8440                 }
8441                 break;
8442         }
8443         case NIF:
8444                 evaltree(n->nif.test, EV_TESTED);
8445                 if (evalskip)
8446                         break;
8447                 if (exitstatus == 0) {
8448                         n = n->nif.ifpart;
8449                         goto evaln;
8450                 }
8451                 if (n->nif.elsepart) {
8452                         n = n->nif.elsepart;
8453                         goto evaln;
8454                 }
8455                 goto success;
8456         case NDEFUN:
8457                 defun(n->narg.text, n->narg.next);
8458  success:
8459                 status = 0;
8460  setstatus:
8461                 exitstatus = status;
8462                 break;
8463         }
8464
8465  out:
8466         exception_handler = savehandler;
8467
8468  out1:
8469         /* Order of checks below is important:
8470          * signal handlers trigger before exit caused by "set -e".
8471          */
8472         if (pending_sig && dotrap())
8473                 goto exexit;
8474         if (checkexit & exitstatus)
8475                 evalskip |= SKIPEVAL;
8476
8477         if (flags & EV_EXIT) {
8478  exexit:
8479                 raise_exception(EXEXIT);
8480         }
8481
8482         RESTORE_INT(int_level);
8483         TRACE(("leaving evaltree (no interrupts)\n"));
8484 }
8485
8486 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8487 static
8488 #endif
8489 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8490
8491 static void
8492 evalloop(union node *n, int flags)
8493 {
8494         int status;
8495
8496         loopnest++;
8497         status = 0;
8498         flags &= EV_TESTED;
8499         for (;;) {
8500                 int i;
8501
8502                 evaltree(n->nbinary.ch1, EV_TESTED);
8503                 if (evalskip) {
8504  skipping:
8505                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8506                                 evalskip = 0;
8507                                 continue;
8508                         }
8509                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8510                                 evalskip = 0;
8511                         break;
8512                 }
8513                 i = exitstatus;
8514                 if (n->type != NWHILE)
8515                         i = !i;
8516                 if (i != 0)
8517                         break;
8518                 evaltree(n->nbinary.ch2, flags);
8519                 status = exitstatus;
8520                 if (evalskip)
8521                         goto skipping;
8522         }
8523         loopnest--;
8524         exitstatus = status;
8525 }
8526
8527 static void
8528 evalfor(union node *n, int flags)
8529 {
8530         struct arglist arglist;
8531         union node *argp;
8532         struct strlist *sp;
8533         struct stackmark smark;
8534
8535         setstackmark(&smark);
8536         arglist.list = NULL;
8537         arglist.lastp = &arglist.list;
8538         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8539                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8540                 /* XXX */
8541                 if (evalskip)
8542                         goto out;
8543         }
8544         *arglist.lastp = NULL;
8545
8546         exitstatus = 0;
8547         loopnest++;
8548         flags &= EV_TESTED;
8549         for (sp = arglist.list; sp; sp = sp->next) {
8550                 setvar0(n->nfor.var, sp->text);
8551                 evaltree(n->nfor.body, flags);
8552                 if (evalskip) {
8553                         if (evalskip == SKIPCONT && --skipcount <= 0) {
8554                                 evalskip = 0;
8555                                 continue;
8556                         }
8557                         if (evalskip == SKIPBREAK && --skipcount <= 0)
8558                                 evalskip = 0;
8559                         break;
8560                 }
8561         }
8562         loopnest--;
8563  out:
8564         popstackmark(&smark);
8565 }
8566
8567 static void
8568 evalcase(union node *n, int flags)
8569 {
8570         union node *cp;
8571         union node *patp;
8572         struct arglist arglist;
8573         struct stackmark smark;
8574
8575         setstackmark(&smark);
8576         arglist.list = NULL;
8577         arglist.lastp = &arglist.list;
8578         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8579         exitstatus = 0;
8580         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8581                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8582                         if (casematch(patp, arglist.list->text)) {
8583                                 if (evalskip == 0) {
8584                                         evaltree(cp->nclist.body, flags);
8585                                 }
8586                                 goto out;
8587                         }
8588                 }
8589         }
8590  out:
8591         popstackmark(&smark);
8592 }
8593
8594 /*
8595  * Kick off a subshell to evaluate a tree.
8596  */
8597 static void
8598 evalsubshell(union node *n, int flags)
8599 {
8600         struct job *jp;
8601         int backgnd = (n->type == NBACKGND);
8602         int status;
8603
8604         expredir(n->nredir.redirect);
8605         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8606                 goto nofork;
8607         INT_OFF;
8608         jp = makejob(/*n,*/ 1);
8609         if (forkshell(jp, n, backgnd) == 0) {
8610                 /* child */
8611                 INT_ON;
8612                 flags |= EV_EXIT;
8613                 if (backgnd)
8614                         flags &= ~EV_TESTED;
8615  nofork:
8616                 redirect(n->nredir.redirect, 0);
8617                 evaltreenr(n->nredir.n, flags);
8618                 /* never returns */
8619         }
8620         status = 0;
8621         if (!backgnd)
8622                 status = waitforjob(jp);
8623         exitstatus = status;
8624         INT_ON;
8625 }
8626
8627 /*
8628  * Compute the names of the files in a redirection list.
8629  */
8630 static void fixredir(union node *, const char *, int);
8631 static void
8632 expredir(union node *n)
8633 {
8634         union node *redir;
8635
8636         for (redir = n; redir; redir = redir->nfile.next) {
8637                 struct arglist fn;
8638
8639                 fn.list = NULL;
8640                 fn.lastp = &fn.list;
8641                 switch (redir->type) {
8642                 case NFROMTO:
8643                 case NFROM:
8644                 case NTO:
8645 #if ENABLE_ASH_BASH_COMPAT
8646                 case NTO2:
8647 #endif
8648                 case NCLOBBER:
8649                 case NAPPEND:
8650                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8651                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
8652 #if ENABLE_ASH_BASH_COMPAT
8653  store_expfname:
8654 #endif
8655 #if 0
8656 // By the design of stack allocator, the loop of this kind:
8657 //      while true; do while true; do break; done </dev/null; done
8658 // will look like a memory leak: ash plans to free expfname's
8659 // of "/dev/null" as soon as it finishes running the loop
8660 // (in this case, never).
8661 // This "fix" is wrong:
8662                         if (redir->nfile.expfname)
8663                                 stunalloc(redir->nfile.expfname);
8664 // It results in corrupted state of stacked allocations.
8665 #endif
8666                         redir->nfile.expfname = fn.list->text;
8667                         break;
8668                 case NFROMFD:
8669                 case NTOFD: /* >& */
8670                         if (redir->ndup.vname) {
8671                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8672                                 if (fn.list == NULL)
8673                                         ash_msg_and_raise_error("redir error");
8674 #if ENABLE_ASH_BASH_COMPAT
8675 //FIXME: we used expandarg with different args!
8676                                 if (!isdigit_str9(fn.list->text)) {
8677                                         /* >&file, not >&fd */
8678                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
8679                                                 ash_msg_and_raise_error("redir error");
8680                                         redir->type = NTO2;
8681                                         goto store_expfname;
8682                                 }
8683 #endif
8684                                 fixredir(redir, fn.list->text, 1);
8685                         }
8686                         break;
8687                 }
8688         }
8689 }
8690
8691 /*
8692  * Evaluate a pipeline.  All the processes in the pipeline are children
8693  * of the process creating the pipeline.  (This differs from some versions
8694  * of the shell, which make the last process in a pipeline the parent
8695  * of all the rest.)
8696  */
8697 static void
8698 evalpipe(union node *n, int flags)
8699 {
8700         struct job *jp;
8701         struct nodelist *lp;
8702         int pipelen;
8703         int prevfd;
8704         int pip[2];
8705
8706         TRACE(("evalpipe(0x%lx) called\n", (long)n));
8707         pipelen = 0;
8708         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8709                 pipelen++;
8710         flags |= EV_EXIT;
8711         INT_OFF;
8712         jp = makejob(/*n,*/ pipelen);
8713         prevfd = -1;
8714         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8715                 prehash(lp->n);
8716                 pip[1] = -1;
8717                 if (lp->next) {
8718                         if (pipe(pip) < 0) {
8719                                 close(prevfd);
8720                                 ash_msg_and_raise_error("pipe call failed");
8721                         }
8722                 }
8723                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8724                         INT_ON;
8725                         if (pip[1] >= 0) {
8726                                 close(pip[0]);
8727                         }
8728                         if (prevfd > 0) {
8729                                 dup2(prevfd, 0);
8730                                 close(prevfd);
8731                         }
8732                         if (pip[1] > 1) {
8733                                 dup2(pip[1], 1);
8734                                 close(pip[1]);
8735                         }
8736                         evaltreenr(lp->n, flags);
8737                         /* never returns */
8738                 }
8739                 if (prevfd >= 0)
8740                         close(prevfd);
8741                 prevfd = pip[0];
8742                 /* Don't want to trigger debugging */
8743                 if (pip[1] != -1)
8744                         close(pip[1]);
8745         }
8746         if (n->npipe.pipe_backgnd == 0) {
8747                 exitstatus = waitforjob(jp);
8748                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
8749         }
8750         INT_ON;
8751 }
8752
8753 /*
8754  * Controls whether the shell is interactive or not.
8755  */
8756 static void
8757 setinteractive(int on)
8758 {
8759         static smallint is_interactive;
8760
8761         if (++on == is_interactive)
8762                 return;
8763         is_interactive = on;
8764         setsignal(SIGINT);
8765         setsignal(SIGQUIT);
8766         setsignal(SIGTERM);
8767 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8768         if (is_interactive > 1) {
8769                 /* Looks like they want an interactive shell */
8770                 static smallint did_banner;
8771
8772                 if (!did_banner) {
8773                         /* note: ash and hush share this string */
8774                         out1fmt("\n\n%s %s\n"
8775                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
8776                                 "\n",
8777                                 bb_banner,
8778                                 "built-in shell (ash)"
8779                         );
8780                         did_banner = 1;
8781                 }
8782         }
8783 #endif
8784 }
8785
8786 static void
8787 optschanged(void)
8788 {
8789 #if DEBUG
8790         opentrace();
8791 #endif
8792         setinteractive(iflag);
8793         setjobctl(mflag);
8794 #if ENABLE_FEATURE_EDITING_VI
8795         if (viflag)
8796                 line_input_state->flags |= VI_MODE;
8797         else
8798                 line_input_state->flags &= ~VI_MODE;
8799 #else
8800         viflag = 0; /* forcibly keep the option off */
8801 #endif
8802 }
8803
8804 static struct localvar *localvars;
8805
8806 /*
8807  * Called after a function returns.
8808  * Interrupts must be off.
8809  */
8810 static void
8811 poplocalvars(void)
8812 {
8813         struct localvar *lvp;
8814         struct var *vp;
8815
8816         while ((lvp = localvars) != NULL) {
8817                 localvars = lvp->next;
8818                 vp = lvp->vp;
8819                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
8820                 if (vp == NULL) {       /* $- saved */
8821                         memcpy(optlist, lvp->text, sizeof(optlist));
8822                         free((char*)lvp->text);
8823                         optschanged();
8824                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8825                         unsetvar(vp->var_text);
8826                 } else {
8827                         if (vp->var_func)
8828                                 vp->var_func(var_end(lvp->text));
8829                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8830                                 free((char*)vp->var_text);
8831                         vp->flags = lvp->flags;
8832                         vp->var_text = lvp->text;
8833                 }
8834                 free(lvp);
8835         }
8836 }
8837
8838 static int
8839 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8840 {
8841         volatile struct shparam saveparam;
8842         struct localvar *volatile savelocalvars;
8843         struct jmploc *volatile savehandler;
8844         struct jmploc jmploc;
8845         int e;
8846
8847         saveparam = shellparam;
8848         savelocalvars = localvars;
8849         e = setjmp(jmploc.loc);
8850         if (e) {
8851                 goto funcdone;
8852         }
8853         INT_OFF;
8854         savehandler = exception_handler;
8855         exception_handler = &jmploc;
8856         localvars = NULL;
8857         shellparam.malloced = 0;
8858         func->count++;
8859         funcnest++;
8860         INT_ON;
8861         shellparam.nparam = argc - 1;
8862         shellparam.p = argv + 1;
8863 #if ENABLE_ASH_GETOPTS
8864         shellparam.optind = 1;
8865         shellparam.optoff = -1;
8866 #endif
8867         evaltree(&func->n, flags & EV_TESTED);
8868  funcdone:
8869         INT_OFF;
8870         funcnest--;
8871         freefunc(func);
8872         poplocalvars();
8873         localvars = savelocalvars;
8874         freeparam(&shellparam);
8875         shellparam = saveparam;
8876         exception_handler = savehandler;
8877         INT_ON;
8878         evalskip &= ~SKIPFUNC;
8879         return e;
8880 }
8881
8882 #if ENABLE_ASH_CMDCMD
8883 static char **
8884 parse_command_args(char **argv, const char **path)
8885 {
8886         char *cp, c;
8887
8888         for (;;) {
8889                 cp = *++argv;
8890                 if (!cp)
8891                         return NULL;
8892                 if (*cp++ != '-')
8893                         break;
8894                 c = *cp++;
8895                 if (!c)
8896                         break;
8897                 if (c == '-' && !*cp) {
8898                         if (!*++argv)
8899                                 return NULL;
8900                         break;
8901                 }
8902                 do {
8903                         switch (c) {
8904                         case 'p':
8905                                 *path = bb_default_path;
8906                                 break;
8907                         default:
8908                                 /* run 'typecmd' for other options */
8909                                 return NULL;
8910                         }
8911                         c = *cp++;
8912                 } while (c);
8913         }
8914         return argv;
8915 }
8916 #endif
8917
8918 /*
8919  * Make a variable a local variable.  When a variable is made local, it's
8920  * value and flags are saved in a localvar structure.  The saved values
8921  * will be restored when the shell function returns.  We handle the name
8922  * "-" as a special case: it makes changes to "set +-options" local
8923  * (options will be restored on return from the function).
8924  */
8925 static void
8926 mklocal(char *name)
8927 {
8928         struct localvar *lvp;
8929         struct var **vpp;
8930         struct var *vp;
8931         char *eq = strchr(name, '=');
8932
8933         INT_OFF;
8934         /* Cater for duplicate "local". Examples:
8935          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
8936          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
8937          */
8938         lvp = localvars;
8939         while (lvp) {
8940                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
8941                         if (eq)
8942                                 setvareq(name, 0);
8943                         /* else:
8944                          * it's a duplicate "local VAR" declaration, do nothing
8945                          */
8946                         return;
8947                 }
8948                 lvp = lvp->next;
8949         }
8950
8951         lvp = ckzalloc(sizeof(*lvp));
8952         if (LONE_DASH(name)) {
8953                 char *p;
8954                 p = ckmalloc(sizeof(optlist));
8955                 lvp->text = memcpy(p, optlist, sizeof(optlist));
8956                 vp = NULL;
8957         } else {
8958                 vpp = hashvar(name);
8959                 vp = *findvar(vpp, name);
8960                 if (vp == NULL) {
8961                         /* variable did not exist yet */
8962                         if (eq)
8963                                 setvareq(name, VSTRFIXED);
8964                         else
8965                                 setvar(name, NULL, VSTRFIXED);
8966                         vp = *vpp;      /* the new variable */
8967                         lvp->flags = VUNSET;
8968                 } else {
8969                         lvp->text = vp->var_text;
8970                         lvp->flags = vp->flags;
8971                         /* make sure neither "struct var" nor string gets freed
8972                          * during (un)setting:
8973                          */
8974                         vp->flags |= VSTRFIXED|VTEXTFIXED;
8975                         if (eq)
8976                                 setvareq(name, 0);
8977                         else
8978                                 /* "local VAR" unsets VAR: */
8979                                 setvar0(name, NULL);
8980                 }
8981         }
8982         lvp->vp = vp;
8983         lvp->next = localvars;
8984         localvars = lvp;
8985         INT_ON;
8986 }
8987
8988 /*
8989  * The "local" command.
8990  */
8991 static int FAST_FUNC
8992 localcmd(int argc UNUSED_PARAM, char **argv)
8993 {
8994         char *name;
8995
8996         if (!funcnest)
8997                 ash_msg_and_raise_error("not in a function");
8998
8999         argv = argptr;
9000         while ((name = *argv++) != NULL) {
9001                 mklocal(name);
9002         }
9003         return 0;
9004 }
9005
9006 static int FAST_FUNC
9007 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9008 {
9009         return 1;
9010 }
9011
9012 static int FAST_FUNC
9013 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9014 {
9015         return 0;
9016 }
9017
9018 static int FAST_FUNC
9019 execcmd(int argc UNUSED_PARAM, char **argv)
9020 {
9021         if (argv[1]) {
9022                 iflag = 0;              /* exit on error */
9023                 mflag = 0;
9024                 optschanged();
9025                 shellexec(argv + 1, pathval(), 0);
9026         }
9027         return 0;
9028 }
9029
9030 /*
9031  * The return command.
9032  */
9033 static int FAST_FUNC
9034 returncmd(int argc UNUSED_PARAM, char **argv)
9035 {
9036         /*
9037          * If called outside a function, do what ksh does;
9038          * skip the rest of the file.
9039          */
9040         evalskip = funcnest ? SKIPFUNC : SKIPFILE;
9041         return argv[1] ? number(argv[1]) : exitstatus;
9042 }
9043
9044 /* Forward declarations for builtintab[] */
9045 static int breakcmd(int, char **) FAST_FUNC;
9046 static int dotcmd(int, char **) FAST_FUNC;
9047 static int evalcmd(int, char **) FAST_FUNC;
9048 static int exitcmd(int, char **) FAST_FUNC;
9049 static int exportcmd(int, char **) FAST_FUNC;
9050 #if ENABLE_ASH_GETOPTS
9051 static int getoptscmd(int, char **) FAST_FUNC;
9052 #endif
9053 #if ENABLE_ASH_HELP
9054 static int helpcmd(int, char **) FAST_FUNC;
9055 #endif
9056 #if MAX_HISTORY
9057 static int historycmd(int, char **) FAST_FUNC;
9058 #endif
9059 #if ENABLE_SH_MATH_SUPPORT
9060 static int letcmd(int, char **) FAST_FUNC;
9061 #endif
9062 static int readcmd(int, char **) FAST_FUNC;
9063 static int setcmd(int, char **) FAST_FUNC;
9064 static int shiftcmd(int, char **) FAST_FUNC;
9065 static int timescmd(int, char **) FAST_FUNC;
9066 static int trapcmd(int, char **) FAST_FUNC;
9067 static int umaskcmd(int, char **) FAST_FUNC;
9068 static int unsetcmd(int, char **) FAST_FUNC;
9069 static int ulimitcmd(int, char **) FAST_FUNC;
9070
9071 #define BUILTIN_NOSPEC          "0"
9072 #define BUILTIN_SPECIAL         "1"
9073 #define BUILTIN_REGULAR         "2"
9074 #define BUILTIN_SPEC_REG        "3"
9075 #define BUILTIN_ASSIGN          "4"
9076 #define BUILTIN_SPEC_ASSG       "5"
9077 #define BUILTIN_REG_ASSG        "6"
9078 #define BUILTIN_SPEC_REG_ASSG   "7"
9079
9080 /* Stubs for calling non-FAST_FUNC's */
9081 #if ENABLE_ASH_BUILTIN_ECHO
9082 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9083 #endif
9084 #if ENABLE_ASH_BUILTIN_PRINTF
9085 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9086 #endif
9087 #if ENABLE_ASH_BUILTIN_TEST
9088 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9089 #endif
9090
9091 /* Keep these in proper order since it is searched via bsearch() */
9092 static const struct builtincmd builtintab[] = {
9093         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9094         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9095 #if ENABLE_ASH_BUILTIN_TEST
9096         { BUILTIN_REGULAR       "["       , testcmd    },
9097 #if ENABLE_ASH_BASH_COMPAT
9098         { BUILTIN_REGULAR       "[["      , testcmd    },
9099 #endif
9100 #endif
9101 #if ENABLE_ASH_ALIAS
9102         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9103 #endif
9104 #if JOBS
9105         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9106 #endif
9107         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9108         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9109         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9110 #if ENABLE_ASH_CMDCMD
9111         { BUILTIN_REGULAR       "command" , commandcmd },
9112 #endif
9113         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9114 #if ENABLE_ASH_BUILTIN_ECHO
9115         { BUILTIN_REGULAR       "echo"    , echocmd    },
9116 #endif
9117         { BUILTIN_SPEC_REG      "eval"    , evalcmd    },
9118         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9119         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9120         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9121         { BUILTIN_REGULAR       "false"   , falsecmd   },
9122 #if JOBS
9123         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9124 #endif
9125 #if ENABLE_ASH_GETOPTS
9126         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9127 #endif
9128         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9129 #if ENABLE_ASH_HELP
9130         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9131 #endif
9132 #if MAX_HISTORY
9133         { BUILTIN_NOSPEC        "history" , historycmd },
9134 #endif
9135 #if JOBS
9136         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9137         { BUILTIN_REGULAR       "kill"    , killcmd    },
9138 #endif
9139 #if ENABLE_SH_MATH_SUPPORT
9140         { BUILTIN_NOSPEC        "let"     , letcmd     },
9141 #endif
9142         { BUILTIN_ASSIGN        "local"   , localcmd   },
9143 #if ENABLE_ASH_BUILTIN_PRINTF
9144         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9145 #endif
9146         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9147         { BUILTIN_REGULAR       "read"    , readcmd    },
9148         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9149         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9150         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9151         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9152 #if ENABLE_ASH_BASH_COMPAT
9153         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9154 #endif
9155 #if ENABLE_ASH_BUILTIN_TEST
9156         { BUILTIN_REGULAR       "test"    , testcmd    },
9157 #endif
9158         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9159         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9160         { BUILTIN_REGULAR       "true"    , truecmd    },
9161         { BUILTIN_NOSPEC        "type"    , typecmd    },
9162         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9163         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9164 #if ENABLE_ASH_ALIAS
9165         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9166 #endif
9167         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9168         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9169 };
9170
9171 /* Should match the above table! */
9172 #define COMMANDCMD (builtintab + \
9173         2 + \
9174         1 * ENABLE_ASH_BUILTIN_TEST + \
9175         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
9176         1 * ENABLE_ASH_ALIAS + \
9177         1 * ENABLE_ASH_JOB_CONTROL + \
9178         3)
9179 #define EXECCMD (builtintab + \
9180         2 + \
9181         1 * ENABLE_ASH_BUILTIN_TEST + \
9182         1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
9183         1 * ENABLE_ASH_ALIAS + \
9184         1 * ENABLE_ASH_JOB_CONTROL + \
9185         3 + \
9186         1 * ENABLE_ASH_CMDCMD + \
9187         1 + \
9188         ENABLE_ASH_BUILTIN_ECHO + \
9189         1)
9190
9191 /*
9192  * Search the table of builtin commands.
9193  */
9194 static struct builtincmd *
9195 find_builtin(const char *name)
9196 {
9197         struct builtincmd *bp;
9198
9199         bp = bsearch(
9200                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9201                 pstrcmp
9202         );
9203         return bp;
9204 }
9205
9206 /*
9207  * Execute a simple command.
9208  */
9209 static int
9210 isassignment(const char *p)
9211 {
9212         const char *q = endofname(p);
9213         if (p == q)
9214                 return 0;
9215         return *q == '=';
9216 }
9217 static int FAST_FUNC
9218 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9219 {
9220         /* Preserve exitstatus of a previous possible redirection
9221          * as POSIX mandates */
9222         return back_exitstatus;
9223 }
9224 static void
9225 evalcommand(union node *cmd, int flags)
9226 {
9227         static const struct builtincmd null_bltin = {
9228                 "\0\0", bltincmd /* why three NULs? */
9229         };
9230         struct stackmark smark;
9231         union node *argp;
9232         struct arglist arglist;
9233         struct arglist varlist;
9234         char **argv;
9235         int argc;
9236         const struct strlist *sp;
9237         struct cmdentry cmdentry;
9238         struct job *jp;
9239         char *lastarg;
9240         const char *path;
9241         int spclbltin;
9242         int status;
9243         char **nargv;
9244         struct builtincmd *bcmd;
9245         smallint cmd_is_exec;
9246         smallint pseudovarflag = 0;
9247
9248         /* First expand the arguments. */
9249         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9250         setstackmark(&smark);
9251         back_exitstatus = 0;
9252
9253         cmdentry.cmdtype = CMDBUILTIN;
9254         cmdentry.u.cmd = &null_bltin;
9255         varlist.lastp = &varlist.list;
9256         *varlist.lastp = NULL;
9257         arglist.lastp = &arglist.list;
9258         *arglist.lastp = NULL;
9259
9260         argc = 0;
9261         if (cmd->ncmd.args) {
9262                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9263                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9264         }
9265
9266         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9267                 struct strlist **spp;
9268
9269                 spp = arglist.lastp;
9270                 if (pseudovarflag && isassignment(argp->narg.text))
9271                         expandarg(argp, &arglist, EXP_VARTILDE);
9272                 else
9273                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9274
9275                 for (sp = *spp; sp; sp = sp->next)
9276                         argc++;
9277         }
9278
9279         argv = nargv = stalloc(sizeof(char *) * (argc + 1));
9280         for (sp = arglist.list; sp; sp = sp->next) {
9281                 TRACE(("evalcommand arg: %s\n", sp->text));
9282                 *nargv++ = sp->text;
9283         }
9284         *nargv = NULL;
9285
9286         lastarg = NULL;
9287         if (iflag && funcnest == 0 && argc > 0)
9288                 lastarg = nargv[-1];
9289
9290         preverrout_fd = 2;
9291         expredir(cmd->ncmd.redirect);
9292         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9293
9294         path = vpath.var_text;
9295         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9296                 struct strlist **spp;
9297                 char *p;
9298
9299                 spp = varlist.lastp;
9300                 expandarg(argp, &varlist, EXP_VARTILDE);
9301
9302                 /*
9303                  * Modify the command lookup path, if a PATH= assignment
9304                  * is present
9305                  */
9306                 p = (*spp)->text;
9307                 if (varcmp(p, path) == 0)
9308                         path = p;
9309         }
9310
9311         /* Print the command if xflag is set. */
9312         if (xflag) {
9313                 int n;
9314                 const char *p = " %s" + 1;
9315
9316                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9317                 sp = varlist.list;
9318                 for (n = 0; n < 2; n++) {
9319                         while (sp) {
9320                                 fdprintf(preverrout_fd, p, sp->text);
9321                                 sp = sp->next;
9322                                 p = " %s";
9323                         }
9324                         sp = arglist.list;
9325                 }
9326                 safe_write(preverrout_fd, "\n", 1);
9327         }
9328
9329         cmd_is_exec = 0;
9330         spclbltin = -1;
9331
9332         /* Now locate the command. */
9333         if (argc) {
9334                 int cmd_flag = DO_ERR;
9335 #if ENABLE_ASH_CMDCMD
9336                 const char *oldpath = path + 5;
9337 #endif
9338                 path += 5;
9339                 for (;;) {
9340                         find_command(argv[0], &cmdentry, cmd_flag, path);
9341                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9342                                 flush_stdout_stderr();
9343                                 status = 127;
9344                                 goto bail;
9345                         }
9346
9347                         /* implement bltin and command here */
9348                         if (cmdentry.cmdtype != CMDBUILTIN)
9349                                 break;
9350                         if (spclbltin < 0)
9351                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9352                         if (cmdentry.u.cmd == EXECCMD)
9353                                 cmd_is_exec = 1;
9354 #if ENABLE_ASH_CMDCMD
9355                         if (cmdentry.u.cmd == COMMANDCMD) {
9356                                 path = oldpath;
9357                                 nargv = parse_command_args(argv, &path);
9358                                 if (!nargv)
9359                                         break;
9360                                 argc -= nargv - argv;
9361                                 argv = nargv;
9362                                 cmd_flag |= DO_NOFUNC;
9363                         } else
9364 #endif
9365                                 break;
9366                 }
9367         }
9368
9369         if (status) {
9370                 /* We have a redirection error. */
9371                 if (spclbltin > 0)
9372                         raise_exception(EXERROR);
9373  bail:
9374                 exitstatus = status;
9375                 goto out;
9376         }
9377
9378         /* Execute the command. */
9379         switch (cmdentry.cmdtype) {
9380         default: {
9381
9382 #if ENABLE_FEATURE_SH_NOFORK
9383 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9384  *     around run_nofork_applet() call.
9385  * (2) Should this check also be done in forkshell()?
9386  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9387  */
9388                 /* find_command() encodes applet_no as (-2 - applet_no) */
9389                 int applet_no = (- cmdentry.u.index - 2);
9390                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9391                         listsetvar(varlist.list, VEXPORT|VSTACK);
9392                         /* run <applet>_main() */
9393                         exitstatus = run_nofork_applet(applet_no, argv);
9394                         break;
9395                 }
9396 #endif
9397                 /* Can we avoid forking off? For example, very last command
9398                  * in a script or a subshell does not need forking,
9399                  * we can just exec it.
9400                  */
9401                 if (!(flags & EV_EXIT) || may_have_traps) {
9402                         /* No, forking off a child is necessary */
9403                         INT_OFF;
9404                         jp = makejob(/*cmd,*/ 1);
9405                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9406                                 /* parent */
9407                                 exitstatus = waitforjob(jp);
9408                                 INT_ON;
9409                                 TRACE(("forked child exited with %d\n", exitstatus));
9410                                 break;
9411                         }
9412                         /* child */
9413                         FORCE_INT_ON;
9414                         /* fall through to exec'ing external program */
9415                 }
9416                 listsetvar(varlist.list, VEXPORT|VSTACK);
9417                 shellexec(argv, path, cmdentry.u.index);
9418                 /* NOTREACHED */
9419         } /* default */
9420         case CMDBUILTIN:
9421                 cmdenviron = varlist.list;
9422                 if (cmdenviron) {
9423                         struct strlist *list = cmdenviron;
9424                         int i = VNOSET;
9425                         if (spclbltin > 0 || argc == 0) {
9426                                 i = 0;
9427                                 if (cmd_is_exec && argc > 1)
9428                                         i = VEXPORT;
9429                         }
9430                         listsetvar(list, i);
9431                 }
9432                 /* Tight loop with builtins only:
9433                  * "while kill -0 $child; do true; done"
9434                  * will never exit even if $child died, unless we do this
9435                  * to reap the zombie and make kill detect that it's gone: */
9436                 dowait(DOWAIT_NONBLOCK, NULL);
9437
9438                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9439                         int exit_status;
9440                         int i = exception_type;
9441                         if (i == EXEXIT || i == EXEXEC)
9442                                 goto raise;
9443                         exit_status = 2;
9444                         if (i == EXINT)
9445                                 exit_status = 128 + SIGINT;
9446                         if (i == EXSIG)
9447                                 exit_status = 128 + pending_sig;
9448                         exitstatus = exit_status;
9449                         if (i == EXINT || spclbltin > 0) {
9450  raise:
9451                                 longjmp(exception_handler->loc, 1);
9452                         }
9453                         FORCE_INT_ON;
9454                 }
9455                 break;
9456
9457         case CMDFUNCTION:
9458                 listsetvar(varlist.list, 0);
9459                 /* See above for the rationale */
9460                 dowait(DOWAIT_NONBLOCK, NULL);
9461                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9462                         goto raise;
9463                 break;
9464         } /* switch */
9465
9466  out:
9467         popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9468         if (lastarg) {
9469                 /* dsl: I think this is intended to be used to support
9470                  * '_' in 'vi' command mode during line editing...
9471                  * However I implemented that within libedit itself.
9472                  */
9473                 setvar0("_", lastarg);
9474         }
9475         popstackmark(&smark);
9476 }
9477
9478 static int
9479 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9480 {
9481         char *volatile savecmdname;
9482         struct jmploc *volatile savehandler;
9483         struct jmploc jmploc;
9484         int i;
9485
9486         savecmdname = commandname;
9487         i = setjmp(jmploc.loc);
9488         if (i)
9489                 goto cmddone;
9490         savehandler = exception_handler;
9491         exception_handler = &jmploc;
9492         commandname = argv[0];
9493         argptr = argv + 1;
9494         optptr = NULL;                  /* initialize nextopt */
9495         exitstatus = (*cmd->builtin)(argc, argv);
9496         flush_stdout_stderr();
9497  cmddone:
9498         exitstatus |= ferror(stdout);
9499         clearerr(stdout);
9500         commandname = savecmdname;
9501         exception_handler = savehandler;
9502
9503         return i;
9504 }
9505
9506 static int
9507 goodname(const char *p)
9508 {
9509         return endofname(p)[0] == '\0';
9510 }
9511
9512
9513 /*
9514  * Search for a command.  This is called before we fork so that the
9515  * location of the command will be available in the parent as well as
9516  * the child.  The check for "goodname" is an overly conservative
9517  * check that the name will not be subject to expansion.
9518  */
9519 static void
9520 prehash(union node *n)
9521 {
9522         struct cmdentry entry;
9523
9524         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9525                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9526 }
9527
9528
9529 /* ============ Builtin commands
9530  *
9531  * Builtin commands whose functions are closely tied to evaluation
9532  * are implemented here.
9533  */
9534
9535 /*
9536  * Handle break and continue commands.  Break, continue, and return are
9537  * all handled by setting the evalskip flag.  The evaluation routines
9538  * above all check this flag, and if it is set they start skipping
9539  * commands rather than executing them.  The variable skipcount is
9540  * the number of loops to break/continue, or the number of function
9541  * levels to return.  (The latter is always 1.)  It should probably
9542  * be an error to break out of more loops than exist, but it isn't
9543  * in the standard shell so we don't make it one here.
9544  */
9545 static int FAST_FUNC
9546 breakcmd(int argc UNUSED_PARAM, char **argv)
9547 {
9548         int n = argv[1] ? number(argv[1]) : 1;
9549
9550         if (n <= 0)
9551                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9552         if (n > loopnest)
9553                 n = loopnest;
9554         if (n > 0) {
9555                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9556                 skipcount = n;
9557         }
9558         return 0;
9559 }
9560
9561
9562 /* ============ input.c
9563  *
9564  * This implements the input routines used by the parser.
9565  */
9566
9567 enum {
9568         INPUT_PUSH_FILE = 1,
9569         INPUT_NOFILE_OK = 2,
9570 };
9571
9572 static smallint checkkwd;
9573 /* values of checkkwd variable */
9574 #define CHKALIAS        0x1
9575 #define CHKKWD          0x2
9576 #define CHKNL           0x4
9577
9578 /*
9579  * Push a string back onto the input at this current parsefile level.
9580  * We handle aliases this way.
9581  */
9582 #if !ENABLE_ASH_ALIAS
9583 #define pushstring(s, ap) pushstring(s)
9584 #endif
9585 static void
9586 pushstring(char *s, struct alias *ap)
9587 {
9588         struct strpush *sp;
9589         int len;
9590
9591         len = strlen(s);
9592         INT_OFF;
9593         if (g_parsefile->strpush) {
9594                 sp = ckzalloc(sizeof(*sp));
9595                 sp->prev = g_parsefile->strpush;
9596         } else {
9597                 sp = &(g_parsefile->basestrpush);
9598         }
9599         g_parsefile->strpush = sp;
9600         sp->prev_string = g_parsefile->next_to_pgetc;
9601         sp->prev_left_in_line = g_parsefile->left_in_line;
9602 #if ENABLE_ASH_ALIAS
9603         sp->ap = ap;
9604         if (ap) {
9605                 ap->flag |= ALIASINUSE;
9606                 sp->string = s;
9607         }
9608 #endif
9609         g_parsefile->next_to_pgetc = s;
9610         g_parsefile->left_in_line = len;
9611         INT_ON;
9612 }
9613
9614 static void
9615 popstring(void)
9616 {
9617         struct strpush *sp = g_parsefile->strpush;
9618
9619         INT_OFF;
9620 #if ENABLE_ASH_ALIAS
9621         if (sp->ap) {
9622                 if (g_parsefile->next_to_pgetc[-1] == ' '
9623                  || g_parsefile->next_to_pgetc[-1] == '\t'
9624                 ) {
9625                         checkkwd |= CHKALIAS;
9626                 }
9627                 if (sp->string != sp->ap->val) {
9628                         free(sp->string);
9629                 }
9630                 sp->ap->flag &= ~ALIASINUSE;
9631                 if (sp->ap->flag & ALIASDEAD) {
9632                         unalias(sp->ap->name);
9633                 }
9634         }
9635 #endif
9636         g_parsefile->next_to_pgetc = sp->prev_string;
9637         g_parsefile->left_in_line = sp->prev_left_in_line;
9638         g_parsefile->strpush = sp->prev;
9639         if (sp != &(g_parsefile->basestrpush))
9640                 free(sp);
9641         INT_ON;
9642 }
9643
9644 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9645 //it peeks whether it is &>, and then pushes back both chars.
9646 //This function needs to save last *next_to_pgetc to buf[0]
9647 //to make two pungetc() reliable. Currently,
9648 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9649 static int
9650 preadfd(void)
9651 {
9652         int nr;
9653         char *buf = g_parsefile->buf;
9654
9655         g_parsefile->next_to_pgetc = buf;
9656 #if ENABLE_FEATURE_EDITING
9657  retry:
9658         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
9659                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9660         else {
9661                 int timeout = -1;
9662 # if ENABLE_ASH_IDLE_TIMEOUT
9663                 if (iflag) {
9664                         const char *tmout_var = lookupvar("TMOUT");
9665                         if (tmout_var) {
9666                                 timeout = atoi(tmout_var) * 1000;
9667                                 if (timeout <= 0)
9668                                         timeout = -1;
9669                         }
9670                 }
9671 # endif
9672 # if ENABLE_FEATURE_TAB_COMPLETION
9673                 line_input_state->path_lookup = pathval();
9674 # endif
9675                 reinit_unicode_for_ash();
9676                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
9677                 if (nr == 0) {
9678                         /* Ctrl+C pressed */
9679                         if (trap[SIGINT]) {
9680                                 buf[0] = '\n';
9681                                 buf[1] = '\0';
9682                                 raise(SIGINT);
9683                                 return 1;
9684                         }
9685                         goto retry;
9686                 }
9687                 if (nr < 0) {
9688                         if (errno == 0) {
9689                                 /* Ctrl+D pressed */
9690                                 nr = 0;
9691                         }
9692 # if ENABLE_ASH_IDLE_TIMEOUT
9693                         else if (errno == EAGAIN && timeout > 0) {
9694                                 puts("\007timed out waiting for input: auto-logout");
9695                                 exitshell();
9696                         }
9697 # endif
9698                 }
9699         }
9700 #else
9701         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
9702 #endif
9703
9704 #if 0 /* disabled: nonblock_immune_read() handles this problem */
9705         if (nr < 0) {
9706                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9707                         int flags = fcntl(0, F_GETFL);
9708                         if (flags >= 0 && (flags & O_NONBLOCK)) {
9709                                 flags &= ~O_NONBLOCK;
9710                                 if (fcntl(0, F_SETFL, flags) >= 0) {
9711                                         out2str("sh: turning off NDELAY mode\n");
9712                                         goto retry;
9713                                 }
9714                         }
9715                 }
9716         }
9717 #endif
9718         return nr;
9719 }
9720
9721 /*
9722  * Refill the input buffer and return the next input character:
9723  *
9724  * 1) If a string was pushed back on the input, pop it;
9725  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9726  *    or we are reading from a string so we can't refill the buffer,
9727  *    return EOF.
9728  * 3) If there is more stuff in this buffer, use it else call read to fill it.
9729  * 4) Process input up to the next newline, deleting nul characters.
9730  */
9731 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9732 #define pgetc_debug(...) ((void)0)
9733 static int
9734 preadbuffer(void)
9735 {
9736         char *q;
9737         int more;
9738
9739         while (g_parsefile->strpush) {
9740 #if ENABLE_ASH_ALIAS
9741                 if (g_parsefile->left_in_line == -1
9742                  && g_parsefile->strpush->ap
9743                  && g_parsefile->next_to_pgetc[-1] != ' '
9744                  && g_parsefile->next_to_pgetc[-1] != '\t'
9745                 ) {
9746                         pgetc_debug("preadbuffer PEOA");
9747                         return PEOA;
9748                 }
9749 #endif
9750                 popstring();
9751                 /* try "pgetc" now: */
9752                 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9753                                 g_parsefile->left_in_line,
9754                                 g_parsefile->next_to_pgetc,
9755                                 g_parsefile->next_to_pgetc);
9756                 if (--g_parsefile->left_in_line >= 0)
9757                         return (unsigned char)(*g_parsefile->next_to_pgetc++);
9758         }
9759         /* on both branches above g_parsefile->left_in_line < 0.
9760          * "pgetc" needs refilling.
9761          */
9762
9763         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9764          * pungetc() may increment it a few times.
9765          * Assuming it won't increment it to less than -90.
9766          */
9767         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9768                 pgetc_debug("preadbuffer PEOF1");
9769                 /* even in failure keep left_in_line and next_to_pgetc
9770                  * in lock step, for correct multi-layer pungetc.
9771                  * left_in_line was decremented before preadbuffer(),
9772                  * must inc next_to_pgetc: */
9773                 g_parsefile->next_to_pgetc++;
9774                 return PEOF;
9775         }
9776
9777         more = g_parsefile->left_in_buffer;
9778         if (more <= 0) {
9779                 flush_stdout_stderr();
9780  again:
9781                 more = preadfd();
9782                 if (more <= 0) {
9783                         /* don't try reading again */
9784                         g_parsefile->left_in_line = -99;
9785                         pgetc_debug("preadbuffer PEOF2");
9786                         g_parsefile->next_to_pgetc++;
9787                         return PEOF;
9788                 }
9789         }
9790
9791         /* Find out where's the end of line.
9792          * Set g_parsefile->left_in_line
9793          * and g_parsefile->left_in_buffer acordingly.
9794          * NUL chars are deleted.
9795          */
9796         q = g_parsefile->next_to_pgetc;
9797         for (;;) {
9798                 char c;
9799
9800                 more--;
9801
9802                 c = *q;
9803                 if (c == '\0') {
9804                         memmove(q, q + 1, more);
9805                 } else {
9806                         q++;
9807                         if (c == '\n') {
9808                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9809                                 break;
9810                         }
9811                 }
9812
9813                 if (more <= 0) {
9814                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9815                         if (g_parsefile->left_in_line < 0)
9816                                 goto again;
9817                         break;
9818                 }
9819         }
9820         g_parsefile->left_in_buffer = more;
9821
9822         if (vflag) {
9823                 char save = *q;
9824                 *q = '\0';
9825                 out2str(g_parsefile->next_to_pgetc);
9826                 *q = save;
9827         }
9828
9829         pgetc_debug("preadbuffer at %d:%p'%s'",
9830                         g_parsefile->left_in_line,
9831                         g_parsefile->next_to_pgetc,
9832                         g_parsefile->next_to_pgetc);
9833         return (unsigned char)*g_parsefile->next_to_pgetc++;
9834 }
9835
9836 #define pgetc_as_macro() \
9837         (--g_parsefile->left_in_line >= 0 \
9838         ? (unsigned char)*g_parsefile->next_to_pgetc++ \
9839         : preadbuffer() \
9840         )
9841
9842 static int
9843 pgetc(void)
9844 {
9845         pgetc_debug("pgetc_fast at %d:%p'%s'",
9846                         g_parsefile->left_in_line,
9847                         g_parsefile->next_to_pgetc,
9848                         g_parsefile->next_to_pgetc);
9849         return pgetc_as_macro();
9850 }
9851
9852 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9853 # define pgetc_fast() pgetc()
9854 #else
9855 # define pgetc_fast() pgetc_as_macro()
9856 #endif
9857
9858 #if ENABLE_ASH_ALIAS
9859 static int
9860 pgetc_without_PEOA(void)
9861 {
9862         int c;
9863         do {
9864                 pgetc_debug("pgetc_fast at %d:%p'%s'",
9865                                 g_parsefile->left_in_line,
9866                                 g_parsefile->next_to_pgetc,
9867                                 g_parsefile->next_to_pgetc);
9868                 c = pgetc_fast();
9869         } while (c == PEOA);
9870         return c;
9871 }
9872 #else
9873 # define pgetc_without_PEOA() pgetc()
9874 #endif
9875
9876 /*
9877  * Read a line from the script.
9878  */
9879 static char *
9880 pfgets(char *line, int len)
9881 {
9882         char *p = line;
9883         int nleft = len;
9884         int c;
9885
9886         while (--nleft > 0) {
9887                 c = pgetc_without_PEOA();
9888                 if (c == PEOF) {
9889                         if (p == line)
9890                                 return NULL;
9891                         break;
9892                 }
9893                 *p++ = c;
9894                 if (c == '\n')
9895                         break;
9896         }
9897         *p = '\0';
9898         return line;
9899 }
9900
9901 /*
9902  * Undo the last call to pgetc.  Only one character may be pushed back.
9903  * PEOF may be pushed back.
9904  */
9905 static void
9906 pungetc(void)
9907 {
9908         g_parsefile->left_in_line++;
9909         g_parsefile->next_to_pgetc--;
9910         pgetc_debug("pushed back to %d:%p'%s'",
9911                         g_parsefile->left_in_line,
9912                         g_parsefile->next_to_pgetc,
9913                         g_parsefile->next_to_pgetc);
9914 }
9915
9916 /*
9917  * To handle the "." command, a stack of input files is used.  Pushfile
9918  * adds a new entry to the stack and popfile restores the previous level.
9919  */
9920 static void
9921 pushfile(void)
9922 {
9923         struct parsefile *pf;
9924
9925         pf = ckzalloc(sizeof(*pf));
9926         pf->prev = g_parsefile;
9927         pf->pf_fd = -1;
9928         /*pf->strpush = NULL; - ckzalloc did it */
9929         /*pf->basestrpush.prev = NULL;*/
9930         g_parsefile = pf;
9931 }
9932
9933 static void
9934 popfile(void)
9935 {
9936         struct parsefile *pf = g_parsefile;
9937
9938         INT_OFF;
9939         if (pf->pf_fd >= 0)
9940                 close(pf->pf_fd);
9941         free(pf->buf);
9942         while (pf->strpush)
9943                 popstring();
9944         g_parsefile = pf->prev;
9945         free(pf);
9946         INT_ON;
9947 }
9948
9949 /*
9950  * Return to top level.
9951  */
9952 static void
9953 popallfiles(void)
9954 {
9955         while (g_parsefile != &basepf)
9956                 popfile();
9957 }
9958
9959 /*
9960  * Close the file(s) that the shell is reading commands from.  Called
9961  * after a fork is done.
9962  */
9963 static void
9964 closescript(void)
9965 {
9966         popallfiles();
9967         if (g_parsefile->pf_fd > 0) {
9968                 close(g_parsefile->pf_fd);
9969                 g_parsefile->pf_fd = 0;
9970         }
9971 }
9972
9973 /*
9974  * Like setinputfile, but takes an open file descriptor.  Call this with
9975  * interrupts off.
9976  */
9977 static void
9978 setinputfd(int fd, int push)
9979 {
9980         close_on_exec_on(fd);
9981         if (push) {
9982                 pushfile();
9983                 g_parsefile->buf = NULL;
9984         }
9985         g_parsefile->pf_fd = fd;
9986         if (g_parsefile->buf == NULL)
9987                 g_parsefile->buf = ckmalloc(IBUFSIZ);
9988         g_parsefile->left_in_buffer = 0;
9989         g_parsefile->left_in_line = 0;
9990         g_parsefile->linno = 1;
9991 }
9992
9993 /*
9994  * Set the input to take input from a file.  If push is set, push the
9995  * old input onto the stack first.
9996  */
9997 static int
9998 setinputfile(const char *fname, int flags)
9999 {
10000         int fd;
10001         int fd2;
10002
10003         INT_OFF;
10004         fd = open(fname, O_RDONLY);
10005         if (fd < 0) {
10006                 if (flags & INPUT_NOFILE_OK)
10007                         goto out;
10008                 ash_msg_and_raise_error("can't open '%s'", fname);
10009         }
10010         if (fd < 10) {
10011                 fd2 = copyfd(fd, 10);
10012                 close(fd);
10013                 if (fd2 < 0)
10014                         ash_msg_and_raise_error("out of file descriptors");
10015                 fd = fd2;
10016         }
10017         setinputfd(fd, flags & INPUT_PUSH_FILE);
10018  out:
10019         INT_ON;
10020         return fd;
10021 }
10022
10023 /*
10024  * Like setinputfile, but takes input from a string.
10025  */
10026 static void
10027 setinputstring(char *string)
10028 {
10029         INT_OFF;
10030         pushfile();
10031         g_parsefile->next_to_pgetc = string;
10032         g_parsefile->left_in_line = strlen(string);
10033         g_parsefile->buf = NULL;
10034         g_parsefile->linno = 1;
10035         INT_ON;
10036 }
10037
10038
10039 /* ============ mail.c
10040  *
10041  * Routines to check for mail.
10042  */
10043
10044 #if ENABLE_ASH_MAIL
10045
10046 /* Hash of mtimes of mailboxes */
10047 static unsigned mailtime_hash;
10048 /* Set if MAIL or MAILPATH is changed. */
10049 static smallint mail_var_path_changed;
10050
10051 /*
10052  * Print appropriate message(s) if mail has arrived.
10053  * If mail_var_path_changed is set,
10054  * then the value of MAIL has mail_var_path_changed,
10055  * so we just update the values.
10056  */
10057 static void
10058 chkmail(void)
10059 {
10060         const char *mpath;
10061         char *p;
10062         char *q;
10063         unsigned new_hash;
10064         struct stackmark smark;
10065         struct stat statb;
10066
10067         setstackmark(&smark);
10068         mpath = mpathset() ? mpathval() : mailval();
10069         new_hash = 0;
10070         for (;;) {
10071                 p = path_advance(&mpath, nullstr);
10072                 if (p == NULL)
10073                         break;
10074                 if (*p == '\0')
10075                         continue;
10076                 for (q = p; *q; q++)
10077                         continue;
10078 #if DEBUG
10079                 if (q[-1] != '/')
10080                         abort();
10081 #endif
10082                 q[-1] = '\0';                   /* delete trailing '/' */
10083                 if (stat(p, &statb) < 0) {
10084                         continue;
10085                 }
10086                 /* Very simplistic "hash": just a sum of all mtimes */
10087                 new_hash += (unsigned)statb.st_mtime;
10088         }
10089         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10090                 if (mailtime_hash != 0)
10091                         out2str("you have mail\n");
10092                 mailtime_hash = new_hash;
10093         }
10094         mail_var_path_changed = 0;
10095         popstackmark(&smark);
10096 }
10097
10098 static void FAST_FUNC
10099 changemail(const char *val UNUSED_PARAM)
10100 {
10101         mail_var_path_changed = 1;
10102 }
10103
10104 #endif /* ASH_MAIL */
10105
10106
10107 /* ============ ??? */
10108
10109 /*
10110  * Set the shell parameters.
10111  */
10112 static void
10113 setparam(char **argv)
10114 {
10115         char **newparam;
10116         char **ap;
10117         int nparam;
10118
10119         for (nparam = 0; argv[nparam]; nparam++)
10120                 continue;
10121         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10122         while (*argv) {
10123                 *ap++ = ckstrdup(*argv++);
10124         }
10125         *ap = NULL;
10126         freeparam(&shellparam);
10127         shellparam.malloced = 1;
10128         shellparam.nparam = nparam;
10129         shellparam.p = newparam;
10130 #if ENABLE_ASH_GETOPTS
10131         shellparam.optind = 1;
10132         shellparam.optoff = -1;
10133 #endif
10134 }
10135
10136 /*
10137  * Process shell options.  The global variable argptr contains a pointer
10138  * to the argument list; we advance it past the options.
10139  *
10140  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10141  * For a non-interactive shell, an error condition encountered
10142  * by a special built-in ... shall cause the shell to write a diagnostic message
10143  * to standard error and exit as shown in the following table:
10144  * Error                                           Special Built-In
10145  * ...
10146  * Utility syntax error (option or operand error)  Shall exit
10147  * ...
10148  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10149  * we see that bash does not do that (set "finishes" with error code 1 instead,
10150  * and shell continues), and people rely on this behavior!
10151  * Testcase:
10152  * set -o barfoo 2>/dev/null
10153  * echo $?
10154  *
10155  * Oh well. Let's mimic that.
10156  */
10157 static int
10158 plus_minus_o(char *name, int val)
10159 {
10160         int i;
10161
10162         if (name) {
10163                 for (i = 0; i < NOPTS; i++) {
10164                         if (strcmp(name, optnames(i)) == 0) {
10165                                 optlist[i] = val;
10166                                 return 0;
10167                         }
10168                 }
10169                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10170                 return 1;
10171         }
10172         for (i = 0; i < NOPTS; i++) {
10173                 if (val) {
10174                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10175                 } else {
10176                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10177                 }
10178         }
10179         return 0;
10180 }
10181 static void
10182 setoption(int flag, int val)
10183 {
10184         int i;
10185
10186         for (i = 0; i < NOPTS; i++) {
10187                 if (optletters(i) == flag) {
10188                         optlist[i] = val;
10189                         return;
10190                 }
10191         }
10192         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10193         /* NOTREACHED */
10194 }
10195 static int
10196 options(int cmdline)
10197 {
10198         char *p;
10199         int val;
10200         int c;
10201
10202         if (cmdline)
10203                 minusc = NULL;
10204         while ((p = *argptr) != NULL) {
10205                 c = *p++;
10206                 if (c != '-' && c != '+')
10207                         break;
10208                 argptr++;
10209                 val = 0; /* val = 0 if c == '+' */
10210                 if (c == '-') {
10211                         val = 1;
10212                         if (p[0] == '\0' || LONE_DASH(p)) {
10213                                 if (!cmdline) {
10214                                         /* "-" means turn off -x and -v */
10215                                         if (p[0] == '\0')
10216                                                 xflag = vflag = 0;
10217                                         /* "--" means reset params */
10218                                         else if (*argptr == NULL)
10219                                                 setparam(argptr);
10220                                 }
10221                                 break;    /* "-" or "--" terminates options */
10222                         }
10223                 }
10224                 /* first char was + or - */
10225                 while ((c = *p++) != '\0') {
10226                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10227                         if (c == 'c' && cmdline) {
10228                                 minusc = p;     /* command is after shell args */
10229                         } else if (c == 'o') {
10230                                 if (plus_minus_o(*argptr, val)) {
10231                                         /* it already printed err message */
10232                                         return 1; /* error */
10233                                 }
10234                                 if (*argptr)
10235                                         argptr++;
10236                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10237                                 isloginsh = 1;
10238                         /* bash does not accept +-login, we also won't */
10239                         } else if (cmdline && val && (c == '-')) { /* long options */
10240                                 if (strcmp(p, "login") == 0)
10241                                         isloginsh = 1;
10242                                 break;
10243                         } else {
10244                                 setoption(c, val);
10245                         }
10246                 }
10247         }
10248         return 0;
10249 }
10250
10251 /*
10252  * The shift builtin command.
10253  */
10254 static int FAST_FUNC
10255 shiftcmd(int argc UNUSED_PARAM, char **argv)
10256 {
10257         int n;
10258         char **ap1, **ap2;
10259
10260         n = 1;
10261         if (argv[1])
10262                 n = number(argv[1]);
10263         if (n > shellparam.nparam)
10264                 n = 0; /* bash compat, was = shellparam.nparam; */
10265         INT_OFF;
10266         shellparam.nparam -= n;
10267         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10268                 if (shellparam.malloced)
10269                         free(*ap1);
10270         }
10271         ap2 = shellparam.p;
10272         while ((*ap2++ = *ap1++) != NULL)
10273                 continue;
10274 #if ENABLE_ASH_GETOPTS
10275         shellparam.optind = 1;
10276         shellparam.optoff = -1;
10277 #endif
10278         INT_ON;
10279         return 0;
10280 }
10281
10282 /*
10283  * POSIX requires that 'set' (but not export or readonly) output the
10284  * variables in lexicographic order - by the locale's collating order (sigh).
10285  * Maybe we could keep them in an ordered balanced binary tree
10286  * instead of hashed lists.
10287  * For now just roll 'em through qsort for printing...
10288  */
10289 static int
10290 showvars(const char *sep_prefix, int on, int off)
10291 {
10292         const char *sep;
10293         char **ep, **epend;
10294
10295         ep = listvars(on, off, &epend);
10296         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10297
10298         sep = *sep_prefix ? " " : sep_prefix;
10299
10300         for (; ep < epend; ep++) {
10301                 const char *p;
10302                 const char *q;
10303
10304                 p = strchrnul(*ep, '=');
10305                 q = nullstr;
10306                 if (*p)
10307                         q = single_quote(++p);
10308                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10309         }
10310         return 0;
10311 }
10312
10313 /*
10314  * The set command builtin.
10315  */
10316 static int FAST_FUNC
10317 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10318 {
10319         int retval;
10320
10321         if (!argv[1])
10322                 return showvars(nullstr, 0, VUNSET);
10323
10324         INT_OFF;
10325         retval = options(/*cmdline:*/ 0);
10326         if (retval == 0) { /* if no parse error... */
10327                 optschanged();
10328                 if (*argptr != NULL) {
10329                         setparam(argptr);
10330                 }
10331         }
10332         INT_ON;
10333         return retval;
10334 }
10335
10336 #if ENABLE_ASH_RANDOM_SUPPORT
10337 static void FAST_FUNC
10338 change_random(const char *value)
10339 {
10340         uint32_t t;
10341
10342         if (value == NULL) {
10343                 /* "get", generate */
10344                 t = next_random(&random_gen);
10345                 /* set without recursion */
10346                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10347                 vrandom.flags &= ~VNOFUNC;
10348         } else {
10349                 /* set/reset */
10350                 t = strtoul(value, NULL, 10);
10351                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10352         }
10353 }
10354 #endif
10355
10356 #if ENABLE_ASH_GETOPTS
10357 static int
10358 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
10359 {
10360         char *p, *q;
10361         char c = '?';
10362         int done = 0;
10363         int err = 0;
10364         char sbuf[2];
10365         char **optnext;
10366
10367         sbuf[1] = '\0';
10368
10369         if (*param_optind < 1)
10370                 return 1;
10371         optnext = optfirst + *param_optind - 1;
10372
10373         if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
10374                 p = NULL;
10375         else
10376                 p = optnext[-1] + *optoff;
10377         if (p == NULL || *p == '\0') {
10378                 /* Current word is done, advance */
10379                 p = *optnext;
10380                 if (p == NULL || *p != '-' || *++p == '\0') {
10381  atend:
10382                         p = NULL;
10383                         done = 1;
10384                         goto out;
10385                 }
10386                 optnext++;
10387                 if (LONE_DASH(p))        /* check for "--" */
10388                         goto atend;
10389         }
10390
10391         c = *p++;
10392         for (q = optstr; *q != c;) {
10393                 if (*q == '\0') {
10394                         if (optstr[0] == ':') {
10395                                 sbuf[0] = c;
10396                                 /*sbuf[1] = '\0'; - already is */
10397                                 err |= setvarsafe("OPTARG", sbuf, 0);
10398                         } else {
10399                                 fprintf(stderr, "Illegal option -%c\n", c);
10400                                 unsetvar("OPTARG");
10401                         }
10402                         c = '?';
10403                         goto out;
10404                 }
10405                 if (*++q == ':')
10406                         q++;
10407         }
10408
10409         if (*++q == ':') {
10410                 if (*p == '\0' && (p = *optnext) == NULL) {
10411                         if (optstr[0] == ':') {
10412                                 sbuf[0] = c;
10413                                 /*sbuf[1] = '\0'; - already is */
10414                                 err |= setvarsafe("OPTARG", sbuf, 0);
10415                                 c = ':';
10416                         } else {
10417                                 fprintf(stderr, "No arg for -%c option\n", c);
10418                                 unsetvar("OPTARG");
10419                                 c = '?';
10420                         }
10421                         goto out;
10422                 }
10423
10424                 if (p == *optnext)
10425                         optnext++;
10426                 err |= setvarsafe("OPTARG", p, 0);
10427                 p = NULL;
10428         } else
10429                 err |= setvarsafe("OPTARG", nullstr, 0);
10430  out:
10431         *optoff = p ? p - *(optnext - 1) : -1;
10432         *param_optind = optnext - optfirst + 1;
10433         err |= setvarsafe("OPTIND", itoa(*param_optind), VNOFUNC);
10434         sbuf[0] = c;
10435         /*sbuf[1] = '\0'; - already is */
10436         err |= setvarsafe(optvar, sbuf, 0);
10437         if (err) {
10438                 *param_optind = 1;
10439                 *optoff = -1;
10440                 flush_stdout_stderr();
10441                 raise_exception(EXERROR);
10442         }
10443         return done;
10444 }
10445
10446 /*
10447  * The getopts builtin.  Shellparam.optnext points to the next argument
10448  * to be processed.  Shellparam.optptr points to the next character to
10449  * be processed in the current argument.  If shellparam.optnext is NULL,
10450  * then it's the first time getopts has been called.
10451  */
10452 static int FAST_FUNC
10453 getoptscmd(int argc, char **argv)
10454 {
10455         char **optbase;
10456
10457         if (argc < 3)
10458                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10459         if (argc == 3) {
10460                 optbase = shellparam.p;
10461                 if (shellparam.optind > shellparam.nparam + 1) {
10462                         shellparam.optind = 1;
10463                         shellparam.optoff = -1;
10464                 }
10465         } else {
10466                 optbase = &argv[3];
10467                 if (shellparam.optind > argc - 2) {
10468                         shellparam.optind = 1;
10469                         shellparam.optoff = -1;
10470                 }
10471         }
10472
10473         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
10474                         &shellparam.optoff);
10475 }
10476 #endif /* ASH_GETOPTS */
10477
10478
10479 /* ============ Shell parser */
10480
10481 struct heredoc {
10482         struct heredoc *next;   /* next here document in list */
10483         union node *here;       /* redirection node */
10484         char *eofmark;          /* string indicating end of input */
10485         smallint striptabs;     /* if set, strip leading tabs */
10486 };
10487
10488 static smallint tokpushback;           /* last token pushed back */
10489 static smallint quoteflag;             /* set if (part of) last token was quoted */
10490 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10491 static struct heredoc *heredoclist;    /* list of here documents to read */
10492 static char *wordtext;                 /* text of last word returned by readtoken */
10493 static struct nodelist *backquotelist;
10494 static union node *redirnode;
10495 static struct heredoc *heredoc;
10496
10497 static const char *
10498 tokname(char *buf, int tok)
10499 {
10500         if (tok < TSEMI)
10501                 return tokname_array[tok] + 1;
10502         sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
10503         return buf;
10504 }
10505
10506 /* raise_error_unexpected_syntax:
10507  * Called when an unexpected token is read during the parse.  The argument
10508  * is the token that is expected, or -1 if more than one type of token can
10509  * occur at this point.
10510  */
10511 static void raise_error_unexpected_syntax(int) NORETURN;
10512 static void
10513 raise_error_unexpected_syntax(int token)
10514 {
10515         char msg[64];
10516         char buf[16];
10517         int l;
10518
10519         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10520         if (token >= 0)
10521                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10522         raise_error_syntax(msg);
10523         /* NOTREACHED */
10524 }
10525
10526 #define EOFMARKLEN 79
10527
10528 /* parsing is heavily cross-recursive, need these forward decls */
10529 static union node *andor(void);
10530 static union node *pipeline(void);
10531 static union node *parse_command(void);
10532 static void parseheredoc(void);
10533 static int peektoken(void);
10534 static int readtoken(void);
10535
10536 static union node *
10537 list(int nlflag)
10538 {
10539         union node *n1, *n2, *n3;
10540         int tok;
10541
10542         n1 = NULL;
10543         for (;;) {
10544                 switch (peektoken()) {
10545                 case TNL:
10546                         if (!(nlflag & 1))
10547                                 break;
10548                         parseheredoc();
10549                         return n1;
10550
10551                 case TEOF:
10552                         if (!n1 && (nlflag & 1))
10553                                 n1 = NODE_EOF;
10554                         parseheredoc();
10555                         return n1;
10556                 }
10557
10558                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10559                 if (nlflag == 2 && tokname_array[peektoken()][0])
10560                         return n1;
10561                 nlflag |= 2;
10562
10563                 n2 = andor();
10564                 tok = readtoken();
10565                 if (tok == TBACKGND) {
10566                         if (n2->type == NPIPE) {
10567                                 n2->npipe.pipe_backgnd = 1;
10568                         } else {
10569                                 if (n2->type != NREDIR) {
10570                                         n3 = stzalloc(sizeof(struct nredir));
10571                                         n3->nredir.n = n2;
10572                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10573                                         n2 = n3;
10574                                 }
10575                                 n2->type = NBACKGND;
10576                         }
10577                 }
10578                 if (n1 == NULL) {
10579                         n1 = n2;
10580                 } else {
10581                         n3 = stzalloc(sizeof(struct nbinary));
10582                         n3->type = NSEMI;
10583                         n3->nbinary.ch1 = n1;
10584                         n3->nbinary.ch2 = n2;
10585                         n1 = n3;
10586                 }
10587                 switch (tok) {
10588                 case TNL:
10589                 case TEOF:
10590                         tokpushback = 1;
10591                         /* fall through */
10592                 case TBACKGND:
10593                 case TSEMI:
10594                         break;
10595                 default:
10596                         if ((nlflag & 1))
10597                                 raise_error_unexpected_syntax(-1);
10598                         tokpushback = 1;
10599                         return n1;
10600                 }
10601         }
10602 }
10603
10604 static union node *
10605 andor(void)
10606 {
10607         union node *n1, *n2, *n3;
10608         int t;
10609
10610         n1 = pipeline();
10611         for (;;) {
10612                 t = readtoken();
10613                 if (t == TAND) {
10614                         t = NAND;
10615                 } else if (t == TOR) {
10616                         t = NOR;
10617                 } else {
10618                         tokpushback = 1;
10619                         return n1;
10620                 }
10621                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10622                 n2 = pipeline();
10623                 n3 = stzalloc(sizeof(struct nbinary));
10624                 n3->type = t;
10625                 n3->nbinary.ch1 = n1;
10626                 n3->nbinary.ch2 = n2;
10627                 n1 = n3;
10628         }
10629 }
10630
10631 static union node *
10632 pipeline(void)
10633 {
10634         union node *n1, *n2, *pipenode;
10635         struct nodelist *lp, *prev;
10636         int negate;
10637
10638         negate = 0;
10639         TRACE(("pipeline: entered\n"));
10640         if (readtoken() == TNOT) {
10641                 negate = !negate;
10642                 checkkwd = CHKKWD | CHKALIAS;
10643         } else
10644                 tokpushback = 1;
10645         n1 = parse_command();
10646         if (readtoken() == TPIPE) {
10647                 pipenode = stzalloc(sizeof(struct npipe));
10648                 pipenode->type = NPIPE;
10649                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10650                 lp = stzalloc(sizeof(struct nodelist));
10651                 pipenode->npipe.cmdlist = lp;
10652                 lp->n = n1;
10653                 do {
10654                         prev = lp;
10655                         lp = stzalloc(sizeof(struct nodelist));
10656                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
10657                         lp->n = parse_command();
10658                         prev->next = lp;
10659                 } while (readtoken() == TPIPE);
10660                 lp->next = NULL;
10661                 n1 = pipenode;
10662         }
10663         tokpushback = 1;
10664         if (negate) {
10665                 n2 = stzalloc(sizeof(struct nnot));
10666                 n2->type = NNOT;
10667                 n2->nnot.com = n1;
10668                 return n2;
10669         }
10670         return n1;
10671 }
10672
10673 static union node *
10674 makename(void)
10675 {
10676         union node *n;
10677
10678         n = stzalloc(sizeof(struct narg));
10679         n->type = NARG;
10680         /*n->narg.next = NULL; - stzalloc did it */
10681         n->narg.text = wordtext;
10682         n->narg.backquote = backquotelist;
10683         return n;
10684 }
10685
10686 static void
10687 fixredir(union node *n, const char *text, int err)
10688 {
10689         int fd;
10690
10691         TRACE(("Fix redir %s %d\n", text, err));
10692         if (!err)
10693                 n->ndup.vname = NULL;
10694
10695         fd = bb_strtou(text, NULL, 10);
10696         if (!errno && fd >= 0)
10697                 n->ndup.dupfd = fd;
10698         else if (LONE_DASH(text))
10699                 n->ndup.dupfd = -1;
10700         else {
10701                 if (err)
10702                         raise_error_syntax("bad fd number");
10703                 n->ndup.vname = makename();
10704         }
10705 }
10706
10707 /*
10708  * Returns true if the text contains nothing to expand (no dollar signs
10709  * or backquotes).
10710  */
10711 static int
10712 noexpand(const char *text)
10713 {
10714         unsigned char c;
10715
10716         while ((c = *text++) != '\0') {
10717                 if (c == CTLQUOTEMARK)
10718                         continue;
10719                 if (c == CTLESC)
10720                         text++;
10721                 else if (SIT(c, BASESYNTAX) == CCTL)
10722                         return 0;
10723         }
10724         return 1;
10725 }
10726
10727 static void
10728 parsefname(void)
10729 {
10730         union node *n = redirnode;
10731
10732         if (readtoken() != TWORD)
10733                 raise_error_unexpected_syntax(-1);
10734         if (n->type == NHERE) {
10735                 struct heredoc *here = heredoc;
10736                 struct heredoc *p;
10737                 int i;
10738
10739                 if (quoteflag == 0)
10740                         n->type = NXHERE;
10741                 TRACE(("Here document %d\n", n->type));
10742                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10743                         raise_error_syntax("illegal eof marker for << redirection");
10744                 rmescapes(wordtext, 0);
10745                 here->eofmark = wordtext;
10746                 here->next = NULL;
10747                 if (heredoclist == NULL)
10748                         heredoclist = here;
10749                 else {
10750                         for (p = heredoclist; p->next; p = p->next)
10751                                 continue;
10752                         p->next = here;
10753                 }
10754         } else if (n->type == NTOFD || n->type == NFROMFD) {
10755                 fixredir(n, wordtext, 0);
10756         } else {
10757                 n->nfile.fname = makename();
10758         }
10759 }
10760
10761 static union node *
10762 simplecmd(void)
10763 {
10764         union node *args, **app;
10765         union node *n = NULL;
10766         union node *vars, **vpp;
10767         union node **rpp, *redir;
10768         int savecheckkwd;
10769 #if ENABLE_ASH_BASH_COMPAT
10770         smallint double_brackets_flag = 0;
10771         smallint function_flag = 0;
10772 #endif
10773
10774         args = NULL;
10775         app = &args;
10776         vars = NULL;
10777         vpp = &vars;
10778         redir = NULL;
10779         rpp = &redir;
10780
10781         savecheckkwd = CHKALIAS;
10782         for (;;) {
10783                 int t;
10784                 checkkwd = savecheckkwd;
10785                 t = readtoken();
10786                 switch (t) {
10787 #if ENABLE_ASH_BASH_COMPAT
10788                 case TFUNCTION:
10789                         if (peektoken() != TWORD)
10790                                 raise_error_unexpected_syntax(TWORD);
10791                         function_flag = 1;
10792                         break;
10793                 case TAND: /* "&&" */
10794                 case TOR: /* "||" */
10795                         if (!double_brackets_flag) {
10796                                 tokpushback = 1;
10797                                 goto out;
10798                         }
10799                         wordtext = (char *) (t == TAND ? "-a" : "-o");
10800 #endif
10801                 case TWORD:
10802                         n = stzalloc(sizeof(struct narg));
10803                         n->type = NARG;
10804                         /*n->narg.next = NULL; - stzalloc did it */
10805                         n->narg.text = wordtext;
10806 #if ENABLE_ASH_BASH_COMPAT
10807                         if (strcmp("[[", wordtext) == 0)
10808                                 double_brackets_flag = 1;
10809                         else if (strcmp("]]", wordtext) == 0)
10810                                 double_brackets_flag = 0;
10811 #endif
10812                         n->narg.backquote = backquotelist;
10813                         if (savecheckkwd && isassignment(wordtext)) {
10814                                 *vpp = n;
10815                                 vpp = &n->narg.next;
10816                         } else {
10817                                 *app = n;
10818                                 app = &n->narg.next;
10819                                 savecheckkwd = 0;
10820                         }
10821 #if ENABLE_ASH_BASH_COMPAT
10822                         if (function_flag) {
10823                                 checkkwd = CHKNL | CHKKWD;
10824                                 switch (peektoken()) {
10825                                 case TBEGIN:
10826                                 case TIF:
10827                                 case TCASE:
10828                                 case TUNTIL:
10829                                 case TWHILE:
10830                                 case TFOR:
10831                                         goto do_func;
10832                                 case TLP:
10833                                         function_flag = 0;
10834                                         break;
10835                                 case TWORD:
10836                                         if (strcmp("[[", wordtext) == 0)
10837                                                 goto do_func;
10838                                         /* fall through */
10839                                 default:
10840                                         raise_error_unexpected_syntax(-1);
10841                                 }
10842                         }
10843 #endif
10844                         break;
10845                 case TREDIR:
10846                         *rpp = n = redirnode;
10847                         rpp = &n->nfile.next;
10848                         parsefname();   /* read name of redirection file */
10849                         break;
10850                 case TLP:
10851  IF_ASH_BASH_COMPAT(do_func:)
10852                         if (args && app == &args->narg.next
10853                          && !vars && !redir
10854                         ) {
10855                                 struct builtincmd *bcmd;
10856                                 const char *name;
10857
10858                                 /* We have a function */
10859                                 if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP)
10860                                         raise_error_unexpected_syntax(TRP);
10861                                 name = n->narg.text;
10862                                 if (!goodname(name)
10863                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10864                                 ) {
10865                                         raise_error_syntax("bad function name");
10866                                 }
10867                                 n->type = NDEFUN;
10868                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10869                                 n->narg.next = parse_command();
10870                                 return n;
10871                         }
10872                         IF_ASH_BASH_COMPAT(function_flag = 0;)
10873                         /* fall through */
10874                 default:
10875                         tokpushback = 1;
10876                         goto out;
10877                 }
10878         }
10879  out:
10880         *app = NULL;
10881         *vpp = NULL;
10882         *rpp = NULL;
10883         n = stzalloc(sizeof(struct ncmd));
10884         n->type = NCMD;
10885         n->ncmd.args = args;
10886         n->ncmd.assign = vars;
10887         n->ncmd.redirect = redir;
10888         return n;
10889 }
10890
10891 static union node *
10892 parse_command(void)
10893 {
10894         union node *n1, *n2;
10895         union node *ap, **app;
10896         union node *cp, **cpp;
10897         union node *redir, **rpp;
10898         union node **rpp2;
10899         int t;
10900
10901         redir = NULL;
10902         rpp2 = &redir;
10903
10904         switch (readtoken()) {
10905         default:
10906                 raise_error_unexpected_syntax(-1);
10907                 /* NOTREACHED */
10908         case TIF:
10909                 n1 = stzalloc(sizeof(struct nif));
10910                 n1->type = NIF;
10911                 n1->nif.test = list(0);
10912                 if (readtoken() != TTHEN)
10913                         raise_error_unexpected_syntax(TTHEN);
10914                 n1->nif.ifpart = list(0);
10915                 n2 = n1;
10916                 while (readtoken() == TELIF) {
10917                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
10918                         n2 = n2->nif.elsepart;
10919                         n2->type = NIF;
10920                         n2->nif.test = list(0);
10921                         if (readtoken() != TTHEN)
10922                                 raise_error_unexpected_syntax(TTHEN);
10923                         n2->nif.ifpart = list(0);
10924                 }
10925                 if (lasttoken == TELSE)
10926                         n2->nif.elsepart = list(0);
10927                 else {
10928                         n2->nif.elsepart = NULL;
10929                         tokpushback = 1;
10930                 }
10931                 t = TFI;
10932                 break;
10933         case TWHILE:
10934         case TUNTIL: {
10935                 int got;
10936                 n1 = stzalloc(sizeof(struct nbinary));
10937                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10938                 n1->nbinary.ch1 = list(0);
10939                 got = readtoken();
10940                 if (got != TDO) {
10941                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got] + 1,
10942                                         got == TWORD ? wordtext : ""));
10943                         raise_error_unexpected_syntax(TDO);
10944                 }
10945                 n1->nbinary.ch2 = list(0);
10946                 t = TDONE;
10947                 break;
10948         }
10949         case TFOR:
10950                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10951                         raise_error_syntax("bad for loop variable");
10952                 n1 = stzalloc(sizeof(struct nfor));
10953                 n1->type = NFOR;
10954                 n1->nfor.var = wordtext;
10955                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10956                 if (readtoken() == TIN) {
10957                         app = &ap;
10958                         while (readtoken() == TWORD) {
10959                                 n2 = stzalloc(sizeof(struct narg));
10960                                 n2->type = NARG;
10961                                 /*n2->narg.next = NULL; - stzalloc did it */
10962                                 n2->narg.text = wordtext;
10963                                 n2->narg.backquote = backquotelist;
10964                                 *app = n2;
10965                                 app = &n2->narg.next;
10966                         }
10967                         *app = NULL;
10968                         n1->nfor.args = ap;
10969                         if (lasttoken != TNL && lasttoken != TSEMI)
10970                                 raise_error_unexpected_syntax(-1);
10971                 } else {
10972                         n2 = stzalloc(sizeof(struct narg));
10973                         n2->type = NARG;
10974                         /*n2->narg.next = NULL; - stzalloc did it */
10975                         n2->narg.text = (char *)dolatstr;
10976                         /*n2->narg.backquote = NULL;*/
10977                         n1->nfor.args = n2;
10978                         /*
10979                          * Newline or semicolon here is optional (but note
10980                          * that the original Bourne shell only allowed NL).
10981                          */
10982                         if (lasttoken != TSEMI)
10983                                 tokpushback = 1;
10984                 }
10985                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10986                 if (readtoken() != TDO)
10987                         raise_error_unexpected_syntax(TDO);
10988                 n1->nfor.body = list(0);
10989                 t = TDONE;
10990                 break;
10991         case TCASE:
10992                 n1 = stzalloc(sizeof(struct ncase));
10993                 n1->type = NCASE;
10994                 if (readtoken() != TWORD)
10995                         raise_error_unexpected_syntax(TWORD);
10996                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10997                 n2->type = NARG;
10998                 /*n2->narg.next = NULL; - stzalloc did it */
10999                 n2->narg.text = wordtext;
11000                 n2->narg.backquote = backquotelist;
11001                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11002                 if (readtoken() != TIN)
11003                         raise_error_unexpected_syntax(TIN);
11004                 cpp = &n1->ncase.cases;
11005  next_case:
11006                 checkkwd = CHKNL | CHKKWD;
11007                 t = readtoken();
11008                 while (t != TESAC) {
11009                         if (lasttoken == TLP)
11010                                 readtoken();
11011                         *cpp = cp = stzalloc(sizeof(struct nclist));
11012                         cp->type = NCLIST;
11013                         app = &cp->nclist.pattern;
11014                         for (;;) {
11015                                 *app = ap = stzalloc(sizeof(struct narg));
11016                                 ap->type = NARG;
11017                                 /*ap->narg.next = NULL; - stzalloc did it */
11018                                 ap->narg.text = wordtext;
11019                                 ap->narg.backquote = backquotelist;
11020                                 if (readtoken() != TPIPE)
11021                                         break;
11022                                 app = &ap->narg.next;
11023                                 readtoken();
11024                         }
11025                         //ap->narg.next = NULL;
11026                         if (lasttoken != TRP)
11027                                 raise_error_unexpected_syntax(TRP);
11028                         cp->nclist.body = list(2);
11029
11030                         cpp = &cp->nclist.next;
11031
11032                         checkkwd = CHKNL | CHKKWD;
11033                         t = readtoken();
11034                         if (t != TESAC) {
11035                                 if (t != TENDCASE)
11036                                         raise_error_unexpected_syntax(TENDCASE);
11037                                 goto next_case;
11038                         }
11039                 }
11040                 *cpp = NULL;
11041                 goto redir;
11042         case TLP:
11043                 n1 = stzalloc(sizeof(struct nredir));
11044                 n1->type = NSUBSHELL;
11045                 n1->nredir.n = list(0);
11046                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11047                 t = TRP;
11048                 break;
11049         case TBEGIN:
11050                 n1 = list(0);
11051                 t = TEND;
11052                 break;
11053         IF_ASH_BASH_COMPAT(case TFUNCTION:)
11054         case TWORD:
11055         case TREDIR:
11056                 tokpushback = 1;
11057                 return simplecmd();
11058         }
11059
11060         if (readtoken() != t)
11061                 raise_error_unexpected_syntax(t);
11062
11063  redir:
11064         /* Now check for redirection which may follow command */
11065         checkkwd = CHKKWD | CHKALIAS;
11066         rpp = rpp2;
11067         while (readtoken() == TREDIR) {
11068                 *rpp = n2 = redirnode;
11069                 rpp = &n2->nfile.next;
11070                 parsefname();
11071         }
11072         tokpushback = 1;
11073         *rpp = NULL;
11074         if (redir) {
11075                 if (n1->type != NSUBSHELL) {
11076                         n2 = stzalloc(sizeof(struct nredir));
11077                         n2->type = NREDIR;
11078                         n2->nredir.n = n1;
11079                         n1 = n2;
11080                 }
11081                 n1->nredir.redirect = redir;
11082         }
11083         return n1;
11084 }
11085
11086 #if ENABLE_ASH_BASH_COMPAT
11087 static int decode_dollar_squote(void)
11088 {
11089         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11090         int c, cnt;
11091         char *p;
11092         char buf[4];
11093
11094         c = pgetc();
11095         p = strchr(C_escapes, c);
11096         if (p) {
11097                 buf[0] = c;
11098                 p = buf;
11099                 cnt = 3;
11100                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11101                         do {
11102                                 c = pgetc();
11103                                 *++p = c;
11104                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11105                         pungetc();
11106                 } else if (c == 'x') { /* \xHH */
11107                         do {
11108                                 c = pgetc();
11109                                 *++p = c;
11110                         } while (isxdigit(c) && --cnt);
11111                         pungetc();
11112                         if (cnt == 3) { /* \x but next char is "bad" */
11113                                 c = 'x';
11114                                 goto unrecognized;
11115                         }
11116                 } else { /* simple seq like \\ or \t */
11117                         p++;
11118                 }
11119                 *p = '\0';
11120                 p = buf;
11121                 c = bb_process_escape_sequence((void*)&p);
11122         } else { /* unrecognized "\z": print both chars unless ' or " */
11123                 if (c != '\'' && c != '"') {
11124  unrecognized:
11125                         c |= 0x100; /* "please encode \, then me" */
11126                 }
11127         }
11128         return c;
11129 }
11130 #endif
11131
11132 /*
11133  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11134  * is not NULL, read a here document.  In the latter case, eofmark is the
11135  * word which marks the end of the document and striptabs is true if
11136  * leading tabs should be stripped from the document.  The argument c
11137  * is the first character of the input token or document.
11138  *
11139  * Because C does not have internal subroutines, I have simulated them
11140  * using goto's to implement the subroutine linkage.  The following macros
11141  * will run code that appears at the end of readtoken1.
11142  */
11143 #define CHECKEND()      {goto checkend; checkend_return:;}
11144 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11145 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11146 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11147 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11148 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11149 static int
11150 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11151 {
11152         /* NB: syntax parameter fits into smallint */
11153         /* c parameter is an unsigned char or PEOF or PEOA */
11154         char *out;
11155         int len;
11156         char line[EOFMARKLEN + 1];
11157         struct nodelist *bqlist;
11158         smallint quotef;
11159         smallint dblquote;
11160         smallint oldstyle;
11161         smallint prevsyntax; /* syntax before arithmetic */
11162 #if ENABLE_ASH_EXPAND_PRMT
11163         smallint pssyntax;   /* we are expanding a prompt string */
11164 #endif
11165         int varnest;         /* levels of variables expansion */
11166         int arinest;         /* levels of arithmetic expansion */
11167         int parenlevel;      /* levels of parens in arithmetic */
11168         int dqvarnest;       /* levels of variables expansion within double quotes */
11169
11170         IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
11171
11172         startlinno = g_parsefile->linno;
11173         bqlist = NULL;
11174         quotef = 0;
11175         prevsyntax = 0;
11176 #if ENABLE_ASH_EXPAND_PRMT
11177         pssyntax = (syntax == PSSYNTAX);
11178         if (pssyntax)
11179                 syntax = DQSYNTAX;
11180 #endif
11181         dblquote = (syntax == DQSYNTAX);
11182         varnest = 0;
11183         arinest = 0;
11184         parenlevel = 0;
11185         dqvarnest = 0;
11186
11187         STARTSTACKSTR(out);
11188  loop:
11189         /* For each line, until end of word */
11190         CHECKEND();     /* set c to PEOF if at end of here document */
11191         for (;;) {      /* until end of line or end of word */
11192                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11193                 switch (SIT(c, syntax)) {
11194                 case CNL:       /* '\n' */
11195                         if (syntax == BASESYNTAX)
11196                                 goto endword;   /* exit outer loop */
11197                         USTPUTC(c, out);
11198                         g_parsefile->linno++;
11199                         setprompt_if(doprompt, 2);
11200                         c = pgetc();
11201                         goto loop;              /* continue outer loop */
11202                 case CWORD:
11203                         USTPUTC(c, out);
11204                         break;
11205                 case CCTL:
11206                         if (eofmark == NULL || dblquote)
11207                                 USTPUTC(CTLESC, out);
11208 #if ENABLE_ASH_BASH_COMPAT
11209                         if (c == '\\' && bash_dollar_squote) {
11210                                 c = decode_dollar_squote();
11211                                 if (c & 0x100) {
11212                                         USTPUTC('\\', out);
11213                                         c = (unsigned char)c;
11214                                 }
11215                         }
11216 #endif
11217                         USTPUTC(c, out);
11218                         break;
11219                 case CBACK:     /* backslash */
11220                         c = pgetc_without_PEOA();
11221                         if (c == PEOF) {
11222                                 USTPUTC(CTLESC, out);
11223                                 USTPUTC('\\', out);
11224                                 pungetc();
11225                         } else if (c == '\n') {
11226                                 setprompt_if(doprompt, 2);
11227                         } else {
11228 #if ENABLE_ASH_EXPAND_PRMT
11229                                 if (c == '$' && pssyntax) {
11230                                         USTPUTC(CTLESC, out);
11231                                         USTPUTC('\\', out);
11232                                 }
11233 #endif
11234                                 /* Backslash is retained if we are in "str" and next char isn't special */
11235                                 if (dblquote
11236                                  && c != '\\'
11237                                  && c != '`'
11238                                  && c != '$'
11239                                  && (c != '"' || eofmark != NULL)
11240                                 ) {
11241                                         USTPUTC('\\', out);
11242                                 }
11243                                 USTPUTC(CTLESC, out);
11244                                 USTPUTC(c, out);
11245                                 quotef = 1;
11246                         }
11247                         break;
11248                 case CSQUOTE:
11249                         syntax = SQSYNTAX;
11250  quotemark:
11251                         if (eofmark == NULL) {
11252                                 USTPUTC(CTLQUOTEMARK, out);
11253                         }
11254                         break;
11255                 case CDQUOTE:
11256                         syntax = DQSYNTAX;
11257                         dblquote = 1;
11258                         goto quotemark;
11259                 case CENDQUOTE:
11260                         IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
11261                         if (eofmark != NULL && varnest == 0) {
11262                                 USTPUTC(c, out);
11263                         } else {
11264                                 if (dqvarnest == 0) {
11265                                         syntax = BASESYNTAX;
11266                                         dblquote = 0;
11267                                 }
11268                                 quotef = 1;
11269                                 goto quotemark;
11270                         }
11271                         break;
11272                 case CVAR:      /* '$' */
11273                         PARSESUB();             /* parse substitution */
11274                         break;
11275                 case CENDVAR:   /* '}' */
11276                         if (varnest > 0) {
11277                                 varnest--;
11278                                 if (dqvarnest > 0) {
11279                                         dqvarnest--;
11280                                 }
11281                                 c = CTLENDVAR;
11282                         }
11283                         USTPUTC(c, out);
11284                         break;
11285 #if ENABLE_SH_MATH_SUPPORT
11286                 case CLP:       /* '(' in arithmetic */
11287                         parenlevel++;
11288                         USTPUTC(c, out);
11289                         break;
11290                 case CRP:       /* ')' in arithmetic */
11291                         if (parenlevel > 0) {
11292                                 parenlevel--;
11293                         } else {
11294                                 if (pgetc() == ')') {
11295                                         c = CTLENDARI;
11296                                         if (--arinest == 0) {
11297                                                 syntax = prevsyntax;
11298                                         }
11299                                 } else {
11300                                         /*
11301                                          * unbalanced parens
11302                                          * (don't 2nd guess - no error)
11303                                          */
11304                                         pungetc();
11305                                 }
11306                         }
11307                         USTPUTC(c, out);
11308                         break;
11309 #endif
11310                 case CBQUOTE:   /* '`' */
11311                         PARSEBACKQOLD();
11312                         break;
11313                 case CENDFILE:
11314                         goto endword;           /* exit outer loop */
11315                 case CIGN:
11316                         break;
11317                 default:
11318                         if (varnest == 0) {
11319 #if ENABLE_ASH_BASH_COMPAT
11320                                 if (c == '&') {
11321                                         if (pgetc() == '>')
11322                                                 c = 0x100 + '>'; /* flag &> */
11323                                         pungetc();
11324                                 }
11325 #endif
11326                                 goto endword;   /* exit outer loop */
11327                         }
11328                         IF_ASH_ALIAS(if (c != PEOA))
11329                                 USTPUTC(c, out);
11330                 }
11331                 c = pgetc_fast();
11332         } /* for (;;) */
11333  endword:
11334
11335 #if ENABLE_SH_MATH_SUPPORT
11336         if (syntax == ARISYNTAX)
11337                 raise_error_syntax("missing '))'");
11338 #endif
11339         if (syntax != BASESYNTAX && eofmark == NULL)
11340                 raise_error_syntax("unterminated quoted string");
11341         if (varnest != 0) {
11342                 startlinno = g_parsefile->linno;
11343                 /* { */
11344                 raise_error_syntax("missing '}'");
11345         }
11346         USTPUTC('\0', out);
11347         len = out - (char *)stackblock();
11348         out = stackblock();
11349         if (eofmark == NULL) {
11350                 if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>'))
11351                  && quotef == 0
11352                 ) {
11353                         if (isdigit_str9(out)) {
11354                                 PARSEREDIR(); /* passed as params: out, c */
11355                                 lasttoken = TREDIR;
11356                                 return lasttoken;
11357                         }
11358                         /* else: non-number X seen, interpret it
11359                          * as "NNNX>file" = "NNNX >file" */
11360                 }
11361                 pungetc();
11362         }
11363         quoteflag = quotef;
11364         backquotelist = bqlist;
11365         grabstackblock(len);
11366         wordtext = out;
11367         lasttoken = TWORD;
11368         return lasttoken;
11369 /* end of readtoken routine */
11370
11371 /*
11372  * Check to see whether we are at the end of the here document.  When this
11373  * is called, c is set to the first character of the next input line.  If
11374  * we are at the end of the here document, this routine sets the c to PEOF.
11375  */
11376 checkend: {
11377         if (eofmark) {
11378 #if ENABLE_ASH_ALIAS
11379                 if (c == PEOA)
11380                         c = pgetc_without_PEOA();
11381 #endif
11382                 if (striptabs) {
11383                         while (c == '\t') {
11384                                 c = pgetc_without_PEOA();
11385                         }
11386                 }
11387                 if (c == *eofmark) {
11388                         if (pfgets(line, sizeof(line)) != NULL) {
11389                                 char *p, *q;
11390
11391                                 p = line;
11392                                 for (q = eofmark + 1; *q && *p == *q; p++, q++)
11393                                         continue;
11394                                 if (*p == '\n' && *q == '\0') {
11395                                         c = PEOF;
11396                                         g_parsefile->linno++;
11397                                         needprompt = doprompt;
11398                                 } else {
11399                                         pushstring(line, NULL);
11400                                 }
11401                         }
11402                 }
11403         }
11404         goto checkend_return;
11405 }
11406
11407 /*
11408  * Parse a redirection operator.  The variable "out" points to a string
11409  * specifying the fd to be redirected.  The variable "c" contains the
11410  * first character of the redirection operator.
11411  */
11412 parseredir: {
11413         /* out is already checked to be a valid number or "" */
11414         int fd = (*out == '\0' ? -1 : atoi(out));
11415         union node *np;
11416
11417         np = stzalloc(sizeof(struct nfile));
11418         if (c == '>') {
11419                 np->nfile.fd = 1;
11420                 c = pgetc();
11421                 if (c == '>')
11422                         np->type = NAPPEND;
11423                 else if (c == '|')
11424                         np->type = NCLOBBER;
11425                 else if (c == '&')
11426                         np->type = NTOFD;
11427                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11428                 else {
11429                         np->type = NTO;
11430                         pungetc();
11431                 }
11432         }
11433 #if ENABLE_ASH_BASH_COMPAT
11434         else if (c == 0x100 + '>') { /* this flags &> redirection */
11435                 np->nfile.fd = 1;
11436                 pgetc(); /* this is '>', no need to check */
11437                 np->type = NTO2;
11438         }
11439 #endif
11440         else { /* c == '<' */
11441                 /*np->nfile.fd = 0; - stzalloc did it */
11442                 c = pgetc();
11443                 switch (c) {
11444                 case '<':
11445                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11446                                 np = stzalloc(sizeof(struct nhere));
11447                                 /*np->nfile.fd = 0; - stzalloc did it */
11448                         }
11449                         np->type = NHERE;
11450                         heredoc = stzalloc(sizeof(struct heredoc));
11451                         heredoc->here = np;
11452                         c = pgetc();
11453                         if (c == '-') {
11454                                 heredoc->striptabs = 1;
11455                         } else {
11456                                 /*heredoc->striptabs = 0; - stzalloc did it */
11457                                 pungetc();
11458                         }
11459                         break;
11460
11461                 case '&':
11462                         np->type = NFROMFD;
11463                         break;
11464
11465                 case '>':
11466                         np->type = NFROMTO;
11467                         break;
11468
11469                 default:
11470                         np->type = NFROM;
11471                         pungetc();
11472                         break;
11473                 }
11474         }
11475         if (fd >= 0)
11476                 np->nfile.fd = fd;
11477         redirnode = np;
11478         goto parseredir_return;
11479 }
11480
11481 /*
11482  * Parse a substitution.  At this point, we have read the dollar sign
11483  * and nothing else.
11484  */
11485
11486 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11487  * (assuming ascii char codes, as the original implementation did) */
11488 #define is_special(c) \
11489         (((unsigned)(c) - 33 < 32) \
11490                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11491 parsesub: {
11492         unsigned char subtype;
11493         int typeloc;
11494         int flags;
11495
11496         c = pgetc();
11497         if (c > 255 /* PEOA or PEOF */
11498          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11499         ) {
11500 #if ENABLE_ASH_BASH_COMPAT
11501                 if (c == '\'')
11502                         bash_dollar_squote = 1;
11503                 else
11504 #endif
11505                         USTPUTC('$', out);
11506                 pungetc();
11507         } else if (c == '(') {
11508                 /* $(command) or $((arith)) */
11509                 if (pgetc() == '(') {
11510 #if ENABLE_SH_MATH_SUPPORT
11511                         PARSEARITH();
11512 #else
11513                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11514 #endif
11515                 } else {
11516                         pungetc();
11517                         PARSEBACKQNEW();
11518                 }
11519         } else {
11520                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11521                 USTPUTC(CTLVAR, out);
11522                 typeloc = out - (char *)stackblock();
11523                 USTPUTC(VSNORMAL, out);
11524                 subtype = VSNORMAL;
11525                 if (c == '{') {
11526                         c = pgetc();
11527                         if (c == '#') {
11528                                 c = pgetc();
11529                                 if (c == '}')
11530                                         c = '#'; /* ${#} - same as $# */
11531                                 else
11532                                         subtype = VSLENGTH; /* ${#VAR} */
11533                         } else {
11534                                 subtype = 0;
11535                         }
11536                 }
11537                 if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) {
11538                         /* $[{[#]]NAME[}] */
11539                         do {
11540                                 STPUTC(c, out);
11541                                 c = pgetc();
11542                         } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
11543                 } else if (isdigit(c)) {
11544                         /* $[{[#]]NUM[}] */
11545                         do {
11546                                 STPUTC(c, out);
11547                                 c = pgetc();
11548                         } while (isdigit(c));
11549                 } else if (is_special(c)) {
11550                         /* $[{[#]]<specialchar>[}] */
11551                         USTPUTC(c, out);
11552                         c = pgetc();
11553                 } else {
11554  badsub:
11555                         raise_error_syntax("bad substitution");
11556                 }
11557                 if (c != '}' && subtype == VSLENGTH) {
11558                         /* ${#VAR didn't end with } */
11559                         goto badsub;
11560                 }
11561
11562                 STPUTC('=', out);
11563                 flags = 0;
11564                 if (subtype == 0) {
11565                         /* ${VAR...} but not $VAR or ${#VAR} */
11566                         /* c == first char after VAR */
11567                         switch (c) {
11568                         case ':':
11569                                 c = pgetc();
11570 #if ENABLE_ASH_BASH_COMPAT
11571                                 if (c == ':' || c == '$' || isdigit(c)) {
11572 //TODO: support more general format ${v:EXPR:EXPR},
11573 // where EXPR follows $(()) rules
11574                                         subtype = VSSUBSTR;
11575                                         pungetc();
11576                                         break; /* "goto do_pungetc" is bigger (!) */
11577                                 }
11578 #endif
11579                                 flags = VSNUL;
11580                                 /*FALLTHROUGH*/
11581                         default: {
11582                                 static const char types[] ALIGN1 = "}-+?=";
11583                                 const char *p = strchr(types, c);
11584                                 if (p == NULL)
11585                                         goto badsub;
11586                                 subtype = p - types + VSNORMAL;
11587                                 break;
11588                         }
11589                         case '%':
11590                         case '#': {
11591                                 int cc = c;
11592                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11593                                 c = pgetc();
11594                                 if (c != cc)
11595                                         goto do_pungetc;
11596                                 subtype++;
11597                                 break;
11598                         }
11599 #if ENABLE_ASH_BASH_COMPAT
11600                         case '/':
11601                                 /* ${v/[/]pattern/repl} */
11602 //TODO: encode pattern and repl separately.
11603 // Currently ${v/$var_with_slash/repl} is horribly broken
11604                                 subtype = VSREPLACE;
11605                                 c = pgetc();
11606                                 if (c != '/')
11607                                         goto do_pungetc;
11608                                 subtype++; /* VSREPLACEALL */
11609                                 break;
11610 #endif
11611                         }
11612                 } else {
11613  do_pungetc:
11614                         pungetc();
11615                 }
11616                 ((unsigned char *)stackblock())[typeloc] = subtype | flags;
11617                 if (subtype != VSNORMAL) {
11618                         varnest++;
11619                         if (dblquote) {
11620                                 dqvarnest++;
11621                         }
11622                 }
11623         }
11624         goto parsesub_return;
11625 }
11626
11627 /*
11628  * Called to parse command substitutions.  Newstyle is set if the command
11629  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11630  * list of commands (passed by reference), and savelen is the number of
11631  * characters on the top of the stack which must be preserved.
11632  */
11633 parsebackq: {
11634         struct nodelist **nlpp;
11635         union node *n;
11636         char *str;
11637         size_t savelen;
11638         smallint saveprompt = 0;
11639
11640         str = NULL;
11641         savelen = out - (char *)stackblock();
11642         if (savelen > 0) {
11643                 str = alloca(savelen);
11644                 memcpy(str, stackblock(), savelen);
11645         }
11646         if (oldstyle) {
11647                 /* We must read until the closing backquote, giving special
11648                  * treatment to some slashes, and then push the string and
11649                  * reread it as input, interpreting it normally.
11650                  */
11651                 char *pout;
11652                 size_t psavelen;
11653                 char *pstr;
11654
11655                 STARTSTACKSTR(pout);
11656                 for (;;) {
11657                         int pc;
11658
11659                         setprompt_if(needprompt, 2);
11660                         pc = pgetc();
11661                         switch (pc) {
11662                         case '`':
11663                                 goto done;
11664
11665                         case '\\':
11666                                 pc = pgetc();
11667                                 if (pc == '\n') {
11668                                         g_parsefile->linno++;
11669                                         setprompt_if(doprompt, 2);
11670                                         /*
11671                                          * If eating a newline, avoid putting
11672                                          * the newline into the new character
11673                                          * stream (via the STPUTC after the
11674                                          * switch).
11675                                          */
11676                                         continue;
11677                                 }
11678                                 if (pc != '\\' && pc != '`' && pc != '$'
11679                                  && (!dblquote || pc != '"')
11680                                 ) {
11681                                         STPUTC('\\', pout);
11682                                 }
11683                                 if (pc <= 255 /* not PEOA or PEOF */) {
11684                                         break;
11685                                 }
11686                                 /* fall through */
11687
11688                         case PEOF:
11689                         IF_ASH_ALIAS(case PEOA:)
11690                                 startlinno = g_parsefile->linno;
11691                                 raise_error_syntax("EOF in backquote substitution");
11692
11693                         case '\n':
11694                                 g_parsefile->linno++;
11695                                 needprompt = doprompt;
11696                                 break;
11697
11698                         default:
11699                                 break;
11700                         }
11701                         STPUTC(pc, pout);
11702                 }
11703  done:
11704                 STPUTC('\0', pout);
11705                 psavelen = pout - (char *)stackblock();
11706                 if (psavelen > 0) {
11707                         pstr = grabstackstr(pout);
11708                         setinputstring(pstr);
11709                 }
11710         }
11711         nlpp = &bqlist;
11712         while (*nlpp)
11713                 nlpp = &(*nlpp)->next;
11714         *nlpp = stzalloc(sizeof(**nlpp));
11715         /* (*nlpp)->next = NULL; - stzalloc did it */
11716
11717         if (oldstyle) {
11718                 saveprompt = doprompt;
11719                 doprompt = 0;
11720         }
11721
11722         n = list(2);
11723
11724         if (oldstyle)
11725                 doprompt = saveprompt;
11726         else if (readtoken() != TRP)
11727                 raise_error_unexpected_syntax(TRP);
11728
11729         (*nlpp)->n = n;
11730         if (oldstyle) {
11731                 /*
11732                  * Start reading from old file again, ignoring any pushed back
11733                  * tokens left from the backquote parsing
11734                  */
11735                 popfile();
11736                 tokpushback = 0;
11737         }
11738         while (stackblocksize() <= savelen)
11739                 growstackblock();
11740         STARTSTACKSTR(out);
11741         if (str) {
11742                 memcpy(out, str, savelen);
11743                 STADJUST(savelen, out);
11744         }
11745         USTPUTC(CTLBACKQ, out);
11746         if (oldstyle)
11747                 goto parsebackq_oldreturn;
11748         goto parsebackq_newreturn;
11749 }
11750
11751 #if ENABLE_SH_MATH_SUPPORT
11752 /*
11753  * Parse an arithmetic expansion (indicate start of one and set state)
11754  */
11755 parsearith: {
11756         if (++arinest == 1) {
11757                 prevsyntax = syntax;
11758                 syntax = ARISYNTAX;
11759         }
11760         USTPUTC(CTLARI, out);
11761         goto parsearith_return;
11762 }
11763 #endif
11764 } /* end of readtoken */
11765
11766 /*
11767  * Read the next input token.
11768  * If the token is a word, we set backquotelist to the list of cmds in
11769  *      backquotes.  We set quoteflag to true if any part of the word was
11770  *      quoted.
11771  * If the token is TREDIR, then we set redirnode to a structure containing
11772  *      the redirection.
11773  * In all cases, the variable startlinno is set to the number of the line
11774  *      on which the token starts.
11775  *
11776  * [Change comment:  here documents and internal procedures]
11777  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
11778  *  word parsing code into a separate routine.  In this case, readtoken
11779  *  doesn't need to have any internal procedures, but parseword does.
11780  *  We could also make parseoperator in essence the main routine, and
11781  *  have parseword (readtoken1?) handle both words and redirection.]
11782  */
11783 #define NEW_xxreadtoken
11784 #ifdef NEW_xxreadtoken
11785 /* singles must be first! */
11786 static const char xxreadtoken_chars[7] ALIGN1 = {
11787         '\n', '(', ')', /* singles */
11788         '&', '|', ';',  /* doubles */
11789         0
11790 };
11791
11792 #define xxreadtoken_singles 3
11793 #define xxreadtoken_doubles 3
11794
11795 static const char xxreadtoken_tokens[] ALIGN1 = {
11796         TNL, TLP, TRP,          /* only single occurrence allowed */
11797         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11798         TEOF,                   /* corresponds to trailing nul */
11799         TAND, TOR, TENDCASE     /* if double occurrence */
11800 };
11801
11802 static int
11803 xxreadtoken(void)
11804 {
11805         int c;
11806
11807         if (tokpushback) {
11808                 tokpushback = 0;
11809                 return lasttoken;
11810         }
11811         setprompt_if(needprompt, 2);
11812         startlinno = g_parsefile->linno;
11813         for (;;) {                      /* until token or start of word found */
11814                 c = pgetc_fast();
11815                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
11816                         continue;
11817
11818                 if (c == '#') {
11819                         while ((c = pgetc()) != '\n' && c != PEOF)
11820                                 continue;
11821                         pungetc();
11822                 } else if (c == '\\') {
11823                         if (pgetc() != '\n') {
11824                                 pungetc();
11825                                 break; /* return readtoken1(...) */
11826                         }
11827                         startlinno = ++g_parsefile->linno;
11828                         setprompt_if(doprompt, 2);
11829                 } else {
11830                         const char *p;
11831
11832                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11833                         if (c != PEOF) {
11834                                 if (c == '\n') {
11835                                         g_parsefile->linno++;
11836                                         needprompt = doprompt;
11837                                 }
11838
11839                                 p = strchr(xxreadtoken_chars, c);
11840                                 if (p == NULL)
11841                                         break; /* return readtoken1(...) */
11842
11843                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11844                                         int cc = pgetc();
11845                                         if (cc == c) {    /* double occurrence? */
11846                                                 p += xxreadtoken_doubles + 1;
11847                                         } else {
11848                                                 pungetc();
11849 #if ENABLE_ASH_BASH_COMPAT
11850                                                 if (c == '&' && cc == '>') /* &> */
11851                                                         break; /* return readtoken1(...) */
11852 #endif
11853                                         }
11854                                 }
11855                         }
11856                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11857                         return lasttoken;
11858                 }
11859         } /* for (;;) */
11860
11861         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11862 }
11863 #else /* old xxreadtoken */
11864 #define RETURN(token)   return lasttoken = token
11865 static int
11866 xxreadtoken(void)
11867 {
11868         int c;
11869
11870         if (tokpushback) {
11871                 tokpushback = 0;
11872                 return lasttoken;
11873         }
11874         setprompt_if(needprompt, 2);
11875         startlinno = g_parsefile->linno;
11876         for (;;) {      /* until token or start of word found */
11877                 c = pgetc_fast();
11878                 switch (c) {
11879                 case ' ': case '\t':
11880                 IF_ASH_ALIAS(case PEOA:)
11881                         continue;
11882                 case '#':
11883                         while ((c = pgetc()) != '\n' && c != PEOF)
11884                                 continue;
11885                         pungetc();
11886                         continue;
11887                 case '\\':
11888                         if (pgetc() == '\n') {
11889                                 startlinno = ++g_parsefile->linno;
11890                                 setprompt_if(doprompt, 2);
11891                                 continue;
11892                         }
11893                         pungetc();
11894                         goto breakloop;
11895                 case '\n':
11896                         g_parsefile->linno++;
11897                         needprompt = doprompt;
11898                         RETURN(TNL);
11899                 case PEOF:
11900                         RETURN(TEOF);
11901                 case '&':
11902                         if (pgetc() == '&')
11903                                 RETURN(TAND);
11904                         pungetc();
11905                         RETURN(TBACKGND);
11906                 case '|':
11907                         if (pgetc() == '|')
11908                                 RETURN(TOR);
11909                         pungetc();
11910                         RETURN(TPIPE);
11911                 case ';':
11912                         if (pgetc() == ';')
11913                                 RETURN(TENDCASE);
11914                         pungetc();
11915                         RETURN(TSEMI);
11916                 case '(':
11917                         RETURN(TLP);
11918                 case ')':
11919                         RETURN(TRP);
11920                 default:
11921                         goto breakloop;
11922                 }
11923         }
11924  breakloop:
11925         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11926 #undef RETURN
11927 }
11928 #endif /* old xxreadtoken */
11929
11930 static int
11931 readtoken(void)
11932 {
11933         int t;
11934         int kwd = checkkwd;
11935 #if DEBUG
11936         smallint alreadyseen = tokpushback;
11937 #endif
11938
11939 #if ENABLE_ASH_ALIAS
11940  top:
11941 #endif
11942
11943         t = xxreadtoken();
11944
11945         /*
11946          * eat newlines
11947          */
11948         if (kwd & CHKNL) {
11949                 while (t == TNL) {
11950                         parseheredoc();
11951                         t = xxreadtoken();
11952                 }
11953         }
11954
11955         if (t != TWORD || quoteflag) {
11956                 goto out;
11957         }
11958
11959         /*
11960          * check for keywords
11961          */
11962         if (kwd & CHKKWD) {
11963                 const char *const *pp;
11964
11965                 pp = findkwd(wordtext);
11966                 if (pp) {
11967                         lasttoken = t = pp - tokname_array;
11968                         TRACE(("keyword '%s' recognized\n", tokname_array[t] + 1));
11969                         goto out;
11970                 }
11971         }
11972
11973         if (checkkwd & CHKALIAS) {
11974 #if ENABLE_ASH_ALIAS
11975                 struct alias *ap;
11976                 ap = lookupalias(wordtext, 1);
11977                 if (ap != NULL) {
11978                         if (*ap->val) {
11979                                 pushstring(ap->val, ap);
11980                         }
11981                         goto top;
11982                 }
11983 #endif
11984         }
11985  out:
11986         checkkwd = 0;
11987 #if DEBUG
11988         if (!alreadyseen)
11989                 TRACE(("token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : ""));
11990         else
11991                 TRACE(("reread token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : ""));
11992 #endif
11993         return t;
11994 }
11995
11996 static int
11997 peektoken(void)
11998 {
11999         int t;
12000
12001         t = readtoken();
12002         tokpushback = 1;
12003         return t;
12004 }
12005
12006 /*
12007  * Read and parse a command.  Returns NODE_EOF on end of file.
12008  * (NULL is a valid parse tree indicating a blank line.)
12009  */
12010 static union node *
12011 parsecmd(int interact)
12012 {
12013         tokpushback = 0;
12014         checkkwd = 0;
12015         heredoclist = 0;
12016         doprompt = interact;
12017         setprompt_if(doprompt, doprompt);
12018         needprompt = 0;
12019         return list(1);
12020 }
12021
12022 /*
12023  * Input any here documents.
12024  */
12025 static void
12026 parseheredoc(void)
12027 {
12028         struct heredoc *here;
12029         union node *n;
12030
12031         here = heredoclist;
12032         heredoclist = NULL;
12033
12034         while (here) {
12035                 setprompt_if(needprompt, 2);
12036                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12037                                 here->eofmark, here->striptabs);
12038                 n = stzalloc(sizeof(struct narg));
12039                 n->narg.type = NARG;
12040                 /*n->narg.next = NULL; - stzalloc did it */
12041                 n->narg.text = wordtext;
12042                 n->narg.backquote = backquotelist;
12043                 here->here->nhere.doc = n;
12044                 here = here->next;
12045         }
12046 }
12047
12048
12049 /*
12050  * called by editline -- any expansions to the prompt should be added here.
12051  */
12052 #if ENABLE_ASH_EXPAND_PRMT
12053 static const char *
12054 expandstr(const char *ps)
12055 {
12056         union node n;
12057
12058         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12059          * and token processing _can_ alter it (delete NULs etc). */
12060         setinputstring((char *)ps);
12061         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12062         popfile();
12063
12064         n.narg.type = NARG;
12065         n.narg.next = NULL;
12066         n.narg.text = wordtext;
12067         n.narg.backquote = backquotelist;
12068
12069         expandarg(&n, NULL, EXP_QUOTED);
12070         return stackblock();
12071 }
12072 #endif
12073
12074 /*
12075  * Execute a command or commands contained in a string.
12076  */
12077 static int
12078 evalstring(char *s, int mask)
12079 {
12080         union node *n;
12081         struct stackmark smark;
12082         int skip;
12083
12084         setinputstring(s);
12085         setstackmark(&smark);
12086
12087         skip = 0;
12088         while ((n = parsecmd(0)) != NODE_EOF) {
12089                 evaltree(n, 0);
12090                 popstackmark(&smark);
12091                 skip = evalskip;
12092                 if (skip)
12093                         break;
12094         }
12095         popfile();
12096
12097         skip &= mask;
12098         evalskip = skip;
12099         return skip;
12100 }
12101
12102 /*
12103  * The eval command.
12104  */
12105 static int FAST_FUNC
12106 evalcmd(int argc UNUSED_PARAM, char **argv)
12107 {
12108         char *p;
12109         char *concat;
12110
12111         if (argv[1]) {
12112                 p = argv[1];
12113                 argv += 2;
12114                 if (argv[0]) {
12115                         STARTSTACKSTR(concat);
12116                         for (;;) {
12117                                 concat = stack_putstr(p, concat);
12118                                 p = *argv++;
12119                                 if (p == NULL)
12120                                         break;
12121                                 STPUTC(' ', concat);
12122                         }
12123                         STPUTC('\0', concat);
12124                         p = grabstackstr(concat);
12125                 }
12126                 evalstring(p, ~SKIPEVAL);
12127         }
12128         return exitstatus;
12129 }
12130
12131 /*
12132  * Read and execute commands.
12133  * "Top" is nonzero for the top level command loop;
12134  * it turns on prompting if the shell is interactive.
12135  */
12136 static int
12137 cmdloop(int top)
12138 {
12139         union node *n;
12140         struct stackmark smark;
12141         int inter;
12142         int numeof = 0;
12143
12144         TRACE(("cmdloop(%d) called\n", top));
12145         for (;;) {
12146                 int skip;
12147
12148                 setstackmark(&smark);
12149 #if JOBS
12150                 if (doing_jobctl)
12151                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12152 #endif
12153                 inter = 0;
12154                 if (iflag && top) {
12155                         inter++;
12156                         chkmail();
12157                 }
12158                 n = parsecmd(inter);
12159 #if DEBUG
12160                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12161                         showtree(n);
12162 #endif
12163                 if (n == NODE_EOF) {
12164                         if (!top || numeof >= 50)
12165                                 break;
12166                         if (!stoppedjobs()) {
12167                                 if (!Iflag)
12168                                         break;
12169                                 out2str("\nUse \"exit\" to leave shell.\n");
12170                         }
12171                         numeof++;
12172                 } else if (nflag == 0) {
12173                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12174                         job_warning >>= 1;
12175                         numeof = 0;
12176                         evaltree(n, 0);
12177                 }
12178                 popstackmark(&smark);
12179                 skip = evalskip;
12180
12181                 if (skip) {
12182                         evalskip = 0;
12183                         return skip & SKIPEVAL;
12184                 }
12185         }
12186         return 0;
12187 }
12188
12189 /*
12190  * Take commands from a file.  To be compatible we should do a path
12191  * search for the file, which is necessary to find sub-commands.
12192  */
12193 static char *
12194 find_dot_file(char *name)
12195 {
12196         char *fullname;
12197         const char *path = pathval();
12198         struct stat statb;
12199
12200         /* don't try this for absolute or relative paths */
12201         if (strchr(name, '/'))
12202                 return name;
12203
12204         /* IIRC standards do not say whether . is to be searched.
12205          * And it is even smaller this way, making it unconditional for now:
12206          */
12207         if (1) { /* ENABLE_ASH_BASH_COMPAT */
12208                 fullname = name;
12209                 goto try_cur_dir;
12210         }
12211
12212         while ((fullname = path_advance(&path, name)) != NULL) {
12213  try_cur_dir:
12214                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12215                         /*
12216                          * Don't bother freeing here, since it will
12217                          * be freed by the caller.
12218                          */
12219                         return fullname;
12220                 }
12221                 if (fullname != name)
12222                         stunalloc(fullname);
12223         }
12224
12225         /* not found in the PATH */
12226         ash_msg_and_raise_error("%s: not found", name);
12227         /* NOTREACHED */
12228 }
12229
12230 static int FAST_FUNC
12231 dotcmd(int argc, char **argv)
12232 {
12233         char *fullname;
12234         struct strlist *sp;
12235         volatile struct shparam saveparam;
12236
12237         for (sp = cmdenviron; sp; sp = sp->next)
12238                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12239
12240         if (!argv[1]) {
12241                 /* bash says: "bash: .: filename argument required" */
12242                 return 2; /* bash compat */
12243         }
12244
12245         /* "false; . empty_file; echo $?" should print 0, not 1: */
12246         exitstatus = 0;
12247
12248         /* This aborts if file isn't found, which is POSIXly correct.
12249          * bash returns exitcode 1 instead.
12250          */
12251         fullname = find_dot_file(argv[1]);
12252         argv += 2;
12253         argc -= 2;
12254         if (argc) { /* argc > 0, argv[0] != NULL */
12255                 saveparam = shellparam;
12256                 shellparam.malloced = 0;
12257                 shellparam.nparam = argc;
12258                 shellparam.p = argv;
12259         };
12260
12261         /* This aborts if file can't be opened, which is POSIXly correct.
12262          * bash returns exitcode 1 instead.
12263          */
12264         setinputfile(fullname, INPUT_PUSH_FILE);
12265         commandname = fullname;
12266         cmdloop(0);
12267         popfile();
12268
12269         if (argc) {
12270                 freeparam(&shellparam);
12271                 shellparam = saveparam;
12272         };
12273
12274         return exitstatus;
12275 }
12276
12277 static int FAST_FUNC
12278 exitcmd(int argc UNUSED_PARAM, char **argv)
12279 {
12280         if (stoppedjobs())
12281                 return 0;
12282         if (argv[1])
12283                 exitstatus = number(argv[1]);
12284         raise_exception(EXEXIT);
12285         /* NOTREACHED */
12286 }
12287
12288 /*
12289  * Read a file containing shell functions.
12290  */
12291 static void
12292 readcmdfile(char *name)
12293 {
12294         setinputfile(name, INPUT_PUSH_FILE);
12295         cmdloop(0);
12296         popfile();
12297 }
12298
12299
12300 /* ============ find_command inplementation */
12301
12302 /*
12303  * Resolve a command name.  If you change this routine, you may have to
12304  * change the shellexec routine as well.
12305  */
12306 static void
12307 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12308 {
12309         struct tblentry *cmdp;
12310         int idx;
12311         int prev;
12312         char *fullname;
12313         struct stat statb;
12314         int e;
12315         int updatetbl;
12316         struct builtincmd *bcmd;
12317
12318         /* If name contains a slash, don't use PATH or hash table */
12319         if (strchr(name, '/') != NULL) {
12320                 entry->u.index = -1;
12321                 if (act & DO_ABS) {
12322                         while (stat(name, &statb) < 0) {
12323 #ifdef SYSV
12324                                 if (errno == EINTR)
12325                                         continue;
12326 #endif
12327                                 entry->cmdtype = CMDUNKNOWN;
12328                                 return;
12329                         }
12330                 }
12331                 entry->cmdtype = CMDNORMAL;
12332                 return;
12333         }
12334
12335 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12336
12337         updatetbl = (path == pathval());
12338         if (!updatetbl) {
12339                 act |= DO_ALTPATH;
12340                 if (strstr(path, "%builtin") != NULL)
12341                         act |= DO_ALTBLTIN;
12342         }
12343
12344         /* If name is in the table, check answer will be ok */
12345         cmdp = cmdlookup(name, 0);
12346         if (cmdp != NULL) {
12347                 int bit;
12348
12349                 switch (cmdp->cmdtype) {
12350                 default:
12351 #if DEBUG
12352                         abort();
12353 #endif
12354                 case CMDNORMAL:
12355                         bit = DO_ALTPATH;
12356                         break;
12357                 case CMDFUNCTION:
12358                         bit = DO_NOFUNC;
12359                         break;
12360                 case CMDBUILTIN:
12361                         bit = DO_ALTBLTIN;
12362                         break;
12363                 }
12364                 if (act & bit) {
12365                         updatetbl = 0;
12366                         cmdp = NULL;
12367                 } else if (cmdp->rehash == 0)
12368                         /* if not invalidated by cd, we're done */
12369                         goto success;
12370         }
12371
12372         /* If %builtin not in path, check for builtin next */
12373         bcmd = find_builtin(name);
12374         if (bcmd) {
12375                 if (IS_BUILTIN_REGULAR(bcmd))
12376                         goto builtin_success;
12377                 if (act & DO_ALTPATH) {
12378                         if (!(act & DO_ALTBLTIN))
12379                                 goto builtin_success;
12380                 } else if (builtinloc <= 0) {
12381                         goto builtin_success;
12382                 }
12383         }
12384
12385 #if ENABLE_FEATURE_SH_STANDALONE
12386         {
12387                 int applet_no = find_applet_by_name(name);
12388                 if (applet_no >= 0) {
12389                         entry->cmdtype = CMDNORMAL;
12390                         entry->u.index = -2 - applet_no;
12391                         return;
12392                 }
12393         }
12394 #endif
12395
12396         /* We have to search path. */
12397         prev = -1;              /* where to start */
12398         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12399                 if (cmdp->cmdtype == CMDBUILTIN)
12400                         prev = builtinloc;
12401                 else
12402                         prev = cmdp->param.index;
12403         }
12404
12405         e = ENOENT;
12406         idx = -1;
12407  loop:
12408         while ((fullname = path_advance(&path, name)) != NULL) {
12409                 stunalloc(fullname);
12410                 /* NB: code below will still use fullname
12411                  * despite it being "unallocated" */
12412                 idx++;
12413                 if (pathopt) {
12414                         if (prefix(pathopt, "builtin")) {
12415                                 if (bcmd)
12416                                         goto builtin_success;
12417                                 continue;
12418                         }
12419                         if ((act & DO_NOFUNC)
12420                          || !prefix(pathopt, "func")
12421                         ) {     /* ignore unimplemented options */
12422                                 continue;
12423                         }
12424                 }
12425                 /* if rehash, don't redo absolute path names */
12426                 if (fullname[0] == '/' && idx <= prev) {
12427                         if (idx < prev)
12428                                 continue;
12429                         TRACE(("searchexec \"%s\": no change\n", name));
12430                         goto success;
12431                 }
12432                 while (stat(fullname, &statb) < 0) {
12433 #ifdef SYSV
12434                         if (errno == EINTR)
12435                                 continue;
12436 #endif
12437                         if (errno != ENOENT && errno != ENOTDIR)
12438                                 e = errno;
12439                         goto loop;
12440                 }
12441                 e = EACCES;     /* if we fail, this will be the error */
12442                 if (!S_ISREG(statb.st_mode))
12443                         continue;
12444                 if (pathopt) {          /* this is a %func directory */
12445                         stalloc(strlen(fullname) + 1);
12446                         /* NB: stalloc will return space pointed by fullname
12447                          * (because we don't have any intervening allocations
12448                          * between stunalloc above and this stalloc) */
12449                         readcmdfile(fullname);
12450                         cmdp = cmdlookup(name, 0);
12451                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12452                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12453                         stunalloc(fullname);
12454                         goto success;
12455                 }
12456                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12457                 if (!updatetbl) {
12458                         entry->cmdtype = CMDNORMAL;
12459                         entry->u.index = idx;
12460                         return;
12461                 }
12462                 INT_OFF;
12463                 cmdp = cmdlookup(name, 1);
12464                 cmdp->cmdtype = CMDNORMAL;
12465                 cmdp->param.index = idx;
12466                 INT_ON;
12467                 goto success;
12468         }
12469
12470         /* We failed.  If there was an entry for this command, delete it */
12471         if (cmdp && updatetbl)
12472                 delete_cmd_entry();
12473         if (act & DO_ERR)
12474                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12475         entry->cmdtype = CMDUNKNOWN;
12476         return;
12477
12478  builtin_success:
12479         if (!updatetbl) {
12480                 entry->cmdtype = CMDBUILTIN;
12481                 entry->u.cmd = bcmd;
12482                 return;
12483         }
12484         INT_OFF;
12485         cmdp = cmdlookup(name, 1);
12486         cmdp->cmdtype = CMDBUILTIN;
12487         cmdp->param.cmd = bcmd;
12488         INT_ON;
12489  success:
12490         cmdp->rehash = 0;
12491         entry->cmdtype = cmdp->cmdtype;
12492         entry->u = cmdp->param;
12493 }
12494
12495
12496 /* ============ trap.c */
12497
12498 /*
12499  * The trap builtin.
12500  */
12501 static int FAST_FUNC
12502 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12503 {
12504         char *action;
12505         char **ap;
12506         int signo, exitcode;
12507
12508         nextopt(nullstr);
12509         ap = argptr;
12510         if (!*ap) {
12511                 for (signo = 0; signo < NSIG; signo++) {
12512                         char *tr = trap_ptr[signo];
12513                         if (tr) {
12514                                 /* note: bash adds "SIG", but only if invoked
12515                                  * as "bash". If called as "sh", or if set -o posix,
12516                                  * then it prints short signal names.
12517                                  * We are printing short names: */
12518                                 out1fmt("trap -- %s %s\n",
12519                                                 single_quote(tr),
12520                                                 get_signame(signo));
12521                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12522                  * In this case, we will exit very soon, no need to free(). */
12523                                 /* if (trap_ptr != trap && tp[0]) */
12524                                 /*      free(tr); */
12525                         }
12526                 }
12527                 /*
12528                 if (trap_ptr != trap) {
12529                         free(trap_ptr);
12530                         trap_ptr = trap;
12531                 }
12532                 */
12533                 return 0;
12534         }
12535
12536         action = NULL;
12537         if (ap[1])
12538                 action = *ap++;
12539         exitcode = 0;
12540         while (*ap) {
12541                 signo = get_signum(*ap);
12542                 if (signo < 0) {
12543                         /* Mimic bash message exactly */
12544                         ash_msg("%s: invalid signal specification", *ap);
12545                         exitcode = 1;
12546                         goto next;
12547                 }
12548                 INT_OFF;
12549                 if (action) {
12550                         if (LONE_DASH(action))
12551                                 action = NULL;
12552                         else
12553                                 action = ckstrdup(action);
12554                 }
12555                 free(trap[signo]);
12556                 if (action)
12557                         may_have_traps = 1;
12558                 trap[signo] = action;
12559                 if (signo != 0)
12560                         setsignal(signo);
12561                 INT_ON;
12562  next:
12563                 ap++;
12564         }
12565         return exitcode;
12566 }
12567
12568
12569 /* ============ Builtins */
12570
12571 #if ENABLE_ASH_HELP
12572 static int FAST_FUNC
12573 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12574 {
12575         unsigned col;
12576         unsigned i;
12577
12578         out1fmt(
12579                 "Built-in commands:\n"
12580                 "------------------\n");
12581         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12582                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12583                                         builtintab[i].name + 1);
12584                 if (col > 60) {
12585                         out1fmt("\n");
12586                         col = 0;
12587                 }
12588         }
12589 # if ENABLE_FEATURE_SH_STANDALONE
12590         {
12591                 const char *a = applet_names;
12592                 while (*a) {
12593                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12594                         if (col > 60) {
12595                                 out1fmt("\n");
12596                                 col = 0;
12597                         }
12598                         a += strlen(a) + 1;
12599                 }
12600         }
12601 # endif
12602         out1fmt("\n\n");
12603         return EXIT_SUCCESS;
12604 }
12605 #endif
12606
12607 #if MAX_HISTORY
12608 static int FAST_FUNC
12609 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12610 {
12611         show_history(line_input_state);
12612         return EXIT_SUCCESS;
12613 }
12614 #endif
12615
12616 /*
12617  * The export and readonly commands.
12618  */
12619 static int FAST_FUNC
12620 exportcmd(int argc UNUSED_PARAM, char **argv)
12621 {
12622         struct var *vp;
12623         char *name;
12624         const char *p;
12625         char **aptr;
12626         char opt;
12627         int flag;
12628         int flag_off;
12629
12630         /* "readonly" in bash accepts, but ignores -n.
12631          * We do the same: it saves a conditional in nextopt's param.
12632          */
12633         flag_off = 0;
12634         while ((opt = nextopt("np")) != '\0') {
12635                 if (opt == 'n')
12636                         flag_off = VEXPORT;
12637         }
12638         flag = VEXPORT;
12639         if (argv[0][0] == 'r') {
12640                 flag = VREADONLY;
12641                 flag_off = 0; /* readonly ignores -n */
12642         }
12643         flag_off = ~flag_off;
12644
12645         /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
12646         {
12647                 aptr = argptr;
12648                 name = *aptr;
12649                 if (name) {
12650                         do {
12651                                 p = strchr(name, '=');
12652                                 if (p != NULL) {
12653                                         p++;
12654                                 } else {
12655                                         vp = *findvar(hashvar(name), name);
12656                                         if (vp) {
12657                                                 vp->flags = ((vp->flags | flag) & flag_off);
12658                                                 continue;
12659                                         }
12660                                 }
12661                                 setvar(name, p, (flag & flag_off));
12662                         } while ((name = *++aptr) != NULL);
12663                         return 0;
12664                 }
12665         }
12666
12667         /* No arguments. Show the list of exported or readonly vars.
12668          * -n is ignored.
12669          */
12670         showvars(argv[0], flag, 0);
12671         return 0;
12672 }
12673
12674 /*
12675  * Delete a function if it exists.
12676  */
12677 static void
12678 unsetfunc(const char *name)
12679 {
12680         struct tblentry *cmdp;
12681
12682         cmdp = cmdlookup(name, 0);
12683         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
12684                 delete_cmd_entry();
12685 }
12686
12687 /*
12688  * The unset builtin command.  We unset the function before we unset the
12689  * variable to allow a function to be unset when there is a readonly variable
12690  * with the same name.
12691  */
12692 static int FAST_FUNC
12693 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12694 {
12695         char **ap;
12696         int i;
12697         int flag = 0;
12698         int ret = 0;
12699
12700         while ((i = nextopt("vf")) != 0) {
12701                 flag = i;
12702         }
12703
12704         for (ap = argptr; *ap; ap++) {
12705                 if (flag != 'f') {
12706                         i = unsetvar(*ap);
12707                         ret |= i;
12708                         if (!(i & 2))
12709                                 continue;
12710                 }
12711                 if (flag != 'v')
12712                         unsetfunc(*ap);
12713         }
12714         return ret & 1;
12715 }
12716
12717 static const unsigned char timescmd_str[] ALIGN1 = {
12718         ' ',  offsetof(struct tms, tms_utime),
12719         '\n', offsetof(struct tms, tms_stime),
12720         ' ',  offsetof(struct tms, tms_cutime),
12721         '\n', offsetof(struct tms, tms_cstime),
12722         0
12723 };
12724 static int FAST_FUNC
12725 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12726 {
12727         unsigned long clk_tck, s, t;
12728         const unsigned char *p;
12729         struct tms buf;
12730
12731         clk_tck = bb_clk_tck();
12732         times(&buf);
12733
12734         p = timescmd_str;
12735         do {
12736                 t = *(clock_t *)(((char *) &buf) + p[1]);
12737                 s = t / clk_tck;
12738                 t = t % clk_tck;
12739                 out1fmt("%lum%lu.%03lus%c",
12740                         s / 60, s % 60,
12741                         (t * 1000) / clk_tck,
12742                         p[0]);
12743                 p += 2;
12744         } while (*p);
12745
12746         return 0;
12747 }
12748
12749 #if ENABLE_SH_MATH_SUPPORT
12750 /*
12751  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
12752  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12753  *
12754  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12755  */
12756 static int FAST_FUNC
12757 letcmd(int argc UNUSED_PARAM, char **argv)
12758 {
12759         arith_t i;
12760
12761         argv++;
12762         if (!*argv)
12763                 ash_msg_and_raise_error("expression expected");
12764         do {
12765                 i = ash_arith(*argv);
12766         } while (*++argv);
12767
12768         return !i;
12769 }
12770 #endif
12771
12772 /*
12773  * The read builtin. Options:
12774  *      -r              Do not interpret '\' specially
12775  *      -s              Turn off echo (tty only)
12776  *      -n NCHARS       Read NCHARS max
12777  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
12778  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
12779  *      -u FD           Read from given FD instead of fd 0
12780  * This uses unbuffered input, which may be avoidable in some cases.
12781  * TODO: bash also has:
12782  *      -a ARRAY        Read into array[0],[1],etc
12783  *      -d DELIM        End on DELIM char, not newline
12784  *      -e              Use line editing (tty only)
12785  */
12786 static int FAST_FUNC
12787 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12788 {
12789         char *opt_n = NULL;
12790         char *opt_p = NULL;
12791         char *opt_t = NULL;
12792         char *opt_u = NULL;
12793         int read_flags = 0;
12794         const char *r;
12795         int i;
12796
12797         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
12798                 switch (i) {
12799                 case 'p':
12800                         opt_p = optionarg;
12801                         break;
12802                 case 'n':
12803                         opt_n = optionarg;
12804                         break;
12805                 case 's':
12806                         read_flags |= BUILTIN_READ_SILENT;
12807                         break;
12808                 case 't':
12809                         opt_t = optionarg;
12810                         break;
12811                 case 'r':
12812                         read_flags |= BUILTIN_READ_RAW;
12813                         break;
12814                 case 'u':
12815                         opt_u = optionarg;
12816                         break;
12817                 default:
12818                         break;
12819                 }
12820         }
12821
12822         /* "read -s" needs to save/restore termios, can't allow ^C
12823          * to jump out of it.
12824          */
12825         INT_OFF;
12826         r = shell_builtin_read(setvar0,
12827                 argptr,
12828                 bltinlookup("IFS"), /* can be NULL */
12829                 read_flags,
12830                 opt_n,
12831                 opt_p,
12832                 opt_t,
12833                 opt_u
12834         );
12835         INT_ON;
12836
12837         if ((uintptr_t)r > 1)
12838                 ash_msg_and_raise_error(r);
12839
12840         return (uintptr_t)r;
12841 }
12842
12843 static int FAST_FUNC
12844 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12845 {
12846         static const char permuser[3] ALIGN1 = "ogu";
12847
12848         mode_t mask;
12849         int symbolic_mode = 0;
12850
12851         while (nextopt("S") != '\0') {
12852                 symbolic_mode = 1;
12853         }
12854
12855         INT_OFF;
12856         mask = umask(0);
12857         umask(mask);
12858         INT_ON;
12859
12860         if (*argptr == NULL) {
12861                 if (symbolic_mode) {
12862                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
12863                         char *p = buf;
12864                         int i;
12865
12866                         i = 2;
12867                         for (;;) {
12868                                 *p++ = ',';
12869                                 *p++ = permuser[i];
12870                                 *p++ = '=';
12871                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
12872                                 if (!(mask & 0400)) *p++ = 'r';
12873                                 if (!(mask & 0200)) *p++ = 'w';
12874                                 if (!(mask & 0100)) *p++ = 'x';
12875                                 mask <<= 3;
12876                                 if (--i < 0)
12877                                         break;
12878                         }
12879                         *p = '\0';
12880                         puts(buf + 1);
12881                 } else {
12882                         out1fmt("%04o\n", mask);
12883                 }
12884         } else {
12885                 char *modestr = *argptr;
12886                 /* numeric umasks are taken as-is */
12887                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
12888                 if (!isdigit(modestr[0]))
12889                         mask ^= 0777;
12890                 mask = bb_parse_mode(modestr, mask);
12891                 if ((unsigned)mask > 0777) {
12892                         ash_msg_and_raise_error("illegal mode: %s", modestr);
12893                 }
12894                 if (!isdigit(modestr[0]))
12895                         mask ^= 0777;
12896                 umask(mask);
12897         }
12898         return 0;
12899 }
12900
12901 static int FAST_FUNC
12902 ulimitcmd(int argc UNUSED_PARAM, char **argv)
12903 {
12904         return shell_builtin_ulimit(argv);
12905 }
12906
12907 /* ============ main() and helpers */
12908
12909 /*
12910  * Called to exit the shell.
12911  */
12912 static void
12913 exitshell(void)
12914 {
12915         struct jmploc loc;
12916         char *p;
12917         int status;
12918
12919 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
12920         save_history(line_input_state);
12921 #endif
12922
12923         status = exitstatus;
12924         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12925         if (setjmp(loc.loc)) {
12926                 if (exception_type == EXEXIT)
12927 /* dash bug: it just does _exit(exitstatus) here
12928  * but we have to do setjobctl(0) first!
12929  * (bug is still not fixed in dash-0.5.3 - if you run dash
12930  * under Midnight Commander, on exit from dash MC is backgrounded) */
12931                         status = exitstatus;
12932                 goto out;
12933         }
12934         exception_handler = &loc;
12935         p = trap[0];
12936         if (p) {
12937                 trap[0] = NULL;
12938                 evalstring(p, 0);
12939                 free(p);
12940         }
12941         flush_stdout_stderr();
12942  out:
12943         setjobctl(0);
12944         _exit(status);
12945         /* NOTREACHED */
12946 }
12947
12948 static void
12949 init(void)
12950 {
12951         /* from input.c: */
12952         /* we will never free this */
12953         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
12954
12955         /* from trap.c: */
12956         signal(SIGCHLD, SIG_DFL);
12957         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
12958          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
12959          */
12960         signal(SIGHUP, SIG_DFL);
12961
12962         /* from var.c: */
12963         {
12964                 char **envp;
12965                 const char *p;
12966                 struct stat st1, st2;
12967
12968                 initvar();
12969                 for (envp = environ; envp && *envp; envp++) {
12970                         if (strchr(*envp, '=')) {
12971                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
12972                         }
12973                 }
12974
12975                 setvar0("PPID", utoa(getppid()));
12976 #if ENABLE_ASH_BASH_COMPAT
12977                 p = lookupvar("SHLVL");
12978                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
12979                 if (!lookupvar("HOSTNAME")) {
12980                         struct utsname uts;
12981                         uname(&uts);
12982                         setvar0("HOSTNAME", uts.nodename);
12983                 }
12984 #endif
12985                 p = lookupvar("PWD");
12986                 if (p) {
12987                         if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12988                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
12989                         ) {
12990                                 p = '\0';
12991                         }
12992                 }
12993                 setpwd(p, 0);
12994         }
12995 }
12996
12997
12998 //usage:#define ash_trivial_usage
12999 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13000 //usage:#define ash_full_usage "\n\n"
13001 //usage:        "Unix shell interpreter"
13002
13003 //usage:#if ENABLE_FEATURE_SH_IS_ASH
13004 //usage:# define sh_trivial_usage ash_trivial_usage
13005 //usage:# define sh_full_usage    ash_full_usage
13006 //usage:#endif
13007 //usage:#if ENABLE_FEATURE_BASH_IS_ASH
13008 //usage:# define bash_trivial_usage ash_trivial_usage
13009 //usage:# define bash_full_usage    ash_full_usage
13010 //usage:#endif
13011
13012 /*
13013  * Process the shell command line arguments.
13014  */
13015 static void
13016 procargs(char **argv)
13017 {
13018         int i;
13019         const char *xminusc;
13020         char **xargv;
13021
13022         xargv = argv;
13023         arg0 = xargv[0];
13024         /* if (xargv[0]) - mmm, this is always true! */
13025                 xargv++;
13026         for (i = 0; i < NOPTS; i++)
13027                 optlist[i] = 2;
13028         argptr = xargv;
13029         if (options(/*cmdline:*/ 1)) {
13030                 /* it already printed err message */
13031                 raise_exception(EXERROR);
13032         }
13033         xargv = argptr;
13034         xminusc = minusc;
13035         if (*xargv == NULL) {
13036                 if (xminusc)
13037                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13038                 sflag = 1;
13039         }
13040         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13041                 iflag = 1;
13042         if (mflag == 2)
13043                 mflag = iflag;
13044         for (i = 0; i < NOPTS; i++)
13045                 if (optlist[i] == 2)
13046                         optlist[i] = 0;
13047 #if DEBUG == 2
13048         debug = 1;
13049 #endif
13050         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13051         if (xminusc) {
13052                 minusc = *xargv++;
13053                 if (*xargv)
13054                         goto setarg0;
13055         } else if (!sflag) {
13056                 setinputfile(*xargv, 0);
13057  setarg0:
13058                 arg0 = *xargv++;
13059                 commandname = arg0;
13060         }
13061
13062         shellparam.p = xargv;
13063 #if ENABLE_ASH_GETOPTS
13064         shellparam.optind = 1;
13065         shellparam.optoff = -1;
13066 #endif
13067         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13068         while (*xargv) {
13069                 shellparam.nparam++;
13070                 xargv++;
13071         }
13072         optschanged();
13073 }
13074
13075 /*
13076  * Read /etc/profile or .profile.
13077  */
13078 static void
13079 read_profile(const char *name)
13080 {
13081         int skip;
13082
13083         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13084                 return;
13085         skip = cmdloop(0);
13086         popfile();
13087         if (skip)
13088                 exitshell();
13089 }
13090
13091 /*
13092  * This routine is called when an error or an interrupt occurs in an
13093  * interactive shell and control is returned to the main command loop.
13094  */
13095 static void
13096 reset(void)
13097 {
13098         /* from eval.c: */
13099         evalskip = 0;
13100         loopnest = 0;
13101         /* from input.c: */
13102         g_parsefile->left_in_buffer = 0;
13103         g_parsefile->left_in_line = 0;      /* clear input buffer */
13104         popallfiles();
13105         /* from parser.c: */
13106         tokpushback = 0;
13107         checkkwd = 0;
13108         /* from redir.c: */
13109         clearredir(/*drop:*/ 0);
13110 }
13111
13112 #if PROFILE
13113 static short profile_buf[16384];
13114 extern int etext();
13115 #endif
13116
13117 /*
13118  * Main routine.  We initialize things, parse the arguments, execute
13119  * profiles if we're a login shell, and then call cmdloop to execute
13120  * commands.  The setjmp call sets up the location to jump to when an
13121  * exception occurs.  When an exception occurs the variable "state"
13122  * is used to figure out how far we had gotten.
13123  */
13124 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13125 int ash_main(int argc UNUSED_PARAM, char **argv)
13126 {
13127         const char *shinit;
13128         volatile smallint state;
13129         struct jmploc jmploc;
13130         struct stackmark smark;
13131
13132         /* Initialize global data */
13133         INIT_G_misc();
13134         INIT_G_memstack();
13135         INIT_G_var();
13136 #if ENABLE_ASH_ALIAS
13137         INIT_G_alias();
13138 #endif
13139         INIT_G_cmdtable();
13140
13141 #if PROFILE
13142         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13143 #endif
13144
13145 #if ENABLE_FEATURE_EDITING
13146         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13147 #endif
13148         state = 0;
13149         if (setjmp(jmploc.loc)) {
13150                 smallint e;
13151                 smallint s;
13152
13153                 reset();
13154
13155                 e = exception_type;
13156                 if (e == EXERROR)
13157                         exitstatus = 2;
13158                 s = state;
13159                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13160                         exitshell();
13161                 }
13162                 if (e == EXINT) {
13163                         newline_and_flush(stderr);
13164                 }
13165
13166                 popstackmark(&smark);
13167                 FORCE_INT_ON; /* enable interrupts */
13168                 if (s == 1)
13169                         goto state1;
13170                 if (s == 2)
13171                         goto state2;
13172                 if (s == 3)
13173                         goto state3;
13174                 goto state4;
13175         }
13176         exception_handler = &jmploc;
13177 #if DEBUG
13178         opentrace();
13179         TRACE(("Shell args: "));
13180         trace_puts_args(argv);
13181 #endif
13182         rootpid = getpid();
13183
13184         init();
13185         setstackmark(&smark);
13186         procargs(argv);
13187
13188         if (argv[0] && argv[0][0] == '-')
13189                 isloginsh = 1;
13190         if (isloginsh) {
13191                 const char *hp;
13192
13193                 state = 1;
13194                 read_profile("/etc/profile");
13195  state1:
13196                 state = 2;
13197                 hp = lookupvar("HOME");
13198                 if (hp) {
13199                         hp = concat_path_file(hp, ".profile");
13200                         read_profile(hp);
13201                         free((char*)hp);
13202                 }
13203         }
13204  state2:
13205         state = 3;
13206         if (
13207 #ifndef linux
13208          getuid() == geteuid() && getgid() == getegid() &&
13209 #endif
13210          iflag
13211         ) {
13212                 shinit = lookupvar("ENV");
13213                 if (shinit != NULL && *shinit != '\0') {
13214                         read_profile(shinit);
13215                 }
13216         }
13217  state3:
13218         state = 4;
13219         if (minusc) {
13220                 /* evalstring pushes parsefile stack.
13221                  * Ensure we don't falsely claim that 0 (stdin)
13222                  * is one of stacked source fds.
13223                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13224                 // if (!sflag) g_parsefile->pf_fd = -1;
13225                 // ^^ not necessary since now we special-case fd 0
13226                 // in is_hidden_fd() to not be considered "hidden fd"
13227                 evalstring(minusc, 0);
13228         }
13229
13230         if (sflag || minusc == NULL) {
13231 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13232                 if (iflag) {
13233                         const char *hp = lookupvar("HISTFILE");
13234                         if (!hp) {
13235                                 hp = lookupvar("HOME");
13236                                 if (hp) {
13237                                         hp = concat_path_file(hp, ".ash_history");
13238                                         setvar0("HISTFILE", hp);
13239                                         free((char*)hp);
13240                                         hp = lookupvar("HISTFILE");
13241                                 }
13242                         }
13243                         if (hp)
13244                                 line_input_state->hist_file = hp;
13245 # if ENABLE_FEATURE_SH_HISTFILESIZE
13246                         hp = lookupvar("HISTFILESIZE");
13247                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13248 # endif
13249                 }
13250 #endif
13251  state4: /* XXX ??? - why isn't this before the "if" statement */
13252                 cmdloop(1);
13253         }
13254 #if PROFILE
13255         monitor(0);
13256 #endif
13257 #ifdef GPROF
13258         {
13259                 extern void _mcleanup(void);
13260                 _mcleanup();
13261         }
13262 #endif
13263         TRACE(("End of main reached\n"));
13264         exitshell();
13265         /* NOTREACHED */
13266 }
13267
13268
13269 /*-
13270  * Copyright (c) 1989, 1991, 1993, 1994
13271  *      The Regents of the University of California.  All rights reserved.
13272  *
13273  * This code is derived from software contributed to Berkeley by
13274  * Kenneth Almquist.
13275  *
13276  * Redistribution and use in source and binary forms, with or without
13277  * modification, are permitted provided that the following conditions
13278  * are met:
13279  * 1. Redistributions of source code must retain the above copyright
13280  *    notice, this list of conditions and the following disclaimer.
13281  * 2. Redistributions in binary form must reproduce the above copyright
13282  *    notice, this list of conditions and the following disclaimer in the
13283  *    documentation and/or other materials provided with the distribution.
13284  * 3. Neither the name of the University nor the names of its contributors
13285  *    may be used to endorse or promote products derived from this software
13286  *    without specific prior written permission.
13287  *
13288  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13289  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13290  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13291  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13292  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13293  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13294  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13295  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13296  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13297  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13298  * SUCH DAMAGE.
13299  */