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