xref: /original-bsd/bin/csh/sem.c (revision 5e5c7fcc)
1c1549ed3Sdist /*
2c1549ed3Sdist  * Copyright (c) 1980 Regents of the University of California.
367f82af8Sedward  * All rights reserved.  The Berkeley Software License Agreement
4c1549ed3Sdist  * specifies the terms and conditions for redistribution.
5c1549ed3Sdist  */
6c1549ed3Sdist 
743fabe3fSedward #ifndef lint
8*5e5c7fccSmarc static char *sccsid = "@(#)sem.c	5.6 (Berkeley) 11/20/89";
967f82af8Sedward #endif
1013082428Sbill 
1113082428Sbill #include "sh.h"
1213082428Sbill #include "sh.proc.h"
1313082428Sbill #include <sys/ioctl.h>
14*5e5c7fccSmarc #include "pathnames.h"
1513082428Sbill 
1613082428Sbill /*
1713082428Sbill  * C shell
1813082428Sbill  */
1913082428Sbill 
20*5e5c7fccSmarc static int nosigchld = 0, osigmask;
21*5e5c7fccSmarc static int onosigchld = 0, oosigmask;
2213082428Sbill /*VARARGS 1*/
2313082428Sbill execute(t, wanttty, pipein, pipeout)
2413082428Sbill 	register struct command *t;
2513082428Sbill 	int wanttty, *pipein, *pipeout;
2613082428Sbill {
2713082428Sbill 	bool forked = 0;
2813082428Sbill 	struct biltins *bifunc;
2913082428Sbill 	int pid = 0;
3013082428Sbill 	int pv[2];
3113082428Sbill 
3213082428Sbill 	if (t == 0)
3313082428Sbill 		return;
34*5e5c7fccSmarc #ifdef REMOVE_THIS
35*5e5c7fccSmarc { short x=t->t_dtyp;
36*5e5c7fccSmarc int flg = t->t_dflg;
37*5e5c7fccSmarc printf("execute: cmd=%s pid=%d t_dtyp=%s wanttty=%d ", t->t_dcom[0], getpid(),
38*5e5c7fccSmarc 	x == TCOM ? "TCOM" : x == TPAR ? "TPAR" : x == TFIL ? "TFIL" :
39*5e5c7fccSmarc 	x == TLST ? "TLST" : x == TOR ? "TOR" : x == TAND ? "TAND" : "UNKNOWN",
40*5e5c7fccSmarc 	wanttty);
41*5e5c7fccSmarc if (flg&FAND) printf("FAND "); if (flg&FCAT) printf("FCAT ");
42*5e5c7fccSmarc if (flg&FPIN) printf("FPIN "); if (flg&FPOU) printf("FPOU ");
43*5e5c7fccSmarc if (flg&FPAR) printf("FPAR "); if (flg&FINT) printf("FINT ");
44*5e5c7fccSmarc if (flg&FDIAG) printf("FDIAG "); if (flg&FANY) printf("FANY ");
45*5e5c7fccSmarc if (flg&FHERE) printf("FHERE "); if (flg&FREDO) printf("FREDO ");
46*5e5c7fccSmarc if (flg&FNICE) printf("FNICE "); if (flg&FNOHUP) printf("FNOHUP ");
47*5e5c7fccSmarc if (flg&FTIME) printf("FTIME "); printf("\n");
48*5e5c7fccSmarc }
49*5e5c7fccSmarc #endif
5013082428Sbill 	if ((t->t_dflg & FAND) && wanttty > 0)
5113082428Sbill 		wanttty = 0;
5213082428Sbill 	switch (t->t_dtyp) {
5313082428Sbill 
5413082428Sbill 	case TCOM:
5513082428Sbill 		if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE)
5643fabe3fSedward 			(void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
5713082428Sbill 		if ((t->t_dflg & FREDO) == 0)
5813082428Sbill 			Dfix(t);		/* $ " ' \ */
5913082428Sbill 		if (t->t_dcom[0] == 0)
6013082428Sbill 			return;
6113082428Sbill 		/* fall into... */
6213082428Sbill 
6313082428Sbill 	case TPAR:
6413082428Sbill 		if (t->t_dflg & FPOU)
6513082428Sbill 			mypipe(pipeout);
6613082428Sbill 		/*
6713082428Sbill 		 * Must do << early so parent will know
6813082428Sbill 		 * where input pointer should be.
6913082428Sbill 		 * If noexec then this is all we do.
7013082428Sbill 		 */
7113082428Sbill 		if (t->t_dflg & FHERE) {
7243fabe3fSedward 			(void) close(0);
7313082428Sbill 			heredoc(t->t_dlef);
7413082428Sbill 			if (noexec)
7543fabe3fSedward 				(void) close(0);
7613082428Sbill 		}
7713082428Sbill 		if (noexec)
7813082428Sbill 			break;
7913082428Sbill 
8013082428Sbill 		set("status", "0");
8113082428Sbill 
8213082428Sbill 		/*
8313082428Sbill 		 * This mess is the necessary kludge to handle the prefix
8413082428Sbill 		 * builtins: nice, nohup, time.  These commands can also
8513082428Sbill 		 * be used by themselves, and this is not handled here.
8613082428Sbill 		 * This will also work when loops are parsed.
8713082428Sbill 		 */
8813082428Sbill 		while (t->t_dtyp == TCOM)
8913082428Sbill 			if (eq(t->t_dcom[0], "nice"))
9013082428Sbill 				if (t->t_dcom[1])
9113082428Sbill 					if (any(t->t_dcom[1][0], "+-"))
9213082428Sbill 						if (t->t_dcom[2]) {
9313082428Sbill 							setname("nice");
9413082428Sbill 							t->t_nice = getn(t->t_dcom[1]);
9513082428Sbill 							lshift(t->t_dcom, 2);
9613082428Sbill 							t->t_dflg |= FNICE;
9713082428Sbill 						} else
9813082428Sbill 							break;
9913082428Sbill 					else {
10013082428Sbill 						t->t_nice = 4;
10113082428Sbill 						lshift(t->t_dcom, 1);
10213082428Sbill 						t->t_dflg |= FNICE;
10313082428Sbill 					}
10413082428Sbill 				else
10513082428Sbill 					break;
10613082428Sbill 			else if (eq(t->t_dcom[0], "nohup"))
10713082428Sbill 				if (t->t_dcom[1]) {
10813082428Sbill 					t->t_dflg |= FNOHUP;
10913082428Sbill 					lshift(t->t_dcom, 1);
11013082428Sbill 				} else
11113082428Sbill 					break;
11213082428Sbill 			else if (eq(t->t_dcom[0], "time"))
11313082428Sbill 				if (t->t_dcom[1]) {
11413082428Sbill 					t->t_dflg |= FTIME;
11513082428Sbill 					lshift(t->t_dcom, 1);
11613082428Sbill 				} else
11713082428Sbill 					break;
11813082428Sbill 			else
11913082428Sbill 				break;
12013082428Sbill 		/*
12113082428Sbill 		 * Check if we have a builtin function and remember which one.
12213082428Sbill 		 */
12313082428Sbill 		bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
12413082428Sbill 
12513082428Sbill 		/*
12613082428Sbill 		 * We fork only if we are timed, or are not the end of
12713082428Sbill 		 * a parenthesized list and not a simple builtin function.
12813082428Sbill 		 * Simple meaning one that is not pipedout, niced, nohupped,
12913082428Sbill 		 * or &'d.
13013082428Sbill 		 * It would be nice(?) to not fork in some of these cases.
13113082428Sbill 		 */
13213082428Sbill 		if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
13313082428Sbill 		     (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
13413082428Sbill #ifdef VFORK
13513082428Sbill 		    if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc)
13613082428Sbill #endif
137*5e5c7fccSmarc 			{ forked++;
138*5e5c7fccSmarc 			  if (wanttty >= 0 && !nosigchld) {
139*5e5c7fccSmarc #ifdef REMOVE_THIS
140*5e5c7fccSmarc 				printf("(%d) blocking sigchld\n", getpid());
141*5e5c7fccSmarc #endif
142*5e5c7fccSmarc 				osigmask = sigblock(sigmask(SIGCHLD));
143*5e5c7fccSmarc 				nosigchld = 1;
144*5e5c7fccSmarc 			  }
145*5e5c7fccSmarc 
146*5e5c7fccSmarc 			  pid = pfork(t, wanttty);
147*5e5c7fccSmarc 			  if (pid == 0 && nosigchld) {
148*5e5c7fccSmarc #ifdef REMOVE_THIS
149*5e5c7fccSmarc 				printf("%d unblocking sigchld after fork\n", getpid());
150*5e5c7fccSmarc #endif
151*5e5c7fccSmarc 				sigsetmask(osigmask);
152*5e5c7fccSmarc 				nosigchld = 0;
153*5e5c7fccSmarc 			  }
154*5e5c7fccSmarc 			}
15513082428Sbill #ifdef VFORK
15613082428Sbill 		    else {
157*5e5c7fccSmarc 			sig_t vffree;
15843fabe3fSedward 			int ochild, osetintr, ohaderr, odidfds;
15913082428Sbill 			int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
1603bb023eaSbostic 			long omask;
16113082428Sbill 
16215d9e91aSlepreau 			/*
16315d9e91aSlepreau 			 * Prepare for the vfork by saving everything
16415d9e91aSlepreau 			 * that the child corrupts before it exec's.
16515d9e91aSlepreau 			 * Note that in some signal implementations
16615d9e91aSlepreau 			 * which keep the signal info in user space
16715d9e91aSlepreau 			 * (e.g. Sun's) it will also be necessary to
16815d9e91aSlepreau  			 * save and restore the current sigvec's for
16915d9e91aSlepreau 			 * the signals the child touches before it
17015d9e91aSlepreau 			 * exec's.
17115d9e91aSlepreau 			 */
172*5e5c7fccSmarc 			if (wanttty >= 0 && !nosigchld && !noexec) {
173*5e5c7fccSmarc #ifdef REMOVE_THIS
174*5e5c7fccSmarc 				printf("(%d) blocking sigchld\n", getpid());
175*5e5c7fccSmarc #endif
176*5e5c7fccSmarc 				osigmask = sigblock(sigmask(SIGCHLD));
177*5e5c7fccSmarc 				nosigchld = 1;
178*5e5c7fccSmarc 			}
1791e9806efSralph 			omask = sigblock(sigmask(SIGCHLD));
18013082428Sbill 			ochild = child; osetintr = setintr;
18143fabe3fSedward 			ohaderr = haderr; odidfds = didfds;
18213082428Sbill 			oSHIN = SHIN; oSHOUT = SHOUT;
18313082428Sbill 			oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp;
184*5e5c7fccSmarc 			oosigmask = osigmask; onosigchld = nosigchld;
18513082428Sbill 			Vsav = Vdp = 0; Vav = 0;
18613082428Sbill 			pid = vfork();
18713082428Sbill 			if (pid < 0) {
18843fabe3fSedward 				(void) sigsetmask(omask);
18913082428Sbill 				error("No more processes");
19013082428Sbill 			}
19113082428Sbill 			forked++;
19215d9e91aSlepreau 			if (pid) {	/* parent */
19313082428Sbill 				child = ochild; setintr = osetintr;
19413082428Sbill 				haderr = ohaderr; didfds = odidfds;
19543fabe3fSedward 				SHIN = oSHIN;
19613082428Sbill 				SHOUT = oSHOUT; SHDIAG = oSHDIAG;
19713082428Sbill 				OLDSTD = oOLDSTD; tpgrp = otpgrp;
198*5e5c7fccSmarc 				osigmask = oosigmask; nosigchld = onosigchld;
19913082428Sbill 				xfree(Vsav); Vsav = 0;
20013082428Sbill 				xfree(Vdp); Vdp = 0;
20143fabe3fSedward 				xfree((char *)Vav); Vav = 0;
20213082428Sbill 				/* this is from pfork() */
20313082428Sbill 				palloc(pid, t);
20443fabe3fSedward 				(void) sigsetmask(omask);
20515d9e91aSlepreau 			} else {	/* child */
20613082428Sbill 				/* this is from pfork() */
20713082428Sbill 				int pgrp;
20813082428Sbill 				bool ignint = 0;
20913082428Sbill 
210*5e5c7fccSmarc 				if (nosigchld) {
211*5e5c7fccSmarc #ifdef REMOVE_THIS
212*5e5c7fccSmarc 					printf("%d unblocking sigchld after fork\n", getpid());
213*5e5c7fccSmarc #endif
214*5e5c7fccSmarc 					sigsetmask(osigmask);
215*5e5c7fccSmarc 					nosigchld = 0;
216*5e5c7fccSmarc 				}
21713082428Sbill 				if (setintr)
21813082428Sbill 					ignint =
21913082428Sbill 					    (tpgrp == -1 && (t->t_dflg&FINT))
22013082428Sbill 					    || gointr && eq(gointr, "-");
22113082428Sbill 				pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
22213082428Sbill 				child++;
22313082428Sbill 				if (setintr) {
22413082428Sbill 					setintr = 0;
2252c8ae23aSsam #ifdef notdef
22643fabe3fSedward 					(void) signal(SIGCHLD, SIG_DFL);
2272c8ae23aSsam #endif
22843fabe3fSedward 					(void) signal(SIGINT, ignint ?
2291e9806efSralph 						SIG_IGN : vffree);
23043fabe3fSedward 					(void) signal(SIGQUIT, ignint ?
2311e9806efSralph 						SIG_IGN : SIG_DFL);
23213082428Sbill 					if (wanttty >= 0) {
23343fabe3fSedward 						(void) signal(SIGTSTP, SIG_DFL);
23443fabe3fSedward 						(void) signal(SIGTTIN, SIG_DFL);
23543fabe3fSedward 						(void) signal(SIGTTOU, SIG_DFL);
23613082428Sbill 					}
23743fabe3fSedward 					(void) signal(SIGTERM, parterm);
23813082428Sbill 				} else if (tpgrp == -1 && (t->t_dflg&FINT)) {
23943fabe3fSedward 					(void) signal(SIGINT, SIG_IGN);
24043fabe3fSedward 					(void) signal(SIGQUIT, SIG_IGN);
24113082428Sbill 				}
242*5e5c7fccSmarc 				if (wanttty >= 0 && tpgrp >= 0)
243*5e5c7fccSmarc 					(void) setpgrp(0, pgrp);
24413082428Sbill 				if (wanttty > 0)
24543fabe3fSedward 					(void) ioctl(FSHTTY, TIOCSPGRP,
24643fabe3fSedward 						(char *)&pgrp);
24713082428Sbill 				if (tpgrp > 0)
24813082428Sbill 					tpgrp = 0;
24913082428Sbill 				if (t->t_dflg & FNOHUP)
25043fabe3fSedward 					(void) signal(SIGHUP, SIG_IGN);
25113082428Sbill 				if (t->t_dflg & FNICE)
25215d9e91aSlepreau 					(void) setpriority(PRIO_PROCESS,
25315d9e91aSlepreau 						0, t->t_nice);
25413082428Sbill 			}
25513082428Sbill 
25613082428Sbill 		    }
25713082428Sbill #endif
25813082428Sbill 		if (pid != 0) {
25913082428Sbill 			/*
26013082428Sbill 			 * It would be better if we could wait for the
26113082428Sbill 			 * whole job when we knew the last process
26213082428Sbill 			 * had been started.  Pwait, in fact, does
26313082428Sbill 			 * wait for the whole job anyway, but this test
26413082428Sbill 			 * doesn't really express our intentions.
26513082428Sbill 			 */
26643fabe3fSedward 			if (didfds==0 && t->t_dflg&FPIN) {
26743fabe3fSedward 				(void) close(pipein[0]);
26843fabe3fSedward 				(void) close(pipein[1]);
26943fabe3fSedward 			}
270*5e5c7fccSmarc 			if ((t->t_dflg & FPOU) == 0) {
271*5e5c7fccSmarc #ifdef REMOVE_THIS
272*5e5c7fccSmarc 				printf("(%d) last command - should unblock sigchld? (%d)\n", getpid(), nosigchld);
273*5e5c7fccSmarc #endif
274*5e5c7fccSmarc 				if (nosigchld) {
275*5e5c7fccSmarc #ifdef foobarbaz
276*5e5c7fccSmarc 					printf("DID\n");
277*5e5c7fccSmarc #endif
278*5e5c7fccSmarc 					sigsetmask(osigmask);
279*5e5c7fccSmarc 					nosigchld = 0;
280*5e5c7fccSmarc 				}
281*5e5c7fccSmarc 				if ((t->t_dflg & FAND) == 0)
28213082428Sbill 					pwait();
283*5e5c7fccSmarc 			}
28413082428Sbill 			break;
28513082428Sbill 		}
28613082428Sbill 		doio(t, pipein, pipeout);
28743fabe3fSedward 		if (t->t_dflg & FPOU) {
28843fabe3fSedward 			(void) close(pipeout[0]);
28943fabe3fSedward 			(void) close(pipeout[1]);
29043fabe3fSedward 		}
29113082428Sbill 
29213082428Sbill 		/*
29313082428Sbill 		 * Perform a builtin function.
29413082428Sbill 		 * If we are not forked, arrange for possible stopping
29513082428Sbill 		 */
29613082428Sbill 		if (bifunc) {
29713082428Sbill 			func(t, bifunc);
29813082428Sbill 			if (forked)
29913082428Sbill 				exitstat();
30013082428Sbill 			break;
30113082428Sbill 		}
30213082428Sbill 		if (t->t_dtyp != TPAR) {
30313082428Sbill 			doexec(t);
30413082428Sbill 			/*NOTREACHED*/
30513082428Sbill 		}
30613082428Sbill 		/*
30713082428Sbill 		 * For () commands must put new 0,1,2 in FSH* and recurse
30813082428Sbill 		 */
30913082428Sbill 		OLDSTD = dcopy(0, FOLDSTD);
31013082428Sbill 		SHOUT = dcopy(1, FSHOUT);
31113082428Sbill 		SHDIAG = dcopy(2, FSHDIAG);
31243fabe3fSedward 		(void) close(SHIN);
31343fabe3fSedward 		SHIN = -1;
31443fabe3fSedward 		didfds = 0;
31513082428Sbill 		wanttty = -1;
31613082428Sbill 		t->t_dspr->t_dflg |= t->t_dflg & FINT;
31713082428Sbill 		execute(t->t_dspr, wanttty);
31813082428Sbill 		exitstat();
31913082428Sbill 
32013082428Sbill 	case TFIL:
32113082428Sbill 		t->t_dcar->t_dflg |= FPOU |
32213082428Sbill 		    (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
32313082428Sbill 		execute(t->t_dcar, wanttty, pipein, pv);
32413082428Sbill 		t->t_dcdr->t_dflg |= FPIN |
32513082428Sbill 		    (t->t_dflg & (FPOU|FAND|FPAR|FINT));
32613082428Sbill 		if (wanttty > 0)
32713082428Sbill 			wanttty = 0;		/* got tty already */
32813082428Sbill 		execute(t->t_dcdr, wanttty, pv, pipeout);
32913082428Sbill 		break;
33013082428Sbill 
33113082428Sbill 	case TLST:
33213082428Sbill 		if (t->t_dcar) {
33313082428Sbill 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
33413082428Sbill 			execute(t->t_dcar, wanttty);
33513082428Sbill 			/*
33613082428Sbill 			 * In strange case of A&B make a new job after A
33713082428Sbill 			 */
33813082428Sbill 			if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
33913082428Sbill 			    (t->t_dcdr->t_dflg&FAND) == 0)
34013082428Sbill 				pendjob();
34113082428Sbill 		}
34213082428Sbill 		if (t->t_dcdr) {
34313082428Sbill 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
34413082428Sbill 			execute(t->t_dcdr, wanttty);
34513082428Sbill 		}
34613082428Sbill 		break;
34713082428Sbill 
34813082428Sbill 	case TOR:
34913082428Sbill 	case TAND:
35013082428Sbill 		if (t->t_dcar) {
35113082428Sbill 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
35213082428Sbill 			execute(t->t_dcar, wanttty);
35313082428Sbill 			if ((getn(value("status")) == 0) != (t->t_dtyp == TAND))
35413082428Sbill 				return;
35513082428Sbill 		}
35613082428Sbill 		if (t->t_dcdr) {
35713082428Sbill 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
35813082428Sbill 			execute(t->t_dcdr, wanttty);
35913082428Sbill 		}
36013082428Sbill 		break;
36113082428Sbill 	}
36213082428Sbill 	/*
36313082428Sbill 	 * Fall through for all breaks from switch
36413082428Sbill 	 *
36513082428Sbill 	 * If there will be no more executions of this
36613082428Sbill 	 * command, flush all file descriptors.
36713082428Sbill 	 * Places that turn on the FREDO bit are responsible
36813082428Sbill 	 * for doing donefds after the last re-execution
36913082428Sbill 	 */
37013082428Sbill 	if (didfds && !(t->t_dflg & FREDO))
37113082428Sbill 		donefds();
37213082428Sbill }
37313082428Sbill 
37413082428Sbill #ifdef VFORK
37513082428Sbill vffree()
37613082428Sbill {
37713082428Sbill 	register char **v;
37813082428Sbill 
37913082428Sbill 	if (v = gargv)
38043fabe3fSedward 		gargv = 0, xfree((char *)v);
38113082428Sbill 	if (v = pargv)
38243fabe3fSedward 		pargv = 0, xfree((char *)v);
38313082428Sbill 	_exit(1);
38413082428Sbill }
38513082428Sbill #endif
38613082428Sbill 
38713082428Sbill /*
38813082428Sbill  * Perform io redirection.
38913082428Sbill  * We may or maynot be forked here.
39013082428Sbill  */
39113082428Sbill doio(t, pipein, pipeout)
39213082428Sbill 	register struct command *t;
39313082428Sbill 	int *pipein, *pipeout;
39413082428Sbill {
39513082428Sbill 	register char *cp;
39613082428Sbill 	register int flags = t->t_dflg;
39713082428Sbill 
39813082428Sbill 	if (didfds || (flags & FREDO))
39913082428Sbill 		return;
40013082428Sbill 	if ((flags & FHERE) == 0) {	/* FHERE already done */
40143fabe3fSedward 		(void) close(0);
40213082428Sbill 		if (cp = t->t_dlef) {
40313082428Sbill 			cp = globone(Dfix1(cp));
40413082428Sbill 			xfree(cp);
40513082428Sbill 			if (open(cp, 0) < 0)
40613082428Sbill 				Perror(cp);
40743fabe3fSedward 		} else if (flags & FPIN) {
40843fabe3fSedward 			(void) dup(pipein[0]);
40943fabe3fSedward 			(void) close(pipein[0]);
41043fabe3fSedward 			(void) close(pipein[1]);
41143fabe3fSedward 		} else if ((flags & FINT) && tpgrp == -1) {
41243fabe3fSedward 			(void) close(0);
413*5e5c7fccSmarc 			(void) open(_PATH_DEVNULL, 0);
41443fabe3fSedward 		} else
415cde959b4Sedward 			(void) dup(OLDSTD);
41613082428Sbill 	}
41743fabe3fSedward 	(void) close(1);
41813082428Sbill 	if (cp = t->t_drit) {
41913082428Sbill 		cp = globone(Dfix1(cp));
42013082428Sbill 		xfree(cp);
42113082428Sbill 		if ((flags & FCAT) && open(cp, 1) >= 0)
42243fabe3fSedward 			(void) lseek(1, (off_t)0, 2);
42313082428Sbill 		else {
42413082428Sbill 			if (!(flags & FANY) && adrof("noclobber")) {
42513082428Sbill 				if (flags & FCAT)
42613082428Sbill 					Perror(cp);
42713082428Sbill 				chkclob(cp);
42813082428Sbill 			}
42913082428Sbill 			if (creat(cp, 0666) < 0)
43013082428Sbill 				Perror(cp);
43113082428Sbill 		}
43213082428Sbill 	} else if (flags & FPOU)
43343fabe3fSedward 		(void) dup(pipeout[1]);
43413082428Sbill 	else
435cde959b4Sedward 		(void) dup(SHOUT);
43613082428Sbill 
43743fabe3fSedward 	(void) close(2);
43843fabe3fSedward 	if (flags & FDIAG)
43943fabe3fSedward 		(void) dup(1);
44043fabe3fSedward 	else
441cde959b4Sedward 		(void) dup(SHDIAG);
44213082428Sbill 	didfds = 1;
44313082428Sbill }
44413082428Sbill 
44513082428Sbill mypipe(pv)
44613082428Sbill 	register int *pv;
44713082428Sbill {
44813082428Sbill 
44913082428Sbill 	if (pipe(pv) < 0)
45013082428Sbill 		goto oops;
45113082428Sbill 	pv[0] = dmove(pv[0], -1);
45213082428Sbill 	pv[1] = dmove(pv[1], -1);
45313082428Sbill 	if (pv[0] >= 0 && pv[1] >= 0)
45413082428Sbill 		return;
45513082428Sbill oops:
45613082428Sbill 	error("Can't make pipe");
45713082428Sbill }
45813082428Sbill 
45913082428Sbill chkclob(cp)
46013082428Sbill 	register char *cp;
46113082428Sbill {
46213082428Sbill 	struct stat stb;
46313082428Sbill 
46413082428Sbill 	if (stat(cp, &stb) < 0)
46513082428Sbill 		return;
46613082428Sbill 	if ((stb.st_mode & S_IFMT) == S_IFCHR)
46713082428Sbill 		return;
46813082428Sbill 	error("%s: File exists", cp);
46913082428Sbill }
470