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