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