xref: /illumos-gate/usr/src/cmd/csh/sh.sem.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
26c02b4a4Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #include <unistd.h>
167c478bd9Sstevel@tonic-gate #include <fcntl.h>
177c478bd9Sstevel@tonic-gate #include "sh.h"
187c478bd9Sstevel@tonic-gate #include "sh.proc.h"
197c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  * C shell
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
256c02b4a4Smuffin void	doio(struct command *, int *, int *);
266c02b4a4Smuffin void	mypipe(int *);
276c02b4a4Smuffin void	chkclob(tchar *);
286c02b4a4Smuffin 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Return true if there is a back-quote (`) anywhere in the argument list.
317c478bd9Sstevel@tonic-gate  * Its presence would cause glob() to be invoked in the child process
327c478bd9Sstevel@tonic-gate  * and this would cause chaos if the child is created with vfork().
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate static bool
AnyBquote(struct command * t)357c478bd9Sstevel@tonic-gate AnyBquote(struct command *t)
367c478bd9Sstevel@tonic-gate {
377c478bd9Sstevel@tonic-gate 	tchar **pp;
387c478bd9Sstevel@tonic-gate 	tchar *p;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate 	if (noexec)
417c478bd9Sstevel@tonic-gate 		return (0);
427c478bd9Sstevel@tonic-gate 	for (pp = t->t_dcom; p = *pp++;) {
437c478bd9Sstevel@tonic-gate 		if (any('`', p))
447c478bd9Sstevel@tonic-gate 			return (1);
457c478bd9Sstevel@tonic-gate 	}
467c478bd9Sstevel@tonic-gate 	return (0);
477c478bd9Sstevel@tonic-gate }
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*VARARGS 1*/
506c02b4a4Smuffin void
execute(t,wanttty,pipein,pipeout)517c478bd9Sstevel@tonic-gate execute(t, wanttty, pipein, pipeout)
526c02b4a4Smuffin 	struct command *t;
537c478bd9Sstevel@tonic-gate 	int wanttty, *pipein, *pipeout;
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate 	bool forked = 0;
567c478bd9Sstevel@tonic-gate 	struct biltins *bifunc;
577c478bd9Sstevel@tonic-gate 	int pid = 0;
587c478bd9Sstevel@tonic-gate 	int pv[2];
597c478bd9Sstevel@tonic-gate 	extern int globcnt;
607c478bd9Sstevel@tonic-gate #ifdef TRACE
617c478bd9Sstevel@tonic-gate 	tprintf("TRACE- execute()\n");
627c478bd9Sstevel@tonic-gate #endif
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	if (t == 0)
657c478bd9Sstevel@tonic-gate 		return;
667c478bd9Sstevel@tonic-gate 	if ((t->t_dflg & FAND) && wanttty > 0)
677c478bd9Sstevel@tonic-gate 		wanttty = 0;
687c478bd9Sstevel@tonic-gate 	switch (t->t_dtyp) {
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	case TCOM:
717c478bd9Sstevel@tonic-gate 		if (t->t_dcom[0][0] == (tchar)S_TOPBIT[0])
727c478bd9Sstevel@tonic-gate 			(void) strcpy_(t->t_dcom[0], t->t_dcom[0] + 1);
737c478bd9Sstevel@tonic-gate 		if ((t->t_dflg & FREDO) == 0)
747c478bd9Sstevel@tonic-gate 			Dfix(t);		/* $ " ' \ */
757c478bd9Sstevel@tonic-gate 		if (t->t_dcom[0] == 0)
767c478bd9Sstevel@tonic-gate 			return;
777c478bd9Sstevel@tonic-gate 		/* fall into... */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	case TPAR:
807c478bd9Sstevel@tonic-gate 		if (t->t_dflg & FPOU)
817c478bd9Sstevel@tonic-gate 			mypipe(pipeout);
827c478bd9Sstevel@tonic-gate 		/*
837c478bd9Sstevel@tonic-gate 		 * Must do << early so parent will know
847c478bd9Sstevel@tonic-gate 		 * where input pointer should be.
857c478bd9Sstevel@tonic-gate 		 * If noexec then this is all we do.
867c478bd9Sstevel@tonic-gate 		 */
877c478bd9Sstevel@tonic-gate 		if (t->t_dflg & FHERE) {
887c478bd9Sstevel@tonic-gate 			(void) close(0);
897c478bd9Sstevel@tonic-gate 			unsetfd(0);
907c478bd9Sstevel@tonic-gate 			heredoc(t->t_dlef);
917c478bd9Sstevel@tonic-gate 			if (noexec) {
927c478bd9Sstevel@tonic-gate 				(void) close(0);
937c478bd9Sstevel@tonic-gate 				unsetfd(0);
947c478bd9Sstevel@tonic-gate 			}
957c478bd9Sstevel@tonic-gate 		}
967c478bd9Sstevel@tonic-gate 		if (noexec)
977c478bd9Sstevel@tonic-gate 			break;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 		set(S_status, S_0);
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 		/*
1027c478bd9Sstevel@tonic-gate 		 * This mess is the necessary kludge to handle the prefix
1037c478bd9Sstevel@tonic-gate 		 * builtins: nice, nohup, time.  These commands can also
1047c478bd9Sstevel@tonic-gate 		 * be used by themselves, and this is not handled here.
1057c478bd9Sstevel@tonic-gate 		 * This will also work when loops are parsed.
1067c478bd9Sstevel@tonic-gate 		 */
1077c478bd9Sstevel@tonic-gate 		while (t->t_dtyp == TCOM)
1087c478bd9Sstevel@tonic-gate 			if (eq(t->t_dcom[0], S_nice /*"nice"*/))
1097c478bd9Sstevel@tonic-gate 				if (t->t_dcom[1])
1107c478bd9Sstevel@tonic-gate 					/*if (any(t->t_dcom[1][0], "+-"))*/
1117c478bd9Sstevel@tonic-gate 					if (t->t_dcom[1][0] == '+' ||
1127c478bd9Sstevel@tonic-gate 					    t->t_dcom[1][0] == '-')
1137c478bd9Sstevel@tonic-gate 						if (t->t_dcom[2]) {
1147c478bd9Sstevel@tonic-gate 							setname(S_nice /*"nice"*/);
1157c478bd9Sstevel@tonic-gate 							t->t_nice = getn(t->t_dcom[1]);
1167c478bd9Sstevel@tonic-gate 							lshift(t->t_dcom, 2);
1177c478bd9Sstevel@tonic-gate 							t->t_dflg |= FNICE;
1187c478bd9Sstevel@tonic-gate 						} else
1197c478bd9Sstevel@tonic-gate 							break;
1207c478bd9Sstevel@tonic-gate 					else {
1217c478bd9Sstevel@tonic-gate 						t->t_nice = 4;
1227c478bd9Sstevel@tonic-gate 						lshift(t->t_dcom, 1);
1237c478bd9Sstevel@tonic-gate 						t->t_dflg |= FNICE;
1247c478bd9Sstevel@tonic-gate 					}
1257c478bd9Sstevel@tonic-gate 				else
1267c478bd9Sstevel@tonic-gate 					break;
1277c478bd9Sstevel@tonic-gate 			else if (eq(t->t_dcom[0], S_nohup /*"nohup"*/))
1287c478bd9Sstevel@tonic-gate 				if (t->t_dcom[1]) {
1297c478bd9Sstevel@tonic-gate 					t->t_dflg |= FNOHUP;
1307c478bd9Sstevel@tonic-gate 					lshift(t->t_dcom, 1);
1317c478bd9Sstevel@tonic-gate 				} else
1327c478bd9Sstevel@tonic-gate 					break;
1337c478bd9Sstevel@tonic-gate 			else if (eq(t->t_dcom[0], S_time /*"time"*/))
1347c478bd9Sstevel@tonic-gate 				if (t->t_dcom[1]) {
1357c478bd9Sstevel@tonic-gate 					t->t_dflg |= FTIME;
1367c478bd9Sstevel@tonic-gate 					lshift(t->t_dcom, 1);
1377c478bd9Sstevel@tonic-gate 				} else
1387c478bd9Sstevel@tonic-gate 					break;
1397c478bd9Sstevel@tonic-gate 			else
1407c478bd9Sstevel@tonic-gate 				break;
1417c478bd9Sstevel@tonic-gate 		/*
1427c478bd9Sstevel@tonic-gate 		 * Check if we have a builtin function and remember which one.
1437c478bd9Sstevel@tonic-gate 		 */
1447c478bd9Sstevel@tonic-gate 		bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 		/*
1477c478bd9Sstevel@tonic-gate 		 * We fork only if we are timed, or are not the end of
1487c478bd9Sstevel@tonic-gate 		 * a parenthesized list and not a simple builtin function.
1497c478bd9Sstevel@tonic-gate 		 * Simple meaning one that is not pipedout, niced, nohupped,
1507c478bd9Sstevel@tonic-gate 		 * or &'d.
1517c478bd9Sstevel@tonic-gate 		 * It would be nice(?) to not fork in some of these cases.
1527c478bd9Sstevel@tonic-gate 		 */
1537c478bd9Sstevel@tonic-gate 		if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
1547c478bd9Sstevel@tonic-gate 		     (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
1557c478bd9Sstevel@tonic-gate #ifdef VFORK
1567c478bd9Sstevel@tonic-gate 		    if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) ||
1577c478bd9Sstevel@tonic-gate 			bifunc || AnyBquote(t))
1587c478bd9Sstevel@tonic-gate #endif
1597c478bd9Sstevel@tonic-gate 			{ forked++; pid = pfork(t, wanttty); }
1607c478bd9Sstevel@tonic-gate #ifdef VFORK
1617c478bd9Sstevel@tonic-gate 		    else {
1627c478bd9Sstevel@tonic-gate 			void vffree();
1637c478bd9Sstevel@tonic-gate 			struct sv {
1647c478bd9Sstevel@tonic-gate 				int mask, child, setintr, haderr, didfds;
1657c478bd9Sstevel@tonic-gate 				int SHIN, SHOUT, SHDIAG, OLDSTD, tpgrp;
1667c478bd9Sstevel@tonic-gate 				struct sigvec sigv;
1677c478bd9Sstevel@tonic-gate 			} sv;
1687c478bd9Sstevel@tonic-gate 
169*2a8bcb4eSToomas Soome 			/*
1707c478bd9Sstevel@tonic-gate 			 * Prepare for the vfork by saving everything
1717c478bd9Sstevel@tonic-gate 			 * that the child corrupts before it exec's.
1727c478bd9Sstevel@tonic-gate 			 * Note that in some signal implementations
1737c478bd9Sstevel@tonic-gate 			 * which keep the signal info in user space
1747c478bd9Sstevel@tonic-gate 			 * (e.g. Sun's) it will also be necessary to
1757c478bd9Sstevel@tonic-gate  			 * save and restore the current sigvec's for
1767c478bd9Sstevel@tonic-gate 			 * the signals the child touches before it
1777c478bd9Sstevel@tonic-gate 			 * exec's.
1787c478bd9Sstevel@tonic-gate 			 */
1797c478bd9Sstevel@tonic-gate 			sv.mask = sigblock(sigmask(SIGCHLD));
1807c478bd9Sstevel@tonic-gate 			sv.child = child; sv.setintr = setintr;
1817c478bd9Sstevel@tonic-gate 			sv.haderr = haderr; sv.didfds = didfds;
1827c478bd9Sstevel@tonic-gate 			sv.SHIN = SHIN; sv.SHOUT = SHOUT;
1837c478bd9Sstevel@tonic-gate 			sv.SHDIAG = SHDIAG; sv.OLDSTD = OLDSTD;
1847c478bd9Sstevel@tonic-gate 			sv.tpgrp = tpgrp;
1857c478bd9Sstevel@tonic-gate 			Vsav = Vdp = 0; Vav = 0;
1867c478bd9Sstevel@tonic-gate 			(void) sigvec(SIGINT, (struct sigvec *)0, &sv.sigv);
1877c478bd9Sstevel@tonic-gate 			pid = vfork();
1887c478bd9Sstevel@tonic-gate 			if (pid < 0) {
1897c478bd9Sstevel@tonic-gate 				(void) sigsetmask(sv.mask);
1907c478bd9Sstevel@tonic-gate 				error("Vfork failed");
1917c478bd9Sstevel@tonic-gate 			}
1927c478bd9Sstevel@tonic-gate 			forked++;
1937c478bd9Sstevel@tonic-gate 			if (pid) {	/* parent */
1947c478bd9Sstevel@tonic-gate 				int ppid;
1957c478bd9Sstevel@tonic-gate 				closelog();
1967c478bd9Sstevel@tonic-gate 				child = sv.child; setintr = sv.setintr;
1977c478bd9Sstevel@tonic-gate 				haderr = sv.haderr; didfds = sv.didfds;
1987c478bd9Sstevel@tonic-gate 				SHIN = sv.SHIN;
1997c478bd9Sstevel@tonic-gate 				SHOUT = sv.SHOUT; SHDIAG = sv.SHDIAG;
2007c478bd9Sstevel@tonic-gate 				OLDSTD = sv.OLDSTD; tpgrp = sv.tpgrp;
2017c478bd9Sstevel@tonic-gate 				xfree(Vsav); Vsav = 0;
2027c478bd9Sstevel@tonic-gate 				xfree(Vdp); Vdp = 0;
2037c478bd9Sstevel@tonic-gate 				xfree( (tchar *)Vav); Vav = 0;
2047c478bd9Sstevel@tonic-gate 				/* this is from pfork() */
2057c478bd9Sstevel@tonic-gate 				ppid = pcurrjob ? pcurrjob->p_jobid : pid;
2067c478bd9Sstevel@tonic-gate 				if (wanttty >= 0 && tpgrp >= 0)
2077c478bd9Sstevel@tonic-gate 					setpgid (ppid, ppid);
2087c478bd9Sstevel@tonic-gate 				palloc(pid, t);
2097c478bd9Sstevel@tonic-gate 				/*
2107c478bd9Sstevel@tonic-gate 				 * Restore SIGINT handler.
2117c478bd9Sstevel@tonic-gate 				 */
2127c478bd9Sstevel@tonic-gate 				(void) sigvec(SIGINT, &sv.sigv, (struct sigvec *)0);
2137c478bd9Sstevel@tonic-gate 				(void) sigsetmask(sv.mask);
2147c478bd9Sstevel@tonic-gate 			} else {	/* child */
2157c478bd9Sstevel@tonic-gate 				/* this is from pfork() */
2167c478bd9Sstevel@tonic-gate 				int pgrp;
2177c478bd9Sstevel@tonic-gate 				bool ignint = 0;
2187c478bd9Sstevel@tonic-gate 				int sigttou;
2197c478bd9Sstevel@tonic-gate 				if (setintr)
2207c478bd9Sstevel@tonic-gate 					ignint =
2217c478bd9Sstevel@tonic-gate 					    (tpgrp == -1 && (t->t_dflg&FINT))
222*2a8bcb4eSToomas Soome 					    || gointr
2237c478bd9Sstevel@tonic-gate 						&& eq(gointr, S_MINUS/*"-"*/);
2247c478bd9Sstevel@tonic-gate 				pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
2257c478bd9Sstevel@tonic-gate 				child++;
2267c478bd9Sstevel@tonic-gate 				if (setintr) {
2277c478bd9Sstevel@tonic-gate 					setintr = 0;
2287c478bd9Sstevel@tonic-gate #ifdef notdef
2297c478bd9Sstevel@tonic-gate 					(void) signal(SIGCHLD, SIG_DFL);
2307c478bd9Sstevel@tonic-gate #endif
2317c478bd9Sstevel@tonic-gate 					(void) signal(SIGINT, ignint ?
2327c478bd9Sstevel@tonic-gate 						SIG_IGN : vffree);
2337c478bd9Sstevel@tonic-gate 					(void) signal(SIGQUIT, ignint ?
2347c478bd9Sstevel@tonic-gate 						SIG_IGN : SIG_DFL);
2357c478bd9Sstevel@tonic-gate 					if (wanttty >= 0) {
2367c478bd9Sstevel@tonic-gate 						(void) signal(SIGTSTP, SIG_DFL);
2377c478bd9Sstevel@tonic-gate 						(void) signal(SIGTTIN, SIG_DFL);
2387c478bd9Sstevel@tonic-gate 						(void) signal(SIGTTOU, SIG_DFL);
2397c478bd9Sstevel@tonic-gate 					}
2407c478bd9Sstevel@tonic-gate 					(void) signal(SIGTERM, parterm);
2417c478bd9Sstevel@tonic-gate 				} else if (tpgrp == -1 && (t->t_dflg&FINT)) {
2427c478bd9Sstevel@tonic-gate 					(void) signal(SIGINT, SIG_IGN);
2437c478bd9Sstevel@tonic-gate 					(void) signal(SIGQUIT, SIG_IGN);
2447c478bd9Sstevel@tonic-gate 				}
2457c478bd9Sstevel@tonic-gate 				if (wanttty >= 0 && tpgrp >= 0)
2467c478bd9Sstevel@tonic-gate 					(void) setpgid(0, pgrp);
2477c478bd9Sstevel@tonic-gate 				if (wanttty > 0) {
2487c478bd9Sstevel@tonic-gate 					sigttou = sigblock (
2497c478bd9Sstevel@tonic-gate 						sigmask(SIGTTOU) |
2507c478bd9Sstevel@tonic-gate 						sigmask(SIGTTIN) |
2517c478bd9Sstevel@tonic-gate 						sigmask(SIGTSTP));
2527c478bd9Sstevel@tonic-gate 					(void) ioctl(FSHTTY, TIOCSPGRP,
2537c478bd9Sstevel@tonic-gate 						 (tchar *)&pgrp);
2547c478bd9Sstevel@tonic-gate 					sigsetmask (sigttou);
2557c478bd9Sstevel@tonic-gate 				}
2567c478bd9Sstevel@tonic-gate 				if (tpgrp > 0)
2577c478bd9Sstevel@tonic-gate 					tpgrp = 0;
2587c478bd9Sstevel@tonic-gate 				if (t->t_dflg & FNOHUP)
2597c478bd9Sstevel@tonic-gate 					(void) signal(SIGHUP, SIG_IGN);
2607c478bd9Sstevel@tonic-gate 				if (t->t_dflg & FNICE)
2617c478bd9Sstevel@tonic-gate 					(void) setpriority(PRIO_PROCESS,
2627c478bd9Sstevel@tonic-gate 						0, t->t_nice);
2637c478bd9Sstevel@tonic-gate 			}
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 		    }
2667c478bd9Sstevel@tonic-gate #endif
2677c478bd9Sstevel@tonic-gate 		if (pid != 0) {
2687c478bd9Sstevel@tonic-gate 			/*
2697c478bd9Sstevel@tonic-gate 			 * It would be better if we could wait for the
2707c478bd9Sstevel@tonic-gate 			 * whole job when we knew the last process
2717c478bd9Sstevel@tonic-gate 			 * had been started.  Pwait, in fact, does
2727c478bd9Sstevel@tonic-gate 			 * wait for the whole job anyway, but this test
2737c478bd9Sstevel@tonic-gate 			 * doesn't really express our intentions.
2747c478bd9Sstevel@tonic-gate 			 */
2757c478bd9Sstevel@tonic-gate 			if (didfds==0 && t->t_dflg&FPIN) {
2767c478bd9Sstevel@tonic-gate 				(void) close(pipein[0]);
2777c478bd9Sstevel@tonic-gate 				unsetfd(pipein[0]);
2787c478bd9Sstevel@tonic-gate 				(void) close(pipein[1]);
2797c478bd9Sstevel@tonic-gate 				unsetfd(pipein[1]);
2807c478bd9Sstevel@tonic-gate 			}
2817c478bd9Sstevel@tonic-gate 			if ((t->t_dflg & (FPOU|FAND)) == 0)
2827c478bd9Sstevel@tonic-gate 				pwait();
2837c478bd9Sstevel@tonic-gate 			break;
2847c478bd9Sstevel@tonic-gate 		}
2857c478bd9Sstevel@tonic-gate 		doio(t, pipein, pipeout);
2867c478bd9Sstevel@tonic-gate 		if (t->t_dflg & FPOU) {
2877c478bd9Sstevel@tonic-gate 			(void) close(pipeout[0]);
2887c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipeout[0]);
2897c478bd9Sstevel@tonic-gate 			(void) close(pipeout[1]);
2907c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipeout[1]);
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		/*
2947c478bd9Sstevel@tonic-gate 		 * Perform a builtin function.
2957c478bd9Sstevel@tonic-gate 		 * If we are not forked, arrange for possible stopping
2967c478bd9Sstevel@tonic-gate 		 */
2977c478bd9Sstevel@tonic-gate 		if (bifunc) {
2987c478bd9Sstevel@tonic-gate 			func(t, bifunc);
2997c478bd9Sstevel@tonic-gate 			if (forked)
3007c478bd9Sstevel@tonic-gate 				exitstat();
3017c478bd9Sstevel@tonic-gate 			break;
3027c478bd9Sstevel@tonic-gate 		}
3037c478bd9Sstevel@tonic-gate 		if (t->t_dtyp != TPAR) {
3047c478bd9Sstevel@tonic-gate 			doexec(t);
3057c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 		/*
3087c478bd9Sstevel@tonic-gate 		 * For () commands must put new 0,1,2 in FSH* and recurse
3097c478bd9Sstevel@tonic-gate 		 */
3107c478bd9Sstevel@tonic-gate 		OLDSTD = dcopy(0, FOLDSTD);
3117c478bd9Sstevel@tonic-gate 		SHOUT = dcopy(1, FSHOUT);
3127c478bd9Sstevel@tonic-gate 		SHDIAG = dcopy(2, FSHDIAG);
3137c478bd9Sstevel@tonic-gate 		(void) close(SHIN);
3147c478bd9Sstevel@tonic-gate 		(void) unsetfd(SHIN);
3157c478bd9Sstevel@tonic-gate 		SHIN = -1;
3167c478bd9Sstevel@tonic-gate 		didfds = 0;
3177c478bd9Sstevel@tonic-gate 		wanttty = -1;
3187c478bd9Sstevel@tonic-gate 		t->t_dspr->t_dflg |= t->t_dflg & FINT;
3197c478bd9Sstevel@tonic-gate 		execute(t->t_dspr, wanttty);
3207c478bd9Sstevel@tonic-gate 		exitstat();
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	case TFIL:
3237c478bd9Sstevel@tonic-gate 		t->t_dcar->t_dflg |= FPOU |
3247c478bd9Sstevel@tonic-gate 		    (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
3257c478bd9Sstevel@tonic-gate 		execute(t->t_dcar, wanttty, pipein, pv);
3267c478bd9Sstevel@tonic-gate 		t->t_dcdr->t_dflg |= FPIN |
3277c478bd9Sstevel@tonic-gate 		    (t->t_dflg & (FPOU|FAND|FPAR|FINT));
3287c478bd9Sstevel@tonic-gate 		if (wanttty > 0)
3297c478bd9Sstevel@tonic-gate 			wanttty = 0;		/* got tty already */
3307c478bd9Sstevel@tonic-gate 		execute(t->t_dcdr, wanttty, pv, pipeout);
3317c478bd9Sstevel@tonic-gate 		break;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	case TLST:
3347c478bd9Sstevel@tonic-gate 		if (t->t_dcar) {
3357c478bd9Sstevel@tonic-gate 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
3367c478bd9Sstevel@tonic-gate 			execute(t->t_dcar, wanttty);
3377c478bd9Sstevel@tonic-gate 			/*
3387c478bd9Sstevel@tonic-gate 			 * In strange case of A&B make a new job after A
3397c478bd9Sstevel@tonic-gate 			 */
3407c478bd9Sstevel@tonic-gate 			if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
3417c478bd9Sstevel@tonic-gate 			    (t->t_dcdr->t_dflg&FAND) == 0)
3427c478bd9Sstevel@tonic-gate 				pendjob();
3437c478bd9Sstevel@tonic-gate 		}
3447c478bd9Sstevel@tonic-gate 		if (t->t_dcdr) {
3457c478bd9Sstevel@tonic-gate 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
3467c478bd9Sstevel@tonic-gate 			execute(t->t_dcdr, wanttty);
3477c478bd9Sstevel@tonic-gate 		}
3487c478bd9Sstevel@tonic-gate 		break;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	case TOR:
3517c478bd9Sstevel@tonic-gate 	case TAND:
3527c478bd9Sstevel@tonic-gate 		if (t->t_dcar) {
3537c478bd9Sstevel@tonic-gate 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
3547c478bd9Sstevel@tonic-gate 			execute(t->t_dcar, wanttty);
3557c478bd9Sstevel@tonic-gate 			if ((getn(value(S_status/*"status"*/)) == 0) != (t->t_dtyp == TAND))
3567c478bd9Sstevel@tonic-gate 				return;
3577c478bd9Sstevel@tonic-gate 		}
3587c478bd9Sstevel@tonic-gate 		if (t->t_dcdr) {
3597c478bd9Sstevel@tonic-gate 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
3607c478bd9Sstevel@tonic-gate 			execute(t->t_dcdr, wanttty);
3617c478bd9Sstevel@tonic-gate 		}
3627c478bd9Sstevel@tonic-gate 		break;
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 	/*
3657c478bd9Sstevel@tonic-gate 	 * Fall through for all breaks from switch
3667c478bd9Sstevel@tonic-gate 	 *
3677c478bd9Sstevel@tonic-gate 	 * If there will be no more executions of this
3687c478bd9Sstevel@tonic-gate 	 * command, flush all file descriptors.
3697c478bd9Sstevel@tonic-gate 	 * Places that turn on the FREDO bit are responsible
3707c478bd9Sstevel@tonic-gate 	 * for doing donefds after the last re-execution
3717c478bd9Sstevel@tonic-gate 	 */
3727c478bd9Sstevel@tonic-gate 	if (didfds && !(t->t_dflg & FREDO))
3737c478bd9Sstevel@tonic-gate 		donefds();
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	/*
3767c478bd9Sstevel@tonic-gate 	 * If glob() was called and arguments list is not yet
3777c478bd9Sstevel@tonic-gate 	 * free'ed, free them here.
3787c478bd9Sstevel@tonic-gate 	 */
3797c478bd9Sstevel@tonic-gate 	if (gargv) {
3807c478bd9Sstevel@tonic-gate 		blkfree(gargv);
3817c478bd9Sstevel@tonic-gate 		gargv = 0;
3827c478bd9Sstevel@tonic-gate 		globcnt = 0;
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate #ifdef VFORK
3877c478bd9Sstevel@tonic-gate void
vffree(void)3886c02b4a4Smuffin vffree(void)
3897c478bd9Sstevel@tonic-gate {
3906c02b4a4Smuffin 	tchar **v;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate #ifdef TRACE
3937c478bd9Sstevel@tonic-gate 	tprintf("TRACE- vffree()\n");
3947c478bd9Sstevel@tonic-gate #endif
3957c478bd9Sstevel@tonic-gate 	if (v = gargv)
3967c478bd9Sstevel@tonic-gate 		gargv = 0, xfree( (tchar *)v);
3977c478bd9Sstevel@tonic-gate 	if (v = pargv)
3987c478bd9Sstevel@tonic-gate 		pargv = 0, xfree( (tchar *)v);
3997c478bd9Sstevel@tonic-gate 	_exit(1);
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate #endif
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate /*
4047c478bd9Sstevel@tonic-gate  * Perform io redirection.
4057c478bd9Sstevel@tonic-gate  * We may or maynot be forked here.
4067c478bd9Sstevel@tonic-gate  */
4076c02b4a4Smuffin void
doio(struct command * t,int * pipein,int * pipeout)4086c02b4a4Smuffin doio(struct command *t, int *pipein, int *pipeout)
4097c478bd9Sstevel@tonic-gate {
4106c02b4a4Smuffin 	tchar *cp, *dp;
4116c02b4a4Smuffin 	int flags = t->t_dflg;
4127c478bd9Sstevel@tonic-gate 	int fd;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate #ifdef TRACE
4157c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doio()\n");
4167c478bd9Sstevel@tonic-gate #endif
4177c478bd9Sstevel@tonic-gate 	if (didfds || (flags & FREDO))
4187c478bd9Sstevel@tonic-gate 		return;
4197c478bd9Sstevel@tonic-gate 	if ((flags & FHERE) == 0) {	/* FHERE already done */
4207c478bd9Sstevel@tonic-gate 		(void) close(0);
4217c478bd9Sstevel@tonic-gate 		(void) unsetfd(0);
4227c478bd9Sstevel@tonic-gate 		if (cp = t->t_dlef) {
4237c478bd9Sstevel@tonic-gate 			dp = Dfix1(cp);
4247c478bd9Sstevel@tonic-gate 			cp = globone(dp);
4257c478bd9Sstevel@tonic-gate 			xfree(dp);
4267c478bd9Sstevel@tonic-gate 			xfree(cp);
4277c478bd9Sstevel@tonic-gate 			if (open_(cp, 0) < 0)
4287c478bd9Sstevel@tonic-gate 				Perror(cp);
4297c478bd9Sstevel@tonic-gate 		} else if (flags & FPIN) {
4307c478bd9Sstevel@tonic-gate 			fd = dup(pipein[0]);
4317c478bd9Sstevel@tonic-gate 			if (fd != -1)
4327c478bd9Sstevel@tonic-gate 				setfd(fd);
4337c478bd9Sstevel@tonic-gate 			(void) close(pipein[0]);
4347c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipein[0]);
4357c478bd9Sstevel@tonic-gate 			(void) close(pipein[1]);
4367c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipein[1]);
4377c478bd9Sstevel@tonic-gate 		} else if ((flags & FINT) && tpgrp == -1) {
4387c478bd9Sstevel@tonic-gate 			(void) close(0);	/* no need for unsetfd */
4397c478bd9Sstevel@tonic-gate 			(void) open("/dev/null", 0); /* no need for setfd */
4407c478bd9Sstevel@tonic-gate 		} else {
4417c478bd9Sstevel@tonic-gate 			fd = dup(OLDSTD);
4427c478bd9Sstevel@tonic-gate 			if (fd != -1)
4437c478bd9Sstevel@tonic-gate 				setfd(fd);
4447c478bd9Sstevel@tonic-gate 		}
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 	(void) close(1);
4477c478bd9Sstevel@tonic-gate 	(void) unsetfd(1);
4487c478bd9Sstevel@tonic-gate 	if (cp = t->t_drit) {
4497c478bd9Sstevel@tonic-gate 		dp = Dfix1(cp);
4507c478bd9Sstevel@tonic-gate 		cp = globone(dp);
4517c478bd9Sstevel@tonic-gate 		xfree(dp);
4527c478bd9Sstevel@tonic-gate 		if ((flags & FCAT) && open_(cp, 1) >= 0)
4537c478bd9Sstevel@tonic-gate 			(void) lseek(1, (off_t)0, 2);
4547c478bd9Sstevel@tonic-gate 		else {
4557c478bd9Sstevel@tonic-gate 			if (!(flags & FANY) && adrof(S_noclobber/*"noclobber"*/)) {
4567c478bd9Sstevel@tonic-gate 				if (flags & FCAT)
4577c478bd9Sstevel@tonic-gate 					Perror(cp);
4587c478bd9Sstevel@tonic-gate 				chkclob(cp);
4597c478bd9Sstevel@tonic-gate 			}
4607c478bd9Sstevel@tonic-gate 			if (creat_(cp, 0666) < 0)
4617c478bd9Sstevel@tonic-gate 				Perror(cp);
4627c478bd9Sstevel@tonic-gate 		}
4637c478bd9Sstevel@tonic-gate 		xfree(cp);
4647c478bd9Sstevel@tonic-gate 	} else if (flags & FPOU) {
4657c478bd9Sstevel@tonic-gate 		fd = dup(pipeout[1]);
4667c478bd9Sstevel@tonic-gate 		if (fd != -1)
4677c478bd9Sstevel@tonic-gate 			setfd (fd);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 	else {
4707c478bd9Sstevel@tonic-gate 		fd = dup(SHOUT);
4717c478bd9Sstevel@tonic-gate 		if (fd != -1)
4727c478bd9Sstevel@tonic-gate 			setfd(fd);
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	(void) close(2);
4767c478bd9Sstevel@tonic-gate 	(void) unsetfd(2);
4777c478bd9Sstevel@tonic-gate 	if (flags & FDIAG) {
4787c478bd9Sstevel@tonic-gate 		fd = dup(1);
4797c478bd9Sstevel@tonic-gate 		if (fd != -1)
4807c478bd9Sstevel@tonic-gate 			setfd(fd);
4817c478bd9Sstevel@tonic-gate 	}
4827c478bd9Sstevel@tonic-gate 	else {
4837c478bd9Sstevel@tonic-gate 		fd = dup(SHDIAG);
4847c478bd9Sstevel@tonic-gate 		if (fd != -1)
4857c478bd9Sstevel@tonic-gate 			setfd(fd);
4867c478bd9Sstevel@tonic-gate 	}
4877c478bd9Sstevel@tonic-gate 	didfds = 1;
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate 
4906c02b4a4Smuffin void
mypipe(int * pv)4916c02b4a4Smuffin mypipe(int *pv)
4927c478bd9Sstevel@tonic-gate {
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate #ifdef TRACE
4957c478bd9Sstevel@tonic-gate 	tprintf("TRACE- mypipe()\n");
4967c478bd9Sstevel@tonic-gate #endif
4977c478bd9Sstevel@tonic-gate 	if (pipe(pv) < 0)
4987c478bd9Sstevel@tonic-gate 		goto oops;
4997c478bd9Sstevel@tonic-gate 	setfd(pv[0]);
5007c478bd9Sstevel@tonic-gate 	setfd(pv[1]);
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	pv[0] = dmove(pv[0], -1);
5037c478bd9Sstevel@tonic-gate 	pv[1] = dmove(pv[1], -1);
5047c478bd9Sstevel@tonic-gate 	if (pv[0] >= 0 && pv[1] >= 0)
5057c478bd9Sstevel@tonic-gate 		return;
5067c478bd9Sstevel@tonic-gate oops:
5077c478bd9Sstevel@tonic-gate 	error("Can't make pipe");
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5106c02b4a4Smuffin void
chkclob(tchar * cp)5116c02b4a4Smuffin chkclob(tchar *cp)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	struct stat stb;
5147c478bd9Sstevel@tonic-gate 	unsigned short	type;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate #ifdef TRACE
5177c478bd9Sstevel@tonic-gate 	tprintf("TRACE- chkclob()\n");
5187c478bd9Sstevel@tonic-gate #endif
5197c478bd9Sstevel@tonic-gate 	if (stat_(cp, &stb) < 0)
5207c478bd9Sstevel@tonic-gate 		return;
5217c478bd9Sstevel@tonic-gate 	type = stb.st_mode & S_IFMT;
5227c478bd9Sstevel@tonic-gate 	if (type == S_IFCHR || type == S_IFIFO)
5237c478bd9Sstevel@tonic-gate 		return;
5247c478bd9Sstevel@tonic-gate 	error("%t: File exists", cp);
5257c478bd9Sstevel@tonic-gate }
526