Home | History | Annotate | Download | only in csh
      1    0  stevel /*
      2  356  muffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
      3    0  stevel  * Use is subject to license terms.
      4    0  stevel  */
      5    0  stevel 
      6    0  stevel /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
      7    0  stevel /*	  All Rights Reserved  	*/
      8    0  stevel 
      9    0  stevel /*
     10    0  stevel  * Copyright (c) 1980 Regents of the University of California.
     11    0  stevel  * All rights reserved. The Berkeley Software License Agreement
     12    0  stevel  * specifies the terms and conditions for redistribution.
     13    0  stevel  */
     14    0  stevel 
     15    0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     16    0  stevel 
     17    0  stevel #include <unistd.h>
     18    0  stevel #include <fcntl.h>
     19    0  stevel #include "sh.h"
     20    0  stevel #include "sh.proc.h"
     21    0  stevel #include "sh.tconst.h"
     22    0  stevel 
     23    0  stevel /*
     24    0  stevel  * C shell
     25    0  stevel  */
     26    0  stevel 
     27  356  muffin void	doio(struct command *, int *, int *);
     28  356  muffin void	mypipe(int *);
     29  356  muffin void	chkclob(tchar *);
     30  356  muffin 
     31    0  stevel /*
     32    0  stevel  * Return true if there is a back-quote (`) anywhere in the argument list.
     33    0  stevel  * Its presence would cause glob() to be invoked in the child process
     34    0  stevel  * and this would cause chaos if the child is created with vfork().
     35    0  stevel  */
     36    0  stevel static bool
     37    0  stevel AnyBquote(struct command *t)
     38    0  stevel {
     39    0  stevel 	tchar **pp;
     40    0  stevel 	tchar *p;
     41    0  stevel 
     42    0  stevel 	if (noexec)
     43    0  stevel 		return (0);
     44    0  stevel 	for (pp = t->t_dcom; p = *pp++;) {
     45    0  stevel 		if (any('`', p))
     46    0  stevel 			return (1);
     47    0  stevel 	}
     48    0  stevel 	return (0);
     49    0  stevel }
     50    0  stevel 
     51    0  stevel /*VARARGS 1*/
     52  356  muffin void
     53    0  stevel execute(t, wanttty, pipein, pipeout)
     54  356  muffin 	struct command *t;
     55    0  stevel 	int wanttty, *pipein, *pipeout;
     56    0  stevel {
     57    0  stevel 	bool forked = 0;
     58    0  stevel 	struct biltins *bifunc;
     59    0  stevel 	int pid = 0;
     60    0  stevel 	int pv[2];
     61    0  stevel 	extern int globcnt;
     62    0  stevel #ifdef TRACE
     63    0  stevel 	tprintf("TRACE- execute()\n");
     64    0  stevel #endif
     65    0  stevel 
     66    0  stevel 	if (t == 0)
     67    0  stevel 		return;
     68    0  stevel 	if ((t->t_dflg & FAND) && wanttty > 0)
     69    0  stevel 		wanttty = 0;
     70    0  stevel 	switch (t->t_dtyp) {
     71    0  stevel 
     72    0  stevel 	case TCOM:
     73    0  stevel 		if (t->t_dcom[0][0] == (tchar)S_TOPBIT[0])
     74    0  stevel 			(void) strcpy_(t->t_dcom[0], t->t_dcom[0] + 1);
     75    0  stevel 		if ((t->t_dflg & FREDO) == 0)
     76    0  stevel 			Dfix(t);		/* $ " ' \ */
     77    0  stevel 		if (t->t_dcom[0] == 0)
     78    0  stevel 			return;
     79    0  stevel 		/* fall into... */
     80    0  stevel 
     81    0  stevel 	case TPAR:
     82    0  stevel 		if (t->t_dflg & FPOU)
     83    0  stevel 			mypipe(pipeout);
     84    0  stevel 		/*
     85    0  stevel 		 * Must do << early so parent will know
     86    0  stevel 		 * where input pointer should be.
     87    0  stevel 		 * If noexec then this is all we do.
     88    0  stevel 		 */
     89    0  stevel 		if (t->t_dflg & FHERE) {
     90    0  stevel 			(void) close(0);
     91    0  stevel 			unsetfd(0);
     92    0  stevel 			heredoc(t->t_dlef);
     93    0  stevel 			if (noexec) {
     94    0  stevel 				(void) close(0);
     95    0  stevel 				unsetfd(0);
     96    0  stevel 			}
     97    0  stevel 		}
     98    0  stevel 		if (noexec)
     99    0  stevel 			break;
    100    0  stevel 
    101    0  stevel 		set(S_status, S_0);
    102    0  stevel 
    103    0  stevel 		/*
    104    0  stevel 		 * This mess is the necessary kludge to handle the prefix
    105    0  stevel 		 * builtins: nice, nohup, time.  These commands can also
    106    0  stevel 		 * be used by themselves, and this is not handled here.
    107    0  stevel 		 * This will also work when loops are parsed.
    108    0  stevel 		 */
    109    0  stevel 		while (t->t_dtyp == TCOM)
    110    0  stevel 			if (eq(t->t_dcom[0], S_nice /*"nice"*/))
    111    0  stevel 				if (t->t_dcom[1])
    112    0  stevel 					/*if (any(t->t_dcom[1][0], "+-"))*/
    113    0  stevel 					if (t->t_dcom[1][0] == '+' ||
    114    0  stevel 					    t->t_dcom[1][0] == '-')
    115    0  stevel 						if (t->t_dcom[2]) {
    116    0  stevel 							setname(S_nice /*"nice"*/);
    117    0  stevel 							t->t_nice = getn(t->t_dcom[1]);
    118    0  stevel 							lshift(t->t_dcom, 2);
    119    0  stevel 							t->t_dflg |= FNICE;
    120    0  stevel 						} else
    121    0  stevel 							break;
    122    0  stevel 					else {
    123    0  stevel 						t->t_nice = 4;
    124    0  stevel 						lshift(t->t_dcom, 1);
    125    0  stevel 						t->t_dflg |= FNICE;
    126    0  stevel 					}
    127    0  stevel 				else
    128    0  stevel 					break;
    129    0  stevel 			else if (eq(t->t_dcom[0], S_nohup /*"nohup"*/))
    130    0  stevel 				if (t->t_dcom[1]) {
    131    0  stevel 					t->t_dflg |= FNOHUP;
    132    0  stevel 					lshift(t->t_dcom, 1);
    133    0  stevel 				} else
    134    0  stevel 					break;
    135    0  stevel 			else if (eq(t->t_dcom[0], S_time /*"time"*/))
    136    0  stevel 				if (t->t_dcom[1]) {
    137    0  stevel 					t->t_dflg |= FTIME;
    138    0  stevel 					lshift(t->t_dcom, 1);
    139    0  stevel 				} else
    140    0  stevel 					break;
    141    0  stevel 			else
    142    0  stevel 				break;
    143    0  stevel 		/*
    144    0  stevel 		 * Check if we have a builtin function and remember which one.
    145    0  stevel 		 */
    146    0  stevel 		bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
    147    0  stevel 
    148    0  stevel 		/*
    149    0  stevel 		 * We fork only if we are timed, or are not the end of
    150    0  stevel 		 * a parenthesized list and not a simple builtin function.
    151    0  stevel 		 * Simple meaning one that is not pipedout, niced, nohupped,
    152    0  stevel 		 * or &'d.
    153    0  stevel 		 * It would be nice(?) to not fork in some of these cases.
    154    0  stevel 		 */
    155    0  stevel 		if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
    156    0  stevel 		     (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
    157    0  stevel #ifdef VFORK
    158    0  stevel 		    if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) ||
    159    0  stevel 			bifunc || AnyBquote(t))
    160    0  stevel #endif
    161    0  stevel 			{ forked++; pid = pfork(t, wanttty); }
    162    0  stevel #ifdef VFORK
    163    0  stevel 		    else {
    164    0  stevel 			void vffree();
    165    0  stevel 			struct sv {
    166    0  stevel 				int mask, child, setintr, haderr, didfds;
    167    0  stevel 				int SHIN, SHOUT, SHDIAG, OLDSTD, tpgrp;
    168    0  stevel 				struct sigvec sigv;
    169    0  stevel 			} sv;
    170    0  stevel 
    171    0  stevel 			/*
    172    0  stevel 			 * Prepare for the vfork by saving everything
    173    0  stevel 			 * that the child corrupts before it exec's.
    174    0  stevel 			 * Note that in some signal implementations
    175    0  stevel 			 * which keep the signal info in user space
    176    0  stevel 			 * (e.g. Sun's) it will also be necessary to
    177    0  stevel  			 * save and restore the current sigvec's for
    178    0  stevel 			 * the signals the child touches before it
    179    0  stevel 			 * exec's.
    180    0  stevel 			 */
    181    0  stevel 			sv.mask = sigblock(sigmask(SIGCHLD));
    182    0  stevel 			sv.child = child; sv.setintr = setintr;
    183    0  stevel 			sv.haderr = haderr; sv.didfds = didfds;
    184    0  stevel 			sv.SHIN = SHIN; sv.SHOUT = SHOUT;
    185    0  stevel 			sv.SHDIAG = SHDIAG; sv.OLDSTD = OLDSTD;
    186    0  stevel 			sv.tpgrp = tpgrp;
    187    0  stevel 			Vsav = Vdp = 0; Vav = 0;
    188    0  stevel 			(void) sigvec(SIGINT, (struct sigvec *)0, &sv.sigv);
    189    0  stevel 			pid = vfork();
    190    0  stevel 			if (pid < 0) {
    191    0  stevel 				(void) sigsetmask(sv.mask);
    192    0  stevel 				error("Vfork failed");
    193    0  stevel 			}
    194    0  stevel 			forked++;
    195    0  stevel 			if (pid) {	/* parent */
    196    0  stevel 				int ppid;
    197    0  stevel 				closelog();
    198    0  stevel 				child = sv.child; setintr = sv.setintr;
    199    0  stevel 				haderr = sv.haderr; didfds = sv.didfds;
    200    0  stevel 				SHIN = sv.SHIN;
    201    0  stevel 				SHOUT = sv.SHOUT; SHDIAG = sv.SHDIAG;
    202    0  stevel 				OLDSTD = sv.OLDSTD; tpgrp = sv.tpgrp;
    203    0  stevel 				xfree(Vsav); Vsav = 0;
    204    0  stevel 				xfree(Vdp); Vdp = 0;
    205    0  stevel 				xfree( (tchar *)Vav); Vav = 0;
    206    0  stevel 				/* this is from pfork() */
    207    0  stevel 				ppid = pcurrjob ? pcurrjob->p_jobid : pid;
    208    0  stevel 				if (wanttty >= 0 && tpgrp >= 0)
    209    0  stevel 					setpgid (ppid, ppid);
    210    0  stevel 				palloc(pid, t);
    211    0  stevel 				/*
    212    0  stevel 				 * Restore SIGINT handler.
    213    0  stevel 				 */
    214    0  stevel 				(void) sigvec(SIGINT, &sv.sigv, (struct sigvec *)0);
    215    0  stevel 				(void) sigsetmask(sv.mask);
    216    0  stevel 			} else {	/* child */
    217    0  stevel 				/* this is from pfork() */
    218    0  stevel 				int pgrp;
    219    0  stevel 				bool ignint = 0;
    220    0  stevel 				int sigttou;
    221    0  stevel 				if (setintr)
    222    0  stevel 					ignint =
    223    0  stevel 					    (tpgrp == -1 && (t->t_dflg&FINT))
    224    0  stevel 					    || gointr
    225    0  stevel 						&& eq(gointr, S_MINUS/*"-"*/);
    226    0  stevel 				pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
    227    0  stevel 				child++;
    228    0  stevel 				if (setintr) {
    229    0  stevel 					setintr = 0;
    230    0  stevel #ifdef notdef
    231    0  stevel 					(void) signal(SIGCHLD, SIG_DFL);
    232    0  stevel #endif
    233    0  stevel 					(void) signal(SIGINT, ignint ?
    234    0  stevel 						SIG_IGN : vffree);
    235    0  stevel 					(void) signal(SIGQUIT, ignint ?
    236    0  stevel 						SIG_IGN : SIG_DFL);
    237    0  stevel 					if (wanttty >= 0) {
    238    0  stevel 						(void) signal(SIGTSTP, SIG_DFL);
    239    0  stevel 						(void) signal(SIGTTIN, SIG_DFL);
    240    0  stevel 						(void) signal(SIGTTOU, SIG_DFL);
    241    0  stevel 					}
    242    0  stevel 					(void) signal(SIGTERM, parterm);
    243    0  stevel 				} else if (tpgrp == -1 && (t->t_dflg&FINT)) {
    244    0  stevel 					(void) signal(SIGINT, SIG_IGN);
    245    0  stevel 					(void) signal(SIGQUIT, SIG_IGN);
    246    0  stevel 				}
    247    0  stevel 				if (wanttty >= 0 && tpgrp >= 0)
    248    0  stevel 					(void) setpgid(0, pgrp);
    249    0  stevel 				if (wanttty > 0) {
    250    0  stevel 					sigttou = sigblock (
    251    0  stevel 						sigmask(SIGTTOU) |
    252    0  stevel 						sigmask(SIGTTIN) |
    253    0  stevel 						sigmask(SIGTSTP));
    254    0  stevel 					(void) ioctl(FSHTTY, TIOCSPGRP,
    255    0  stevel 						 (tchar *)&pgrp);
    256    0  stevel 					sigsetmask (sigttou);
    257    0  stevel 				}
    258    0  stevel 				if (tpgrp > 0)
    259    0  stevel 					tpgrp = 0;
    260    0  stevel 				if (t->t_dflg & FNOHUP)
    261    0  stevel 					(void) signal(SIGHUP, SIG_IGN);
    262    0  stevel 				if (t->t_dflg & FNICE)
    263    0  stevel 					(void) setpriority(PRIO_PROCESS,
    264    0  stevel 						0, t->t_nice);
    265    0  stevel 			}
    266    0  stevel 
    267    0  stevel 		    }
    268    0  stevel #endif
    269    0  stevel 		if (pid != 0) {
    270    0  stevel 			/*
    271    0  stevel 			 * It would be better if we could wait for the
    272    0  stevel 			 * whole job when we knew the last process
    273    0  stevel 			 * had been started.  Pwait, in fact, does
    274    0  stevel 			 * wait for the whole job anyway, but this test
    275    0  stevel 			 * doesn't really express our intentions.
    276    0  stevel 			 */
    277    0  stevel 			if (didfds==0 && t->t_dflg&FPIN) {
    278    0  stevel 				(void) close(pipein[0]);
    279    0  stevel 				unsetfd(pipein[0]);
    280    0  stevel 				(void) close(pipein[1]);
    281    0  stevel 				unsetfd(pipein[1]);
    282    0  stevel 			}
    283    0  stevel 			if ((t->t_dflg & (FPOU|FAND)) == 0)
    284    0  stevel 				pwait();
    285    0  stevel 			break;
    286    0  stevel 		}
    287    0  stevel 		doio(t, pipein, pipeout);
    288    0  stevel 		if (t->t_dflg & FPOU) {
    289    0  stevel 			(void) close(pipeout[0]);
    290    0  stevel 			(void) unsetfd(pipeout[0]);
    291    0  stevel 			(void) close(pipeout[1]);
    292    0  stevel 			(void) unsetfd(pipeout[1]);
    293    0  stevel 		}
    294    0  stevel 
    295    0  stevel 		/*
    296    0  stevel 		 * Perform a builtin function.
    297    0  stevel 		 * If we are not forked, arrange for possible stopping
    298    0  stevel 		 */
    299    0  stevel 		if (bifunc) {
    300    0  stevel 			func(t, bifunc);
    301    0  stevel 			if (forked)
    302    0  stevel 				exitstat();
    303    0  stevel 			break;
    304    0  stevel 		}
    305    0  stevel 		if (t->t_dtyp != TPAR) {
    306    0  stevel 			doexec(t);
    307    0  stevel 			/*NOTREACHED*/
    308    0  stevel 		}
    309    0  stevel 		/*
    310    0  stevel 		 * For () commands must put new 0,1,2 in FSH* and recurse
    311    0  stevel 		 */
    312    0  stevel 		OLDSTD = dcopy(0, FOLDSTD);
    313    0  stevel 		SHOUT = dcopy(1, FSHOUT);
    314    0  stevel 		SHDIAG = dcopy(2, FSHDIAG);
    315    0  stevel 		(void) close(SHIN);
    316    0  stevel 		(void) unsetfd(SHIN);
    317    0  stevel 		SHIN = -1;
    318    0  stevel 		didfds = 0;
    319    0  stevel 		wanttty = -1;
    320    0  stevel 		t->t_dspr->t_dflg |= t->t_dflg & FINT;
    321    0  stevel 		execute(t->t_dspr, wanttty);
    322    0  stevel 		exitstat();
    323    0  stevel 
    324    0  stevel 	case TFIL:
    325    0  stevel 		t->t_dcar->t_dflg |= FPOU |
    326    0  stevel 		    (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
    327    0  stevel 		execute(t->t_dcar, wanttty, pipein, pv);
    328    0  stevel 		t->t_dcdr->t_dflg |= FPIN |
    329    0  stevel 		    (t->t_dflg & (FPOU|FAND|FPAR|FINT));
    330    0  stevel 		if (wanttty > 0)
    331    0  stevel 			wanttty = 0;		/* got tty already */
    332    0  stevel 		execute(t->t_dcdr, wanttty, pv, pipeout);
    333    0  stevel 		break;
    334    0  stevel 
    335    0  stevel 	case TLST:
    336    0  stevel 		if (t->t_dcar) {
    337    0  stevel 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
    338    0  stevel 			execute(t->t_dcar, wanttty);
    339    0  stevel 			/*
    340    0  stevel 			 * In strange case of A&B make a new job after A
    341    0  stevel 			 */
    342    0  stevel 			if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
    343    0  stevel 			    (t->t_dcdr->t_dflg&FAND) == 0)
    344    0  stevel 				pendjob();
    345    0  stevel 		}
    346    0  stevel 		if (t->t_dcdr) {
    347    0  stevel 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
    348    0  stevel 			execute(t->t_dcdr, wanttty);
    349    0  stevel 		}
    350    0  stevel 		break;
    351    0  stevel 
    352    0  stevel 	case TOR:
    353    0  stevel 	case TAND:
    354    0  stevel 		if (t->t_dcar) {
    355    0  stevel 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
    356    0  stevel 			execute(t->t_dcar, wanttty);
    357    0  stevel 			if ((getn(value(S_status/*"status"*/)) == 0) != (t->t_dtyp == TAND))
    358    0  stevel 				return;
    359    0  stevel 		}
    360    0  stevel 		if (t->t_dcdr) {
    361    0  stevel 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
    362    0  stevel 			execute(t->t_dcdr, wanttty);
    363    0  stevel 		}
    364    0  stevel 		break;
    365    0  stevel 	}
    366    0  stevel 	/*
    367    0  stevel 	 * Fall through for all breaks from switch
    368    0  stevel 	 *
    369    0  stevel 	 * If there will be no more executions of this
    370    0  stevel 	 * command, flush all file descriptors.
    371    0  stevel 	 * Places that turn on the FREDO bit are responsible
    372    0  stevel 	 * for doing donefds after the last re-execution
    373    0  stevel 	 */
    374    0  stevel 	if (didfds && !(t->t_dflg & FREDO))
    375    0  stevel 		donefds();
    376    0  stevel 
    377    0  stevel 	/*
    378    0  stevel 	 * If glob() was called and arguments list is not yet
    379    0  stevel 	 * free'ed, free them here.
    380    0  stevel 	 */
    381    0  stevel 	if (gargv) {
    382    0  stevel 		blkfree(gargv);
    383    0  stevel 		gargv = 0;
    384    0  stevel 		globcnt = 0;
    385    0  stevel 	}
    386    0  stevel }
    387    0  stevel 
    388    0  stevel #ifdef VFORK
    389    0  stevel void
    390  356  muffin vffree(void)
    391    0  stevel {
    392  356  muffin 	tchar **v;
    393    0  stevel 
    394    0  stevel #ifdef TRACE
    395    0  stevel 	tprintf("TRACE- vffree()\n");
    396    0  stevel #endif
    397    0  stevel 	if (v = gargv)
    398    0  stevel 		gargv = 0, xfree( (tchar *)v);
    399    0  stevel 	if (v = pargv)
    400    0  stevel 		pargv = 0, xfree( (tchar *)v);
    401    0  stevel 	_exit(1);
    402    0  stevel }
    403    0  stevel #endif
    404    0  stevel 
    405    0  stevel /*
    406    0  stevel  * Perform io redirection.
    407    0  stevel  * We may or maynot be forked here.
    408    0  stevel  */
    409  356  muffin void
    410  356  muffin doio(struct command *t, int *pipein, int *pipeout)
    411    0  stevel {
    412  356  muffin 	tchar *cp, *dp;
    413  356  muffin 	int flags = t->t_dflg;
    414    0  stevel 	int fd;
    415    0  stevel 
    416    0  stevel #ifdef TRACE
    417    0  stevel 	tprintf("TRACE- doio()\n");
    418    0  stevel #endif
    419    0  stevel 	if (didfds || (flags & FREDO))
    420    0  stevel 		return;
    421    0  stevel 	if ((flags & FHERE) == 0) {	/* FHERE already done */
    422    0  stevel 		(void) close(0);
    423    0  stevel 		(void) unsetfd(0);
    424    0  stevel 		if (cp = t->t_dlef) {
    425    0  stevel 			dp = Dfix1(cp);
    426    0  stevel 			cp = globone(dp);
    427    0  stevel 			xfree(dp);
    428    0  stevel 			xfree(cp);
    429    0  stevel 			if (open_(cp, 0) < 0)
    430    0  stevel 				Perror(cp);
    431    0  stevel 		} else if (flags & FPIN) {
    432    0  stevel 			fd = dup(pipein[0]);
    433    0  stevel 			if (fd != -1)
    434    0  stevel 				setfd(fd);
    435    0  stevel 			(void) close(pipein[0]);
    436    0  stevel 			(void) unsetfd(pipein[0]);
    437    0  stevel 			(void) close(pipein[1]);
    438    0  stevel 			(void) unsetfd(pipein[1]);
    439    0  stevel 		} else if ((flags & FINT) && tpgrp == -1) {
    440    0  stevel 			(void) close(0);	/* no need for unsetfd */
    441    0  stevel 			(void) open("/dev/null", 0); /* no need for setfd */
    442    0  stevel 		} else {
    443    0  stevel 			fd = dup(OLDSTD);
    444    0  stevel 			if (fd != -1)
    445    0  stevel 				setfd(fd);
    446    0  stevel 		}
    447    0  stevel 	}
    448    0  stevel 	(void) close(1);
    449    0  stevel 	(void) unsetfd(1);
    450    0  stevel 	if (cp = t->t_drit) {
    451    0  stevel 		dp = Dfix1(cp);
    452    0  stevel 		cp = globone(dp);
    453    0  stevel 		xfree(dp);
    454    0  stevel 		if ((flags & FCAT) && open_(cp, 1) >= 0)
    455    0  stevel 			(void) lseek(1, (off_t)0, 2);
    456    0  stevel 		else {
    457    0  stevel 			if (!(flags & FANY) && adrof(S_noclobber/*"noclobber"*/)) {
    458    0  stevel 				if (flags & FCAT)
    459    0  stevel 					Perror(cp);
    460    0  stevel 				chkclob(cp);
    461    0  stevel 			}
    462    0  stevel 			if (creat_(cp, 0666) < 0)
    463    0  stevel 				Perror(cp);
    464    0  stevel 		}
    465    0  stevel 		xfree(cp);
    466    0  stevel 	} else if (flags & FPOU) {
    467    0  stevel 		fd = dup(pipeout[1]);
    468    0  stevel 		if (fd != -1)
    469    0  stevel 			setfd (fd);
    470    0  stevel 	}
    471    0  stevel 	else {
    472    0  stevel 		fd = dup(SHOUT);
    473    0  stevel 		if (fd != -1)
    474    0  stevel 			setfd(fd);
    475    0  stevel 	}
    476    0  stevel 
    477    0  stevel 	(void) close(2);
    478    0  stevel 	(void) unsetfd(2);
    479    0  stevel 	if (flags & FDIAG) {
    480    0  stevel 		fd = dup(1);
    481    0  stevel 		if (fd != -1)
    482    0  stevel 			setfd(fd);
    483    0  stevel 	}
    484    0  stevel 	else {
    485    0  stevel 		fd = dup(SHDIAG);
    486    0  stevel 		if (fd != -1)
    487    0  stevel 			setfd(fd);
    488    0  stevel 	}
    489    0  stevel 	didfds = 1;
    490    0  stevel }
    491    0  stevel 
    492  356  muffin void
    493  356  muffin mypipe(int *pv)
    494    0  stevel {
    495    0  stevel 
    496    0  stevel #ifdef TRACE
    497    0  stevel 	tprintf("TRACE- mypipe()\n");
    498    0  stevel #endif
    499    0  stevel 	if (pipe(pv) < 0)
    500    0  stevel 		goto oops;
    501    0  stevel 	setfd(pv[0]);
    502    0  stevel 	setfd(pv[1]);
    503    0  stevel 
    504    0  stevel 	pv[0] = dmove(pv[0], -1);
    505    0  stevel 	pv[1] = dmove(pv[1], -1);
    506    0  stevel 	if (pv[0] >= 0 && pv[1] >= 0)
    507    0  stevel 		return;
    508    0  stevel oops:
    509    0  stevel 	error("Can't make pipe");
    510    0  stevel }
    511    0  stevel 
    512  356  muffin void
    513  356  muffin chkclob(tchar *cp)
    514    0  stevel {
    515    0  stevel 	struct stat stb;
    516    0  stevel 	unsigned short	type;
    517    0  stevel 
    518    0  stevel #ifdef TRACE
    519    0  stevel 	tprintf("TRACE- chkclob()\n");
    520    0  stevel #endif
    521    0  stevel 	if (stat_(cp, &stb) < 0)
    522    0  stevel 		return;
    523    0  stevel 	type = stb.st_mode & S_IFMT;
    524    0  stevel 	if (type == S_IFCHR || type == S_IFIFO)
    525    0  stevel 		return;
    526    0  stevel 	error("%t: File exists", cp);
    527    0  stevel }
    528