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