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