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