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