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