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