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