1/*	$OpenBSD: exec.c,v 1.49 2009/01/29 23:27:26 jaredy Exp $	*/
2
3/*-
4 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5 *		 2011, 2012, 2013
6 *	Thorsten Glaser <tg@mirbsd.org>
7 *
8 * Provided that these terms and disclaimer and all copyright notices
9 * are retained or reproduced in an accompanying document, permission
10 * is granted to deal in this work without restriction, including un-
11 * limited rights to use, publicly perform, distribute, sell, modify,
12 * merge, give away, or sublicence.
13 *
14 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
15 * the utmost extent permitted by applicable law, neither express nor
16 * implied; without malicious intent or gross negligence. In no event
17 * may a licensor, author or contributor be held liable for indirect,
18 * direct, other damage, loss, or other issues arising in any way out
19 * of dealing in the work, even if advised of the possibility of such
20 * damage or existence of a defect, except proven that it results out
21 * of said person's immediate fault when using the work as intended.
22 */
23
24#include "sh.h"
25
26__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.116 2013/02/17 05:40:15 tg Exp $");
27
28#ifndef MKSH_DEFAULT_EXECSHELL
29#define MKSH_DEFAULT_EXECSHELL	"/bin/sh"
30#endif
31
32static int comexec(struct op *, struct tbl * volatile, const char **,
33    int volatile, volatile int *);
34static void scriptexec(struct op *, const char **) MKSH_A_NORETURN;
35static int call_builtin(struct tbl *, const char **, const char *);
36static int iosetup(struct ioword *, struct tbl *);
37static int herein(struct ioword *, char **);
38static const char *do_selectargs(const char **, bool);
39static Test_op dbteste_isa(Test_env *, Test_meta);
40static const char *dbteste_getopnd(Test_env *, Test_op, bool);
41static void dbteste_error(Test_env *, int, const char *);
42static int search_access(const char *, int);
43/* XXX: horrible kludge to fit within the framework */
44static char *plain_fmt_entry(char *, size_t, unsigned int, const void *);
45static char *select_fmt_entry(char *, size_t, unsigned int, const void *);
46
47/*
48 * execute command tree
49 */
50int
51execute(struct op * volatile t,
52    /* if XEXEC don't fork */
53    volatile int flags,
54    volatile int * volatile xerrok)
55{
56	int i;
57	volatile int rv = 0, dummy = 0;
58	int pv[2];
59	const char ** volatile ap = NULL;
60	char ** volatile up;
61	const char *s, *ccp;
62	struct ioword **iowp;
63	struct tbl *tp = NULL;
64	char *cp;
65
66	if (t == NULL)
67		return (0);
68
69	/* Caller doesn't care if XERROK should propagate. */
70	if (xerrok == NULL)
71		xerrok = &dummy;
72
73	if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE)
74		/* run in sub-process */
75		return (exchild(t, flags & ~XTIME, xerrok, -1));
76
77	newenv(E_EXEC);
78	if (trap)
79		runtraps(0);
80
81	/* we want to run an executable, do some variance checks */
82	if (t->type == TCOM) {
83		/* check if this is 'var=<<EOF' */
84		if (
85		    /* we have zero arguments, i.e. no programme to run */
86		    t->args[0] == NULL &&
87		    /* we have exactly one variable assignment */
88		    t->vars[0] != NULL && t->vars[1] == NULL &&
89		    /* we have exactly one I/O redirection */
90		    t->ioact != NULL && t->ioact[0] != NULL &&
91		    t->ioact[1] == NULL &&
92		    /* of type "here document" (or "here string") */
93		    (t->ioact[0]->flag & IOTYPE) == IOHERE &&
94		    /* the variable assignment begins with a valid varname */
95		    (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
96		    /* and has no right-hand side (i.e. "varname=") */
97		    ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS &&
98		    /* plus we can have a here document content */
99		    herein(t->ioact[0], &cp) == 0 && cp && *cp) {
100			char *sp = cp, *dp;
101			size_t n = ccp - t->vars[0] + 2, z;
102
103			/* drop redirection (will be garbage collected) */
104			t->ioact = NULL;
105
106			/* set variable to its expanded value */
107			z = strlen(cp) + 1;
108			if (notoktomul(z, 2) || notoktoadd(z * 2, n))
109				internal_errorf(Toomem, (unsigned long)-1);
110			dp = alloc(z * 2 + n, ATEMP);
111			memcpy(dp, t->vars[0], n);
112			t->vars[0] = dp;
113			dp += n;
114			while (*sp) {
115				*dp++ = QCHAR;
116				*dp++ = *sp++;
117			}
118			*dp = EOS;
119			/* free the expanded value */
120			afree(cp, APERM);
121		}
122
123		/*
124		 * Clear subst_exstat before argument expansion. Used by
125		 * null commands (see comexec() and c_eval()) and by c_set().
126		 */
127		subst_exstat = 0;
128
129		/* for $LINENO */
130		current_lineno = t->lineno;
131
132		/*
133		 * POSIX says expand command words first, then redirections,
134		 * and assignments last..
135		 */
136		up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE);
137		if (flags & XTIME)
138			/* Allow option parsing (bizarre, but POSIX) */
139			timex_hook(t, &up);
140		ap = (const char **)up;
141		if (Flag(FXTRACE) && ap[0]) {
142			shf_puts(substitute(str_val(global("PS4")), 0),
143			    shl_out);
144			for (i = 0; ap[i]; i++)
145				shf_fprintf(shl_out, "%s%c", ap[i],
146				    ap[i + 1] ? ' ' : '\n');
147			shf_flush(shl_out);
148		}
149		if (ap[0])
150			tp = findcom(ap[0], FC_BI|FC_FUNC);
151	}
152	flags &= ~XTIME;
153
154	if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) {
155		e->savefd = alloc2(NUFILE, sizeof(short), ATEMP);
156		/* initialise to not redirected */
157		memset(e->savefd, 0, NUFILE * sizeof(short));
158	}
159
160	/* mark for replacement later (unless TPIPE) */
161	vp_pipest->flag |= INT_L;
162
163	/* do redirection, to be restored in quitenv() */
164	if (t->ioact != NULL)
165		for (iowp = t->ioact; *iowp != NULL; iowp++) {
166			if (iosetup(*iowp, tp) < 0) {
167				exstat = rv = 1;
168				/*
169				 * Redirection failures for special commands
170				 * cause (non-interactive) shell to exit.
171				 */
172				if (tp && tp->type == CSHELL &&
173				    (tp->flag & SPEC_BI))
174					errorfz();
175				/* Deal with FERREXIT, quitenv(), etc. */
176				goto Break;
177			}
178		}
179
180	switch (t->type) {
181	case TCOM:
182		rv = comexec(t, tp, (const char **)ap, flags, xerrok);
183		break;
184
185	case TPAREN:
186		rv = execute(t->left, flags | XFORK, xerrok);
187		break;
188
189	case TPIPE:
190		flags |= XFORK;
191		flags &= ~XEXEC;
192		e->savefd[0] = savefd(0);
193		e->savefd[1] = savefd(1);
194		while (t->type == TPIPE) {
195			openpipe(pv);
196			/* stdout of curr */
197			ksh_dup2(pv[1], 1, false);
198			/**
199			 * Let exchild() close pv[0] in child
200			 * (if this isn't done, commands like
201			 *	(: ; cat /etc/termcap) | sleep 1
202			 * will hang forever).
203			 */
204			exchild(t->left, flags | XPIPEO | XCCLOSE,
205			    NULL, pv[0]);
206			/* stdin of next */
207			ksh_dup2(pv[0], 0, false);
208			closepipe(pv);
209			flags |= XPIPEI;
210			t = t->right;
211		}
212		/* stdout of last */
213		restfd(1, e->savefd[1]);
214		/* no need to re-restore this */
215		e->savefd[1] = 0;
216		/* Let exchild() close 0 in parent, after fork, before wait */
217		i = exchild(t, flags | XPCLOSE | XPIPEST, xerrok, 0);
218		if (!(flags&XBGND) && !(flags&XXCOM))
219			rv = i;
220		break;
221
222	case TLIST:
223		while (t->type == TLIST) {
224			execute(t->left, flags & XERROK, NULL);
225			t = t->right;
226		}
227		rv = execute(t, flags & XERROK, xerrok);
228		break;
229
230	case TCOPROC: {
231#ifndef MKSH_NOPROSPECTOFWORK
232		sigset_t omask;
233
234		/*
235		 * Block sigchild as we are using things changed in the
236		 * signal handler
237		 */
238		sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
239		e->type = E_ERRH;
240		if ((i = kshsetjmp(e->jbuf))) {
241			sigprocmask(SIG_SETMASK, &omask, NULL);
242			quitenv(NULL);
243			unwind(i);
244			/* NOTREACHED */
245		}
246#endif
247		/* Already have a (live) co-process? */
248		if (coproc.job && coproc.write >= 0)
249			errorf("coprocess already exists");
250
251		/* Can we re-use the existing co-process pipe? */
252		coproc_cleanup(true);
253
254		/* do this before opening pipes, in case these fail */
255		e->savefd[0] = savefd(0);
256		e->savefd[1] = savefd(1);
257
258		openpipe(pv);
259		if (pv[0] != 0) {
260			ksh_dup2(pv[0], 0, false);
261			close(pv[0]);
262		}
263		coproc.write = pv[1];
264		coproc.job = NULL;
265
266		if (coproc.readw >= 0)
267			ksh_dup2(coproc.readw, 1, false);
268		else {
269			openpipe(pv);
270			coproc.read = pv[0];
271			ksh_dup2(pv[1], 1, false);
272			/* closed before first read */
273			coproc.readw = pv[1];
274			coproc.njobs = 0;
275			/* create new coprocess id */
276			++coproc.id;
277		}
278#ifndef MKSH_NOPROSPECTOFWORK
279		sigprocmask(SIG_SETMASK, &omask, NULL);
280		/* no more need for error handler */
281		e->type = E_EXEC;
282#endif
283
284		/*
285		 * exchild() closes coproc.* in child after fork,
286		 * will also increment coproc.njobs when the
287		 * job is actually created.
288		 */
289		flags &= ~XEXEC;
290		exchild(t->left, flags | XBGND | XFORK | XCOPROC | XCCLOSE,
291		    NULL, coproc.readw);
292		break;
293	}
294
295	case TASYNC:
296		/*
297		 * XXX non-optimal, I think - "(foo &)", forks for (),
298		 * forks again for async... parent should optimise
299		 * this to "foo &"...
300		 */
301		rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok);
302		break;
303
304	case TOR:
305	case TAND:
306		rv = execute(t->left, XERROK, xerrok);
307		if ((rv == 0) == (t->type == TAND))
308			rv = execute(t->right, XERROK, xerrok);
309		flags |= XERROK;
310		if (xerrok)
311			*xerrok = 1;
312		break;
313
314	case TBANG:
315		rv = !execute(t->right, XERROK, xerrok);
316		flags |= XERROK;
317		if (xerrok)
318			*xerrok = 1;
319		break;
320
321	case TDBRACKET: {
322		Test_env te;
323
324		te.flags = TEF_DBRACKET;
325		te.pos.wp = t->args;
326		te.isa = dbteste_isa;
327		te.getopnd = dbteste_getopnd;
328		te.eval = test_eval;
329		te.error = dbteste_error;
330
331		rv = test_parse(&te);
332		break;
333	}
334
335	case TFOR:
336	case TSELECT: {
337		volatile bool is_first = true;
338		ap = (t->vars == NULL) ? e->loc->argv + 1 :
339		    (const char **)eval((const char **)t->vars,
340		    DOBLANK | DOGLOB | DOTILDE);
341		e->type = E_LOOP;
342		while ((i = kshsetjmp(e->jbuf))) {
343			if ((e->flags&EF_BRKCONT_PASS) ||
344			    (i != LBREAK && i != LCONTIN)) {
345				quitenv(NULL);
346				unwind(i);
347			} else if (i == LBREAK) {
348				rv = 0;
349				goto Break;
350			}
351		}
352		/* in case of a continue */
353		rv = 0;
354		if (t->type == TFOR) {
355			while (*ap != NULL) {
356				setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
357				rv = execute(t->left, flags & XERROK, xerrok);
358			}
359		} else {
360			/* TSELECT */
361			for (;;) {
362				if (!(ccp = do_selectargs(ap, is_first))) {
363					rv = 1;
364					break;
365				}
366				is_first = false;
367				setstr(global(t->str), ccp, KSH_UNWIND_ERROR);
368				execute(t->left, flags & XERROK, xerrok);
369			}
370		}
371		break;
372	}
373
374	case TWHILE:
375	case TUNTIL:
376		e->type = E_LOOP;
377		while ((i = kshsetjmp(e->jbuf))) {
378			if ((e->flags&EF_BRKCONT_PASS) ||
379			    (i != LBREAK && i != LCONTIN)) {
380				quitenv(NULL);
381				unwind(i);
382			} else if (i == LBREAK) {
383				rv = 0;
384				goto Break;
385			}
386		}
387		/* in case of a continue */
388		rv = 0;
389		while ((execute(t->left, XERROK, NULL) == 0) ==
390		    (t->type == TWHILE))
391			rv = execute(t->right, flags & XERROK, xerrok);
392		break;
393
394	case TIF:
395	case TELIF:
396		if (t->right == NULL)
397			/* should be error */
398			break;
399		rv = execute(t->left, XERROK, NULL) == 0 ?
400		    execute(t->right->left, flags & XERROK, xerrok) :
401		    execute(t->right->right, flags & XERROK, xerrok);
402		break;
403
404	case TCASE:
405		i = 0;
406		ccp = evalstr(t->str, DOTILDE);
407		for (t = t->left; t != NULL && t->type == TPAT; t = t->right) {
408			for (ap = (const char **)t->vars; *ap; ap++) {
409				if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
410				    gmatchx(ccp, s, false))) {
411					rv = execute(t->left, flags & XERROK,
412					    xerrok);
413					i = 0;
414					switch (t->u.charflag) {
415					case '&':
416						i = 1;
417						/* FALLTHROUGH */
418					case '|':
419						goto TCASE_next;
420					}
421					goto TCASE_out;
422				}
423			}
424			i = 0;
425 TCASE_next:
426			/* empty */;
427		}
428 TCASE_out:
429		break;
430
431	case TBRACE:
432		rv = execute(t->left, flags & XERROK, xerrok);
433		break;
434
435	case TFUNCT:
436		rv = define(t->str, t);
437		break;
438
439	case TTIME:
440		/*
441		 * Clear XEXEC so nested execute() call doesn't exit
442		 * (allows "ls -l | time grep foo").
443		 */
444		rv = timex(t, flags & ~XEXEC, xerrok);
445		break;
446
447	case TEXEC:
448		/* an eval'd TCOM */
449		s = t->args[0];
450		up = makenv();
451		restoresigs();
452		cleanup_proc_env();
453		{
454			union mksh_ccphack cargs;
455
456			cargs.ro = t->args;
457			execve(t->str, cargs.rw, up);
458			rv = errno;
459		}
460		if (rv == ENOEXEC)
461			scriptexec(t, (const char **)up);
462		else
463			errorf("%s: %s", s, cstrerror(rv));
464	}
465 Break:
466	exstat = rv & 0xFF;
467	if (vp_pipest->flag & INT_L) {
468		unset(vp_pipest, 1);
469		vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY |
470		    ARRAY | INT_U;
471		vp_pipest->val.i = rv;
472	}
473
474	/* restores IO */
475	quitenv(NULL);
476	if ((flags&XEXEC))
477		/* exit child */
478		unwind(LEXIT);
479	if (rv != 0 && !(flags & XERROK) &&
480	    (xerrok == NULL || !*xerrok)) {
481		if (Flag(FERREXIT) & 0x80) {
482			/* inside eval */
483			Flag(FERREXIT) = 0;
484		} else {
485			trapsig(ksh_SIGERR);
486			if (Flag(FERREXIT))
487				unwind(LERROR);
488		}
489	}
490	return (rv);
491}
492
493/*
494 * execute simple command
495 */
496
497static int
498comexec(struct op *t, struct tbl * volatile tp, const char **ap,
499    volatile int flags, volatile int *xerrok)
500{
501	int i;
502	volatile int rv = 0;
503	const char *cp;
504	const char **lastp;
505	/* Must be static (XXX but why?) */
506	static struct op texec;
507	int type_flags;
508	bool keepasn_ok;
509	int fcflags = FC_BI|FC_FUNC|FC_PATH;
510	bool bourne_function_call = false;
511	struct block *l_expand, *l_assign;
512
513	/*
514	 * snag the last argument for $_ XXX not the same as AT&T ksh,
515	 * which only seems to set $_ after a newline (but not in
516	 * functions/dot scripts, but in interactive and script) -
517	 * perhaps save last arg here and set it in shell()?.
518	 */
519	if (Flag(FTALKING) && *(lastp = ap)) {
520		while (*++lastp)
521			;
522		/* setstr() can't fail here */
523		setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp,
524		    KSH_RETURN_ERROR);
525	}
526
527	/**
528	 * Deal with the shell builtins builtin, exec and command since
529	 * they can be followed by other commands. This must be done before
530	 * we know if we should create a local block which must be done
531	 * before we can do a path search (in case the assignments change
532	 * PATH).
533	 * Odd cases:
534	 *	FOO=bar exec >/dev/null		FOO is kept but not exported
535	 *	FOO=bar exec foobar		FOO is exported
536	 *	FOO=bar command exec >/dev/null	FOO is neither kept nor exported
537	 *	FOO=bar command			FOO is neither kept nor exported
538	 *	PATH=... foobar			use new PATH in foobar search
539	 */
540	keepasn_ok = true;
541	while (tp && tp->type == CSHELL) {
542		/* undo effects of command */
543		fcflags = FC_BI|FC_FUNC|FC_PATH;
544		if (tp->val.f == c_builtin) {
545			if ((cp = *++ap) == NULL ||
546			    (!strcmp(cp, "--") && (cp = *++ap) == NULL)) {
547				tp = NULL;
548				break;
549			}
550			if ((tp = findcom(cp, FC_BI)) == NULL)
551				errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin");
552			continue;
553		} else if (tp->val.f == c_exec) {
554			if (ap[1] == NULL)
555				break;
556			ap++;
557			flags |= XEXEC;
558		} else if (tp->val.f == c_command) {
559			int optc, saw_p = 0;
560
561			/*
562			 * Ugly dealing with options in two places (here
563			 * and in c_command(), but such is life)
564			 */
565			ksh_getopt_reset(&builtin_opt, 0);
566			while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p')
567				saw_p = 1;
568			if (optc != EOF)
569				/* command -vV or something */
570				break;
571			/* don't look for functions */
572			fcflags = FC_BI|FC_PATH;
573			if (saw_p) {
574				if (Flag(FRESTRICTED)) {
575					warningf(true, "%s: %s",
576					    "command -p", "restricted");
577					rv = 1;
578					goto Leave;
579				}
580				fcflags |= FC_DEFPATH;
581			}
582			ap += builtin_opt.optind;
583			/*
584			 * POSIX says special builtins lose their status
585			 * if accessed using command.
586			 */
587			keepasn_ok = false;
588			if (!ap[0]) {
589				/* ensure command with no args exits with 0 */
590				subst_exstat = 0;
591				break;
592			}
593#ifndef MKSH_NO_EXTERNAL_CAT
594		} else if (tp->val.f == c_cat) {
595			/*
596			 * if we have any flags, do not use the builtin
597			 * in theory, we could allow -u, but that would
598			 * mean to use ksh_getopt here and possibly ad-
599			 * ded complexity and more code and isn't worth
600			 * additional hassle (and the builtin must call
601			 * ksh_getopt already but can't come back here)
602			 */
603			if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
604			    /* argument, begins with -, is not - or -- */
605			    (ap[1][1] != '-' || ap[1][2] != '\0'))
606				/* don't look for builtins or functions */
607				fcflags = FC_PATH;
608			else
609				/* go on, use the builtin */
610				break;
611#endif
612#if !defined(MKSH_SMALL)
613		} else if (tp->val.f == c_trap) {
614			t->u.evalflags &= ~DOTCOMEXEC;
615			break;
616#endif
617		} else
618			break;
619		tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
620	}
621#if !defined(MKSH_SMALL)
622	if (t->u.evalflags & DOTCOMEXEC)
623		flags |= XEXEC;
624#endif
625	l_expand = e->loc;
626	if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
627		type_flags = 0;
628	else {
629		/* create new variable/function block */
630		newblock();
631		/* ksh functions don't keep assignments, POSIX functions do. */
632		if (keepasn_ok && tp && tp->type == CFUNC &&
633		    !(tp->flag & FKSH)) {
634			bourne_function_call = true;
635			type_flags = EXPORT;
636		} else
637			type_flags = LOCAL|LOCAL_COPY|EXPORT;
638	}
639	l_assign = e->loc;
640	if (Flag(FEXPORT))
641		type_flags |= EXPORT;
642	for (i = 0; t->vars[i]; i++) {
643		/* do NOT lookup in the new var/fn block just created */
644		e->loc = l_expand;
645		cp = evalstr(t->vars[i], DOASNTILDE);
646		e->loc = l_assign;
647		/* but assign in there as usual */
648
649		if (Flag(FXTRACE)) {
650			if (i == 0)
651				shf_puts(substitute(str_val(global("PS4")), 0),
652				    shl_out);
653			shf_fprintf(shl_out, "%s%c", cp,
654			    t->vars[i + 1] ? ' ' : '\n');
655			if (!t->vars[i + 1])
656				shf_flush(shl_out);
657		}
658		typeset(cp, type_flags, 0, 0, 0);
659		if (bourne_function_call && !(type_flags & EXPORT))
660			typeset(cp, LOCAL|LOCAL_COPY|EXPORT, 0, 0, 0);
661	}
662
663	if ((cp = *ap) == NULL) {
664		rv = subst_exstat;
665		goto Leave;
666	} else if (!tp) {
667		if (Flag(FRESTRICTED) && vstrchr(cp, '/')) {
668			warningf(true, "%s: %s", cp, "restricted");
669			rv = 1;
670			goto Leave;
671		}
672		tp = findcom(cp, fcflags);
673	}
674
675	switch (tp->type) {
676
677	/* shell built-in */
678	case CSHELL:
679		rv = call_builtin(tp, (const char **)ap, null);
680		if (!keepasn_ok && tp->val.f == c_shift) {
681			l_expand->argc = l_assign->argc;
682			l_expand->argv = l_assign->argv;
683		}
684		break;
685
686	/* function call */
687	case CFUNC: {
688		volatile unsigned char old_xflag;
689		volatile uint32_t old_inuse;
690		const char * volatile old_kshname;
691
692		if (!(tp->flag & ISSET)) {
693			struct tbl *ftp;
694
695			if (!tp->u.fpath) {
696				rv = (tp->u2.errnov == ENOENT) ? 127 : 126;
697				warningf(true, "%s: %s %s: %s", cp,
698				    "can't find", "function definition file",
699				    cstrerror(tp->u2.errnov));
700				break;
701			}
702			if (include(tp->u.fpath, 0, NULL, false) < 0) {
703				rv = errno;
704				warningf(true, "%s: %s %s %s: %s", cp,
705				    "can't open", "function definition file",
706				    tp->u.fpath, cstrerror(rv));
707				rv = 127;
708				break;
709			}
710			if (!(ftp = findfunc(cp, hash(cp), false)) ||
711			    !(ftp->flag & ISSET)) {
712				warningf(true, "%s: %s %s", cp,
713				    "function not defined by", tp->u.fpath);
714				rv = 127;
715				break;
716			}
717			tp = ftp;
718		}
719
720		/*
721		 * ksh functions set $0 to function name, POSIX
722		 * functions leave $0 unchanged.
723		 */
724		old_kshname = kshname;
725		if (tp->flag & FKSH)
726			kshname = ap[0];
727		else
728			ap[0] = kshname;
729		e->loc->argv = ap;
730		for (i = 0; *ap++ != NULL; i++)
731			;
732		e->loc->argc = i - 1;
733		/*
734		 * ksh-style functions handle getopts sanely,
735		 * Bourne/POSIX functions are insane...
736		 */
737		if (tp->flag & FKSH) {
738			e->loc->flags |= BF_DOGETOPTS;
739			e->loc->getopts_state = user_opt;
740			getopts_reset(1);
741		}
742
743		old_xflag = Flag(FXTRACE);
744		Flag(FXTRACE) |= tp->flag & TRACE ? 1 : 0;
745
746		old_inuse = tp->flag & FINUSE;
747		tp->flag |= FINUSE;
748
749		e->type = E_FUNC;
750		if (!(i = kshsetjmp(e->jbuf))) {
751			execute(tp->val.t, flags & XERROK, NULL);
752			i = LRETURN;
753		}
754		kshname = old_kshname;
755		Flag(FXTRACE) = old_xflag;
756		tp->flag = (tp->flag & ~FINUSE) | old_inuse;
757		/*
758		 * Were we deleted while executing? If so, free the
759		 * execution tree. TODO: Unfortunately, the table entry
760		 * is never re-used until the lookup table is expanded.
761		 */
762		if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
763			if (tp->flag & ALLOC) {
764				tp->flag &= ~ALLOC;
765				tfree(tp->val.t, tp->areap);
766			}
767			tp->flag = 0;
768		}
769		switch (i) {
770		case LRETURN:
771		case LERROR:
772			rv = exstat & 0xFF;
773			break;
774		case LINTR:
775		case LEXIT:
776		case LLEAVE:
777		case LSHELL:
778			quitenv(NULL);
779			unwind(i);
780			/* NOTREACHED */
781		default:
782			quitenv(NULL);
783			internal_errorf("%s %d", "CFUNC", i);
784		}
785		break;
786	}
787
788	/* executable command */
789	case CEXEC:
790	/* tracked alias */
791	case CTALIAS:
792		if (!(tp->flag&ISSET)) {
793			if (tp->u2.errnov == ENOENT) {
794				rv = 127;
795				warningf(true, "%s: %s", cp, "not found");
796			} else {
797				rv = 126;
798				warningf(true, "%s: %s: %s", cp, "can't execute",
799				    cstrerror(tp->u2.errnov));
800			}
801			break;
802		}
803
804		/* set $_ to programme's full path */
805		/* setstr() can't fail here */
806		setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0),
807		    tp->val.s, KSH_RETURN_ERROR);
808
809		if (flags&XEXEC) {
810			j_exit();
811			if (!(flags&XBGND)
812#ifndef MKSH_UNEMPLOYED
813			    || Flag(FMONITOR)
814#endif
815			    ) {
816				setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG);
817				setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG);
818			}
819		}
820
821		/* to fork we set up a TEXEC node and call execute */
822		texec.type = TEXEC;
823		/* for tprint */
824		texec.left = t;
825		texec.str = tp->val.s;
826		texec.args = ap;
827		rv = exchild(&texec, flags, xerrok, -1);
828		break;
829	}
830 Leave:
831	if (flags & XEXEC) {
832		exstat = rv & 0xFF;
833		unwind(LLEAVE);
834	}
835	return (rv);
836}
837
838static void
839scriptexec(struct op *tp, const char **ap)
840{
841	const char *sh;
842#ifndef MKSH_SMALL
843	unsigned char *cp;
844	/* 64 == MAXINTERP in MirBSD <sys/param.h> */
845	char buf[64];
846	int fd;
847#endif
848	union mksh_ccphack args, cap;
849
850	sh = str_val(global("EXECSHELL"));
851	if (sh && *sh)
852		sh = search_path(sh, path, X_OK, NULL);
853	if (!sh || !*sh)
854		sh = MKSH_DEFAULT_EXECSHELL;
855
856	*tp->args-- = tp->str;
857
858#ifndef MKSH_SMALL
859	if ((fd = open(tp->str, O_RDONLY)) >= 0) {
860		/* read first MAXINTERP octets from file */
861		if (read(fd, buf, sizeof(buf)) <= 0)
862			/* read error -> no good */
863			buf[0] = '\0';
864		close(fd);
865
866		/* skip UTF-8 Byte Order Mark, if present */
867		cp = (unsigned char *)buf;
868		if ((cp[0] == 0xEF) && (cp[1] == 0xBB) && (cp[2] == 0xBF))
869			cp += 3;
870		/* save begin of shebang for later */
871		fd = (char *)cp - buf;		/* either 0 or (if BOM) 3 */
872
873		/* scan for newline (or CR) or NUL _before_ end of buffer */
874		while ((char *)cp < (buf + sizeof(buf)))
875			if (*cp == '\0' || *cp == '\n' || *cp == '\r') {
876				*cp = '\0';
877				break;
878			} else
879				++cp;
880		/* if the shebang line is longer than MAXINTERP, bail out */
881		if ((char *)cp >= (buf + sizeof(buf)))
882			goto noshebang;
883
884		/* restore begin of shebang position (buf+0 or buf+3) */
885		cp = (unsigned char *)(buf + fd);
886		/* bail out if read error (above) or no shebang */
887		if ((cp[0] != '#') || (cp[1] != '!'))
888			goto noshebang;
889
890		cp += 2;
891		/* skip whitespace before shell name */
892		while (*cp == ' ' || *cp == '\t')
893			++cp;
894		/* just whitespace on the line? */
895		if (*cp == '\0')
896			goto noshebang;
897		/* no, we actually found an interpreter name */
898		sh = (char *)cp;
899		/* look for end of shell/interpreter name */
900		while (*cp != ' ' && *cp != '\t' && *cp != '\0')
901			++cp;
902		/* any arguments? */
903		if (*cp) {
904			*cp++ = '\0';
905			/* skip spaces before arguments */
906			while (*cp == ' ' || *cp == '\t')
907				++cp;
908			/* pass it all in ONE argument (historic reasons) */
909			if (*cp)
910				*tp->args-- = (char *)cp;
911		}
912 noshebang:
913		fd = buf[0] << 8 | buf[1];
914		if ((fd == /* OMAGIC */ 0407) ||
915		    (fd == /* NMAGIC */ 0410) ||
916		    (fd == /* ZMAGIC */ 0413) ||
917		    (fd == /* QMAGIC */ 0314) ||
918		    (fd == /* ECOFF_I386 */ 0x4C01) ||
919		    (fd == /* ECOFF_M68K */ 0x0150 || fd == 0x5001) ||
920		    (fd == /* ECOFF_SH */   0x0500 || fd == 0x0005) ||
921		    (fd == 0x7F45 && buf[2] == 'L' && buf[3] == 'F') ||
922		    (fd == /* "MZ" */ 0x4D5A) ||
923		    (fd == /* gzip */ 0x1F8B))
924			errorf("%s: not executable: magic %04X", tp->str, fd);
925	}
926#endif
927	args.ro = tp->args;
928	*args.ro = sh;
929
930	cap.ro = ap;
931	execve(args.rw[0], args.rw, cap.rw);
932
933	/* report both the programme that was run and the bogus interpreter */
934	errorf("%s: %s: %s", tp->str, sh, cstrerror(errno));
935}
936
937int
938shcomexec(const char **wp)
939{
940	struct tbl *tp;
941
942	tp = ktsearch(&builtins, *wp, hash(*wp));
943	return (call_builtin(tp, wp, "shcomexec"));
944}
945
946/*
947 * Search function tables for a function. If create set, a table entry
948 * is created if none is found.
949 */
950struct tbl *
951findfunc(const char *name, uint32_t h, bool create)
952{
953	struct block *l;
954	struct tbl *tp = NULL;
955
956	for (l = e->loc; l; l = l->next) {
957		tp = ktsearch(&l->funs, name, h);
958		if (tp)
959			break;
960		if (!l->next && create) {
961			tp = ktenter(&l->funs, name, h);
962			tp->flag = DEFINED;
963			tp->type = CFUNC;
964			tp->val.t = NULL;
965			break;
966		}
967	}
968	return (tp);
969}
970
971/*
972 * define function. Returns 1 if function is being undefined (t == 0) and
973 * function did not exist, returns 0 otherwise.
974 */
975int
976define(const char *name, struct op *t)
977{
978	uint32_t nhash;
979	struct tbl *tp;
980	bool was_set = false;
981
982	nhash = hash(name);
983
984	if (t != NULL && !tobool(t->u.ksh_func)) {
985		/* drop same-name aliases for POSIX functions */
986		if ((tp = ktsearch(&aliases, name, nhash)))
987			ktdelete(tp);
988	}
989
990	while (/* CONSTCOND */ 1) {
991		tp = findfunc(name, nhash, true);
992		/* because findfunc:create=true */
993		mkssert(tp != NULL);
994
995		if (tp->flag & ISSET)
996			was_set = true;
997		/*
998		 * If this function is currently being executed, we zap
999		 * this table entry so findfunc() won't see it
1000		 */
1001		if (tp->flag & FINUSE) {
1002			tp->name[0] = '\0';
1003			/* ensure it won't be found */
1004			tp->flag &= ~DEFINED;
1005			tp->flag |= FDELETE;
1006		} else
1007			break;
1008	}
1009
1010	if (tp->flag & ALLOC) {
1011		tp->flag &= ~(ISSET|ALLOC);
1012		tfree(tp->val.t, tp->areap);
1013	}
1014
1015	if (t == NULL) {
1016		/* undefine */
1017		ktdelete(tp);
1018		return (was_set ? 0 : 1);
1019	}
1020
1021	tp->val.t = tcopy(t->left, tp->areap);
1022	tp->flag |= (ISSET|ALLOC);
1023	if (t->u.ksh_func)
1024		tp->flag |= FKSH;
1025
1026	return (0);
1027}
1028
1029/*
1030 * add builtin
1031 */
1032const char *
1033builtin(const char *name, int (*func) (const char **))
1034{
1035	struct tbl *tp;
1036	uint32_t flag;
1037
1038	/* see if any flags should be set for this builtin */
1039	for (flag = 0; ; name++) {
1040		if (*name == '=')
1041			/* command does variable assignment */
1042			flag |= KEEPASN;
1043		else if (*name == '*')
1044			/* POSIX special builtin */
1045			flag |= SPEC_BI;
1046		else if (*name == '+')
1047			/* POSIX regular builtin */
1048			flag |= REG_BI;
1049		else
1050			break;
1051	}
1052
1053	tp = ktenter(&builtins, name, hash(name));
1054	tp->flag = DEFINED | flag;
1055	tp->type = CSHELL;
1056	tp->val.f = func;
1057
1058	return (name);
1059}
1060
1061/*
1062 * find command
1063 * either function, hashed command, or built-in (in that order)
1064 */
1065struct tbl *
1066findcom(const char *name, int flags)
1067{
1068	static struct tbl temp;
1069	uint32_t h = hash(name);
1070	struct tbl *tp = NULL, *tbi;
1071	/* insert if not found */
1072	unsigned char insert = Flag(FTRACKALL);
1073	/* for function autoloading */
1074	char *fpath;
1075	union mksh_cchack npath;
1076
1077	if (vstrchr(name, '/')) {
1078		insert = 0;
1079		/* prevent FPATH search below */
1080		flags &= ~FC_FUNC;
1081		goto Search;
1082	}
1083	tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL;
1084	/*
1085	 * POSIX says special builtins first, then functions, then
1086	 * POSIX regular builtins, then search path...
1087	 */
1088	if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI))
1089		tp = tbi;
1090	if (!tp && (flags & FC_FUNC)) {
1091		tp = findfunc(name, h, false);
1092		if (tp && !(tp->flag & ISSET)) {
1093			if ((fpath = str_val(global("FPATH"))) == null) {
1094				tp->u.fpath = NULL;
1095				tp->u2.errnov = ENOENT;
1096			} else
1097				tp->u.fpath = search_path(name, fpath, R_OK,
1098				    &tp->u2.errnov);
1099		}
1100	}
1101	if (!tp && (flags & FC_REGBI) && tbi && (tbi->flag & REG_BI))
1102		tp = tbi;
1103	if (!tp && (flags & FC_UNREGBI) && tbi)
1104		tp = tbi;
1105	if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) {
1106		tp = ktsearch(&taliases, name, h);
1107		if (tp && (tp->flag & ISSET) &&
1108		    ksh_access(tp->val.s, X_OK) != 0) {
1109			if (tp->flag & ALLOC) {
1110				tp->flag &= ~ALLOC;
1111				afree(tp->val.s, APERM);
1112			}
1113			tp->flag &= ~ISSET;
1114		}
1115	}
1116
1117 Search:
1118	if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) &&
1119	    (flags & FC_PATH)) {
1120		if (!tp) {
1121			if (insert && !(flags & FC_DEFPATH)) {
1122				tp = ktenter(&taliases, name, h);
1123				tp->type = CTALIAS;
1124			} else {
1125				tp = &temp;
1126				tp->type = CEXEC;
1127			}
1128			/* make ~ISSET */
1129			tp->flag = DEFINED;
1130		}
1131		npath.ro = search_path(name,
1132		    (flags & FC_DEFPATH) ? def_path : path,
1133		    X_OK, &tp->u2.errnov);
1134		if (npath.ro) {
1135			strdupx(tp->val.s, npath.ro, APERM);
1136			if (npath.ro != name)
1137				afree(npath.rw, ATEMP);
1138			tp->flag |= ISSET|ALLOC;
1139		} else if ((flags & FC_FUNC) &&
1140		    (fpath = str_val(global("FPATH"))) != null &&
1141		    (npath.ro = search_path(name, fpath, R_OK,
1142		    &tp->u2.errnov)) != NULL) {
1143			/*
1144			 * An undocumented feature of AT&T ksh is that
1145			 * it searches FPATH if a command is not found,
1146			 * even if the command hasn't been set up as an
1147			 * autoloaded function (ie, no typeset -uf).
1148			 */
1149			tp = &temp;
1150			tp->type = CFUNC;
1151			/* make ~ISSET */
1152			tp->flag = DEFINED;
1153			tp->u.fpath = npath.ro;
1154		}
1155	}
1156	return (tp);
1157}
1158
1159/*
1160 * flush executable commands with relative paths
1161 * (just relative or all?)
1162 */
1163void
1164flushcom(bool all)
1165{
1166	struct tbl *tp;
1167	struct tstate ts;
1168
1169	for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; )
1170		if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) {
1171			if (tp->flag&ALLOC) {
1172				tp->flag &= ~(ALLOC|ISSET);
1173				afree(tp->val.s, APERM);
1174			}
1175			tp->flag &= ~ISSET;
1176		}
1177}
1178
1179/* check if path is something we want to find */
1180static int
1181search_access(const char *fn, int mode)
1182{
1183	struct stat sb;
1184
1185	if (stat(fn, &sb) < 0)
1186		/* file does not exist */
1187		return (ENOENT);
1188	/* LINTED use of access */
1189	if (access(fn, mode) < 0)
1190		/* file exists, but we can't access it */
1191		return (errno);
1192	if (mode == X_OK && (!S_ISREG(sb.st_mode) ||
1193	    !(sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))))
1194		/* access(2) may say root can execute everything */
1195		return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES);
1196	return (0);
1197}
1198
1199/*
1200 * search for command with PATH
1201 */
1202const char *
1203search_path(const char *name, const char *lpath,
1204    /* R_OK or X_OK */
1205    int mode,
1206    /* set if candidate found, but not suitable */
1207    int *errnop)
1208{
1209	const char *sp, *p;
1210	char *xp;
1211	XString xs;
1212	size_t namelen;
1213	int ec = 0, ev;
1214
1215	if (vstrchr(name, '/')) {
1216		if ((ec = search_access(name, mode)) == 0) {
1217 search_path_ok:
1218			if (errnop)
1219				*errnop = 0;
1220			return (name);
1221		}
1222		goto search_path_err;
1223	}
1224
1225	namelen = strlen(name) + 1;
1226	Xinit(xs, xp, 128, ATEMP);
1227
1228	sp = lpath;
1229	while (sp != NULL) {
1230		xp = Xstring(xs, xp);
1231		if (!(p = cstrchr(sp, ':')))
1232			p = sp + strlen(sp);
1233		if (p != sp) {
1234			XcheckN(xs, xp, p - sp);
1235			memcpy(xp, sp, p - sp);
1236			xp += p - sp;
1237			*xp++ = '/';
1238		}
1239		sp = p;
1240		XcheckN(xs, xp, namelen);
1241		memcpy(xp, name, namelen);
1242		if ((ev = search_access(Xstring(xs, xp), mode)) == 0) {
1243			name = Xclose(xs, xp + namelen);
1244			goto search_path_ok;
1245		}
1246		/* accumulate non-ENOENT errors only */
1247		if (ev != ENOENT && ec == 0)
1248			ec = ev;
1249		if (*sp++ == '\0')
1250			sp = NULL;
1251	}
1252	Xfree(xs, xp);
1253 search_path_err:
1254	if (errnop)
1255		*errnop = ec ? ec : ENOENT;
1256	return (NULL);
1257}
1258
1259static int
1260call_builtin(struct tbl *tp, const char **wp, const char *where)
1261{
1262	int rv;
1263
1264	if (!tp)
1265		internal_errorf("%s: %s", where, wp[0]);
1266	builtin_argv0 = wp[0];
1267	builtin_flag = tp->flag;
1268	shf_reopen(1, SHF_WR, shl_stdout);
1269	shl_stdout_ok = true;
1270	ksh_getopt_reset(&builtin_opt, GF_ERROR);
1271	rv = (*tp->val.f)(wp);
1272	shf_flush(shl_stdout);
1273	shl_stdout_ok = false;
1274	builtin_flag = 0;
1275	builtin_argv0 = NULL;
1276	return (rv);
1277}
1278
1279/*
1280 * set up redirection, saving old fds in e->savefd
1281 */
1282static int
1283iosetup(struct ioword *iop, struct tbl *tp)
1284{
1285	int u = -1;
1286	char *cp = iop->name;
1287	int iotype = iop->flag & IOTYPE;
1288	bool do_open = true, do_close = false;
1289	int flags = 0;
1290	struct ioword iotmp;
1291	struct stat statb;
1292
1293	if (iotype != IOHERE)
1294		cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0));
1295
1296	/* Used for tracing and error messages to print expanded cp */
1297	iotmp = *iop;
1298	iotmp.name = (iotype == IOHERE) ? NULL : cp;
1299	iotmp.flag |= IONAMEXP;
1300
1301	if (Flag(FXTRACE))
1302		shellf("%s%s\n",
1303		    substitute(str_val(global("PS4")), 0),
1304		    snptreef(NULL, 32, "%R", &iotmp));
1305
1306	switch (iotype) {
1307	case IOREAD:
1308		flags = O_RDONLY;
1309		break;
1310
1311	case IOCAT:
1312		flags = O_WRONLY | O_APPEND | O_CREAT;
1313		break;
1314
1315	case IOWRITE:
1316		flags = O_WRONLY | O_CREAT | O_TRUNC;
1317		/*
1318		 * The stat() is here to allow redirections to
1319		 * things like /dev/null without error.
1320		 */
1321		if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) &&
1322		    (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
1323			flags |= O_EXCL;
1324		break;
1325
1326	case IORDWR:
1327		flags = O_RDWR | O_CREAT;
1328		break;
1329
1330	case IOHERE:
1331		do_open = false;
1332		/* herein() returns -2 if error has been printed */
1333		u = herein(iop, NULL);
1334		/* cp may have wrong name */
1335		break;
1336
1337	case IODUP: {
1338		const char *emsg;
1339
1340		do_open = false;
1341		if (*cp == '-' && !cp[1]) {
1342			/* prevent error return below */
1343			u = 1009;
1344			do_close = true;
1345		} else if ((u = check_fd(cp,
1346		    X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
1347		    &emsg)) < 0) {
1348			warningf(true, "%s: %s",
1349			    snptreef(NULL, 32, "%R", &iotmp), emsg);
1350			return (-1);
1351		}
1352		if (u == iop->unit)
1353			/* "dup from" == "dup to" */
1354			return (0);
1355		break;
1356	    }
1357	}
1358
1359	if (do_open) {
1360		if (Flag(FRESTRICTED) && (flags & O_CREAT)) {
1361			warningf(true, "%s: %s", cp, "restricted");
1362			return (-1);
1363		}
1364		u = open(cp, flags, 0666);
1365	}
1366	if (u < 0) {
1367		/* herein() may already have printed message */
1368		if (u == -1) {
1369			u = errno;
1370			warningf(true, "can't %s %s: %s",
1371			    iotype == IODUP ? "dup" :
1372			    (iotype == IOREAD || iotype == IOHERE) ?
1373			    "open" : "create", cp, cstrerror(u));
1374		}
1375		return (-1);
1376	}
1377	/* Do not save if it has already been redirected (i.e. "cat >x >y"). */
1378	if (e->savefd[iop->unit] == 0) {
1379		/* If these are the same, it means unit was previously closed */
1380		if (u == iop->unit)
1381			e->savefd[iop->unit] = -1;
1382		else
1383			/*
1384			 * c_exec() assumes e->savefd[fd] set for any
1385			 * redirections. Ask savefd() not to close iop->unit;
1386			 * this allows error messages to be seen if iop->unit
1387			 * is 2; also means we can't lose the fd (eg, both
1388			 * dup2 below and dup2 in restfd() failing).
1389			 */
1390			e->savefd[iop->unit] = savefd(iop->unit);
1391	}
1392
1393	if (do_close)
1394		close(iop->unit);
1395	else if (u != iop->unit) {
1396		if (ksh_dup2(u, iop->unit, true) < 0) {
1397			int eno;
1398
1399			eno = errno;
1400			warningf(true, "%s %s %s",
1401			    "can't finish (dup) redirection",
1402			    snptreef(NULL, 32, "%R", &iotmp),
1403			    cstrerror(eno));
1404			if (iotype != IODUP)
1405				close(u);
1406			return (-1);
1407		}
1408		if (iotype != IODUP)
1409			close(u);
1410		/*
1411		 * Touching any co-process fd in an empty exec
1412		 * causes the shell to close its copies
1413		 */
1414		else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
1415			if (iop->flag & IORDUP)
1416				/* possible exec <&p */
1417				coproc_read_close(u);
1418			else
1419				/* possible exec >&p */
1420				coproc_write_close(u);
1421		}
1422	}
1423	if (u == 2)
1424		/* Clear any write errors */
1425		shf_reopen(2, SHF_WR, shl_out);
1426	return (0);
1427}
1428
1429/*
1430 * Process here documents by providing the content, either as
1431 * result (globally allocated) string or in a temp file; if
1432 * unquoted, the string is expanded first.
1433 */
1434static int
1435hereinval(const char *content, int sub, char **resbuf, struct shf *shf)
1436{
1437	const char * volatile ccp = content;
1438	struct source *s, *osource;
1439
1440	osource = source;
1441	newenv(E_ERRH);
1442	if (kshsetjmp(e->jbuf)) {
1443		source = osource;
1444		quitenv(shf);
1445		/* special to iosetup(): don't print error */
1446		return (-2);
1447	}
1448	if (sub) {
1449		/* do substitutions on the content of heredoc */
1450		s = pushs(SSTRING, ATEMP);
1451		s->start = s->str = ccp;
1452		source = s;
1453		if (yylex(sub) != LWORD)
1454			internal_errorf("%s: %s", "herein", "yylex");
1455		source = osource;
1456		ccp = evalstr(yylval.cp, 0);
1457	}
1458
1459	if (resbuf == NULL)
1460		shf_puts(ccp, shf);
1461	else
1462		strdupx(*resbuf, ccp, APERM);
1463
1464	quitenv(NULL);
1465	return (0);
1466}
1467
1468static int
1469herein(struct ioword *iop, char **resbuf)
1470{
1471	int fd = -1;
1472	struct shf *shf;
1473	struct temp *h;
1474	int i;
1475
1476	/* ksh -c 'cat << EOF' can cause this... */
1477	if (iop->heredoc == NULL) {
1478		warningf(true, "%s missing", "here document");
1479		/* special to iosetup(): don't print error */
1480		return (-2);
1481	}
1482
1483	/* lexer substitution flags */
1484	i = (iop->flag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
1485
1486	/* skip all the fd setup if we just want the value */
1487	if (resbuf != NULL)
1488		return (hereinval(iop->heredoc, i, resbuf, NULL));
1489
1490	/*
1491	 * Create temp file to hold content (done before newenv
1492	 * so temp doesn't get removed too soon).
1493	 */
1494	h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
1495	if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY, 0)) < 0) {
1496		i = errno;
1497		warningf(true, "can't %s temporary file %s: %s",
1498		    !shf ? "create" : "open", h->tffn, cstrerror(i));
1499		if (shf)
1500			shf_close(shf);
1501		/* special to iosetup(): don't print error */
1502		return (-2);
1503	}
1504
1505	if (hereinval(iop->heredoc, i, NULL, shf) == -2) {
1506		close(fd);
1507		/* special to iosetup(): don't print error */
1508		return (-2);
1509	}
1510
1511	if (shf_close(shf) == EOF) {
1512		i = errno;
1513		close(fd);
1514		warningf(true, "can't %s temporary file %s: %s",
1515		    "write", h->tffn, cstrerror(i));
1516		/* special to iosetup(): don't print error */
1517		return (-2);
1518	}
1519
1520	return (fd);
1521}
1522
1523/*
1524 *	ksh special - the select command processing section
1525 *	print the args in column form - assuming that we can
1526 */
1527static const char *
1528do_selectargs(const char **ap, bool print_menu)
1529{
1530	static const char *read_args[] = {
1531		"read", "-r", "REPLY", NULL
1532	};
1533	char *s;
1534	int i, argct;
1535
1536	for (argct = 0; ap[argct]; argct++)
1537		;
1538	while (/* CONSTCOND */ 1) {
1539		/*-
1540		 * Menu is printed if
1541		 *	- this is the first time around the select loop
1542		 *	- the user enters a blank line
1543		 *	- the REPLY parameter is empty
1544		 */
1545		if (print_menu || !*str_val(global("REPLY")))
1546			pr_menu(ap);
1547		shellf("%s", str_val(global("PS3")));
1548		if (call_builtin(findcom("read", FC_BI), read_args, Tselect))
1549			return (NULL);
1550		s = str_val(global("REPLY"));
1551		if (*s) {
1552			getn(s, &i);
1553			return ((i >= 1 && i <= argct) ? ap[i - 1] : null);
1554		}
1555		print_menu = true;
1556	}
1557}
1558
1559struct select_menu_info {
1560	const char * const *args;
1561	int num_width;
1562};
1563
1564/* format a single select menu item */
1565static char *
1566select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1567{
1568	const struct select_menu_info *smi =
1569	    (const struct select_menu_info *)arg;
1570
1571	shf_snprintf(buf, buflen, "%*u) %s",
1572	    smi->num_width, i + 1, smi->args[i]);
1573	return (buf);
1574}
1575
1576/*
1577 *	print a select style menu
1578 */
1579void
1580pr_menu(const char * const *ap)
1581{
1582	struct select_menu_info smi;
1583	const char * const *pp;
1584	size_t acols = 0, aocts = 0, i;
1585	unsigned int n;
1586
1587	/*
1588	 * width/column calculations were done once and saved, but this
1589	 * means select can't be used recursively so we re-calculate
1590	 * each time (could save in a structure that is returned, but
1591	 * it's probably not worth the bother)
1592	 */
1593
1594	/*
1595	 * get dimensions of the list
1596	 */
1597	for (n = 0, pp = ap; *pp; n++, pp++) {
1598		i = strlen(*pp);
1599		if (i > aocts)
1600			aocts = i;
1601		i = utf_mbswidth(*pp);
1602		if (i > acols)
1603			acols = i;
1604	}
1605
1606	/*
1607	 * we will print an index of the form "%d) " in front of
1608	 * each entry, so get the maximum width of this
1609	 */
1610	for (i = n, smi.num_width = 1; i >= 10; i /= 10)
1611		smi.num_width++;
1612
1613	smi.args = ap;
1614	print_columns(shl_out, n, select_fmt_entry, (void *)&smi,
1615	    smi.num_width + 2 + aocts, smi.num_width + 2 + acols,
1616	    true);
1617}
1618
1619static char *
1620plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1621{
1622	strlcpy(buf, ((const char * const *)arg)[i], buflen);
1623	return (buf);
1624}
1625
1626void
1627pr_list(char * const *ap)
1628{
1629	size_t acols = 0, aocts = 0, i;
1630	unsigned int n;
1631	char * const *pp;
1632
1633	for (n = 0, pp = ap; *pp; n++, pp++) {
1634		i = strlen(*pp);
1635		if (i > aocts)
1636			aocts = i;
1637		i = utf_mbswidth(*pp);
1638		if (i > acols)
1639			acols = i;
1640	}
1641
1642	print_columns(shl_out, n, plain_fmt_entry, (const void *)ap,
1643	    aocts, acols, false);
1644}
1645
1646/*
1647 *	[[ ... ]] evaluation routines
1648 */
1649
1650/*
1651 * Test if the current token is a whatever. Accepts the current token if
1652 * it is. Returns 0 if it is not, non-zero if it is (in the case of
1653 * TM_UNOP and TM_BINOP, the returned value is a Test_op).
1654 */
1655static Test_op
1656dbteste_isa(Test_env *te, Test_meta meta)
1657{
1658	Test_op ret = TO_NONOP;
1659	int uqword;
1660	const char *p;
1661
1662	if (!*te->pos.wp)
1663		return (meta == TM_END ? TO_NONNULL : TO_NONOP);
1664
1665	/* unquoted word? */
1666	for (p = *te->pos.wp; *p == CHAR; p += 2)
1667		;
1668	uqword = *p == EOS;
1669
1670	if (meta == TM_UNOP || meta == TM_BINOP) {
1671		if (uqword) {
1672			/* longer than the longest operator */
1673			char buf[8];
1674			char *q = buf;
1675
1676			p = *te->pos.wp;
1677			while (*p++ == CHAR &&
1678			    (size_t)(q - buf) < sizeof(buf) - 1)
1679				*q++ = *p++;
1680			*q = '\0';
1681			ret = test_isop(meta, buf);
1682		}
1683	} else if (meta == TM_END)
1684		ret = TO_NONOP;
1685	else
1686		ret = (uqword && !strcmp(*te->pos.wp,
1687		    dbtest_tokens[(int)meta])) ? TO_NONNULL : TO_NONOP;
1688
1689	/* Accept the token? */
1690	if (ret != TO_NONOP)
1691		te->pos.wp++;
1692
1693	return (ret);
1694}
1695
1696static const char *
1697dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
1698{
1699	const char *s = *te->pos.wp;
1700
1701	if (!s)
1702		return (NULL);
1703
1704	te->pos.wp++;
1705
1706	if (!do_eval)
1707		return (null);
1708
1709	if (op == TO_STEQL || op == TO_STNEQ)
1710		s = evalstr(s, DOTILDE | DOPAT);
1711	else
1712		s = evalstr(s, DOTILDE);
1713
1714	return (s);
1715}
1716
1717static void
1718dbteste_error(Test_env *te, int offset, const char *msg)
1719{
1720	te->flags |= TEF_ERROR;
1721	internal_warningf("dbteste_error: %s (offset %d)", msg, offset);
1722}
1723