1d6fabe6eSbostic /*- 2d6fabe6eSbostic * Copyright (c) 1980, 1991 The Regents of the University of California. 3d6fabe6eSbostic * All rights reserved. 4d6fabe6eSbostic * 5d6fabe6eSbostic * %sccs.include.redist.c% 6c1549ed3Sdist */ 7c1549ed3Sdist 843fabe3fSedward #ifndef lint 9*336c1b24Schristos static char sccsid[] = "@(#)sem.c 5.20 (Berkeley) 09/04/91"; 10d6fabe6eSbostic #endif /* not lint */ 1113082428Sbill 129374f148Sbostic #include <sys/param.h> 139374f148Sbostic #include <sys/ioctl.h> 149374f148Sbostic #include <sys/stat.h> 159374f148Sbostic #include <errno.h> 169374f148Sbostic #include <fcntl.h> 179374f148Sbostic #include <stdlib.h> 189374f148Sbostic #include <string.h> 199374f148Sbostic #include <unistd.h> 20c1ce954aSchristos #if __STDC__ 21c1ce954aSchristos # include <stdarg.h> 22c1ce954aSchristos #else 23c1ce954aSchristos # include <varargs.h> 24c1ce954aSchristos #endif 25c1ce954aSchristos 26afc71901Sbostic #include "csh.h" 27afc71901Sbostic #include "proc.h" 28afc71901Sbostic #include "extern.h" 29f3328da7Sbostic 3023ceb1ffSchristos static void vffree __P((int)); 3123ceb1ffSchristos static void doio __P((struct command *t, int *, int *)); 32e78a8ca9Schristos static void chkclob __P((char *)); 3313082428Sbill 34f3328da7Sbostic void 3513082428Sbill execute(t, wanttty, pipein, pipeout) 3613082428Sbill register struct command *t; 3713082428Sbill int wanttty, *pipein, *pipeout; 3813082428Sbill { 3913082428Sbill bool forked = 0; 4013082428Sbill struct biltins *bifunc; 4113082428Sbill int pid = 0; 4213082428Sbill int pv[2]; 4313082428Sbill 449374f148Sbostic static sigset_t csigmask; 45f3328da7Sbostic 469374f148Sbostic static sigset_t ocsigmask; 47f3328da7Sbostic static int onosigchld = 0; 48f3328da7Sbostic static int nosigchld = 0; 49f3328da7Sbostic 5013082428Sbill if (t == 0) 5113082428Sbill return; 52f3328da7Sbostic 53f3328da7Sbostic if (t->t_dflg & F_AMPERSAND) 5413082428Sbill wanttty = 0; 5513082428Sbill switch (t->t_dtyp) { 5613082428Sbill 575eb3278cSbostic case NODE_COMMAND: 5813082428Sbill if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 59f3328da7Sbostic (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 605eb3278cSbostic if ((t->t_dflg & F_REPEAT) == 0) 6113082428Sbill Dfix(t); /* $ " ' \ */ 6213082428Sbill if (t->t_dcom[0] == 0) 6313082428Sbill return; 6413082428Sbill /* fall into... */ 6513082428Sbill 665eb3278cSbostic case NODE_PAREN: 675eb3278cSbostic if (t->t_dflg & F_PIPEOUT) 6813082428Sbill mypipe(pipeout); 6913082428Sbill /* 70f3328da7Sbostic * Must do << early so parent will know where input pointer should be. 7113082428Sbill * If noexec then this is all we do. 7213082428Sbill */ 735eb3278cSbostic if (t->t_dflg & F_READ) { 7443fabe3fSedward (void) close(0); 7513082428Sbill heredoc(t->t_dlef); 7613082428Sbill if (noexec) 7743fabe3fSedward (void) close(0); 7813082428Sbill } 7913082428Sbill 80f3328da7Sbostic set(STRstatus, Strsave(STR0)); 8113082428Sbill 8213082428Sbill /* 83f3328da7Sbostic * This mess is the necessary kludge to handle the prefix builtins: 84f3328da7Sbostic * nice, nohup, time. These commands can also be used by themselves, 85f3328da7Sbostic * and this is not handled here. This will also work when loops are 86f3328da7Sbostic * parsed. 8713082428Sbill */ 885eb3278cSbostic while (t->t_dtyp == NODE_COMMAND) 89f3328da7Sbostic if (eq(t->t_dcom[0], STRnice)) 9013082428Sbill if (t->t_dcom[1]) 91f3328da7Sbostic if (strchr("+-", t->t_dcom[1][0])) 9213082428Sbill if (t->t_dcom[2]) { 9313082428Sbill setname("nice"); 94f3328da7Sbostic t->t_nice = 95f3328da7Sbostic getn(t->t_dcom[1]); 9613082428Sbill lshift(t->t_dcom, 2); 975eb3278cSbostic t->t_dflg |= F_NICE; 98f3328da7Sbostic } 99f3328da7Sbostic else 10013082428Sbill break; 10113082428Sbill else { 10213082428Sbill t->t_nice = 4; 10313082428Sbill lshift(t->t_dcom, 1); 1045eb3278cSbostic t->t_dflg |= F_NICE; 10513082428Sbill } 10613082428Sbill else 10713082428Sbill break; 108f3328da7Sbostic else if (eq(t->t_dcom[0], STRnohup)) 10913082428Sbill if (t->t_dcom[1]) { 1105eb3278cSbostic t->t_dflg |= F_NOHUP; 11113082428Sbill lshift(t->t_dcom, 1); 112f3328da7Sbostic } 113f3328da7Sbostic else 11413082428Sbill break; 115f3328da7Sbostic else if (eq(t->t_dcom[0], STRtime)) 11613082428Sbill if (t->t_dcom[1]) { 1175eb3278cSbostic t->t_dflg |= F_TIME; 11813082428Sbill lshift(t->t_dcom, 1); 119f3328da7Sbostic } 120f3328da7Sbostic else 12113082428Sbill break; 12213082428Sbill else 12313082428Sbill break; 124f3328da7Sbostic 125*336c1b24Schristos /* is it a command */ 126f3328da7Sbostic if (t->t_dtyp == NODE_COMMAND) { 12713082428Sbill /* 12813082428Sbill * Check if we have a builtin function and remember which one. 12913082428Sbill */ 130f3328da7Sbostic bifunc = isbfunc(t); 131*336c1b24Schristos if (noexec) { 132*336c1b24Schristos /* 133*336c1b24Schristos * Continue for builtins that are part of the scripting language 134*336c1b24Schristos */ 135*336c1b24Schristos if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin && 136*336c1b24Schristos bifunc->bfunct != doelse && bifunc->bfunct != doend && 137*336c1b24Schristos bifunc->bfunct != doforeach && bifunc->bfunct != dogoto && 138*336c1b24Schristos bifunc->bfunct != doif && bifunc->bfunct != dorepeat && 139*336c1b24Schristos bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch && 140*336c1b24Schristos bifunc->bfunct != dowhile && bifunc->bfunct != dozip) 141*336c1b24Schristos break; 142*336c1b24Schristos } 143f3328da7Sbostic } 144f3328da7Sbostic else { /* not a command */ 1459374f148Sbostic bifunc = NULL; 146*336c1b24Schristos if (noexec) 147*336c1b24Schristos break; 148f3328da7Sbostic } 14913082428Sbill 15013082428Sbill /* 151f3328da7Sbostic * We fork only if we are timed, or are not the end of a parenthesized 152f3328da7Sbostic * list and not a simple builtin function. Simple meaning one that is 153f3328da7Sbostic * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 154f3328da7Sbostic * fork in some of these cases. 15513082428Sbill */ 156f3328da7Sbostic /* 157f3328da7Sbostic * Prevent forking cd, pushd, popd, chdir cause this will cause the 158f3328da7Sbostic * shell not to change dir! 159f3328da7Sbostic */ 160f3328da7Sbostic if (bifunc && (bifunc->bfunct == dochngd || 161f3328da7Sbostic bifunc->bfunct == dopushd || 162f3328da7Sbostic bifunc->bfunct == dopopd)) 163f3328da7Sbostic t->t_dflg &= ~(F_NICE); 1645eb3278cSbostic if (((t->t_dflg & F_TIME) || (t->t_dflg & F_NOFORK) == 0 && 165f3328da7Sbostic (!bifunc || t->t_dflg & 166f3328da7Sbostic (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP))) || 167f3328da7Sbostic /* 168f3328da7Sbostic * We have to fork for eval too. 169f3328da7Sbostic */ 170cce51c35Schristos (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 && 171f3328da7Sbostic bifunc->bfunct == doeval)) 1725eb3278cSbostic if (t->t_dtyp == NODE_PAREN || 173afc71901Sbostic t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) { 174f3328da7Sbostic forked++; 175f3328da7Sbostic /* 176f3328da7Sbostic * We need to block SIGCHLD here, so that if the process does 177f3328da7Sbostic * not die before we can set the process group 178f3328da7Sbostic */ 1795e5c7fccSmarc if (wanttty >= 0 && !nosigchld) { 180f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 1815e5c7fccSmarc nosigchld = 1; 1825e5c7fccSmarc } 1835e5c7fccSmarc 1845e5c7fccSmarc pid = pfork(t, wanttty); 1855e5c7fccSmarc if (pid == 0 && nosigchld) { 186f3328da7Sbostic (void) sigsetmask(csigmask); 1875e5c7fccSmarc nosigchld = 0; 1885e5c7fccSmarc } 1895e5c7fccSmarc } 19013082428Sbill else { 19143fabe3fSedward int ochild, osetintr, ohaderr, odidfds; 192cce51c35Schristos int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp; 1939374f148Sbostic sigset_t omask; 19413082428Sbill 19515d9e91aSlepreau /* 196f3328da7Sbostic * Prepare for the vfork by saving everything that the child 197f3328da7Sbostic * corrupts before it exec's. Note that in some signal 198f3328da7Sbostic * implementations which keep the signal info in user space 199f3328da7Sbostic * (e.g. Sun's) it will also be necessary to save and restore 200f3328da7Sbostic * the current sigvec's for the signals the child touches 201f3328da7Sbostic * before it exec's. 20215d9e91aSlepreau */ 2035e5c7fccSmarc if (wanttty >= 0 && !nosigchld && !noexec) { 204f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 2055e5c7fccSmarc nosigchld = 1; 2065e5c7fccSmarc } 207f3328da7Sbostic omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT)); 208f3328da7Sbostic ochild = child; 209f3328da7Sbostic osetintr = setintr; 210f3328da7Sbostic ohaderr = haderr; 211f3328da7Sbostic odidfds = didfds; 212f3328da7Sbostic oSHIN = SHIN; 213f3328da7Sbostic oSHOUT = SHOUT; 214cce51c35Schristos oSHERR = SHERR; 215f3328da7Sbostic oOLDSTD = OLDSTD; 216f3328da7Sbostic otpgrp = tpgrp; 217f3328da7Sbostic ocsigmask = csigmask; 218f3328da7Sbostic onosigchld = nosigchld; 219f3328da7Sbostic Vsav = Vdp = 0; 220f3328da7Sbostic Vexpath = 0; 221f3328da7Sbostic Vt = 0; 22213082428Sbill pid = vfork(); 223f3328da7Sbostic 22413082428Sbill if (pid < 0) { 22543fabe3fSedward (void) sigsetmask(omask); 226f3328da7Sbostic stderror(ERR_NOPROC); 22713082428Sbill } 22813082428Sbill forked++; 22915d9e91aSlepreau if (pid) { /* parent */ 230f3328da7Sbostic child = ochild; 231f3328da7Sbostic setintr = osetintr; 232f3328da7Sbostic haderr = ohaderr; 233f3328da7Sbostic didfds = odidfds; 23443fabe3fSedward SHIN = oSHIN; 235f3328da7Sbostic SHOUT = oSHOUT; 236cce51c35Schristos SHERR = oSHERR; 237f3328da7Sbostic OLDSTD = oOLDSTD; 238f3328da7Sbostic tpgrp = otpgrp; 239f3328da7Sbostic csigmask = ocsigmask; 240f3328da7Sbostic nosigchld = onosigchld; 241f3328da7Sbostic 242f3328da7Sbostic xfree((ptr_t) Vsav); 243f3328da7Sbostic Vsav = 0; 244f3328da7Sbostic xfree((ptr_t) Vdp); 245f3328da7Sbostic Vdp = 0; 246f3328da7Sbostic xfree((ptr_t) Vexpath); 247f3328da7Sbostic Vexpath = 0; 248f3328da7Sbostic blkfree((Char **) Vt); 249f3328da7Sbostic Vt = 0; 25013082428Sbill /* this is from pfork() */ 25113082428Sbill palloc(pid, t); 25243fabe3fSedward (void) sigsetmask(omask); 253f3328da7Sbostic } 254f3328da7Sbostic else { /* child */ 25513082428Sbill /* this is from pfork() */ 25613082428Sbill int pgrp; 25713082428Sbill bool ignint = 0; 25813082428Sbill 2595e5c7fccSmarc if (nosigchld) { 260f3328da7Sbostic (void) sigsetmask(csigmask); 2615e5c7fccSmarc nosigchld = 0; 2625e5c7fccSmarc } 263f3328da7Sbostic 26413082428Sbill if (setintr) 265f3328da7Sbostic ignint = 266f3328da7Sbostic (tpgrp == -1 && 267f3328da7Sbostic (t->t_dflg & F_NOINTERRUPT)) 268f3328da7Sbostic || gointr && eq(gointr, STRminus); 26913082428Sbill pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 27013082428Sbill child++; 27113082428Sbill if (setintr) { 27213082428Sbill setintr = 0; 273f3328da7Sbostic if (ignint) { 274f3328da7Sbostic (void) signal(SIGINT, SIG_IGN); 275f3328da7Sbostic (void) signal(SIGQUIT, SIG_IGN); 276f3328da7Sbostic } 277f3328da7Sbostic else { 278f3328da7Sbostic (void) signal(SIGINT, vffree); 279f3328da7Sbostic (void) signal(SIGQUIT, SIG_DFL); 280f3328da7Sbostic } 281f3328da7Sbostic 28213082428Sbill if (wanttty >= 0) { 28343fabe3fSedward (void) signal(SIGTSTP, SIG_DFL); 28443fabe3fSedward (void) signal(SIGTTIN, SIG_DFL); 28543fabe3fSedward (void) signal(SIGTTOU, SIG_DFL); 28613082428Sbill } 287f3328da7Sbostic 28843fabe3fSedward (void) signal(SIGTERM, parterm); 289f3328da7Sbostic } 290f3328da7Sbostic else if (tpgrp == -1 && 2915eb3278cSbostic (t->t_dflg & F_NOINTERRUPT)) { 29243fabe3fSedward (void) signal(SIGINT, SIG_IGN); 29343fabe3fSedward (void) signal(SIGQUIT, SIG_IGN); 29413082428Sbill } 295f3328da7Sbostic 296f3328da7Sbostic pgetty(wanttty, pgrp); 2975eb3278cSbostic if (t->t_dflg & F_NOHUP) 29843fabe3fSedward (void) signal(SIGHUP, SIG_IGN); 2995eb3278cSbostic if (t->t_dflg & F_NICE) 300f3328da7Sbostic (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 30113082428Sbill } 30213082428Sbill 30313082428Sbill } 30413082428Sbill if (pid != 0) { 30513082428Sbill /* 306f3328da7Sbostic * It would be better if we could wait for the whole job when we 307f3328da7Sbostic * knew the last process had been started. Pwait, in fact, does 308f3328da7Sbostic * wait for the whole job anyway, but this test doesn't really 309f3328da7Sbostic * express our intentions. 31013082428Sbill */ 3115eb3278cSbostic if (didfds == 0 && t->t_dflg & F_PIPEIN) { 31243fabe3fSedward (void) close(pipein[0]); 31343fabe3fSedward (void) close(pipein[1]); 31443fabe3fSedward } 3155eb3278cSbostic if ((t->t_dflg & F_PIPEOUT) == 0) { 3165e5c7fccSmarc if (nosigchld) { 317f3328da7Sbostic (void) sigsetmask(csigmask); 3185e5c7fccSmarc nosigchld = 0; 3195e5c7fccSmarc } 3205eb3278cSbostic if ((t->t_dflg & F_AMPERSAND) == 0) 32113082428Sbill pwait(); 3225e5c7fccSmarc } 32313082428Sbill break; 32413082428Sbill } 32513082428Sbill doio(t, pipein, pipeout); 3265eb3278cSbostic if (t->t_dflg & F_PIPEOUT) { 32743fabe3fSedward (void) close(pipeout[0]); 32843fabe3fSedward (void) close(pipeout[1]); 32943fabe3fSedward } 33013082428Sbill /* 331f3328da7Sbostic * Perform a builtin function. If we are not forked, arrange for 332f3328da7Sbostic * possible stopping 33313082428Sbill */ 33413082428Sbill if (bifunc) { 33513082428Sbill func(t, bifunc); 33613082428Sbill if (forked) 33713082428Sbill exitstat(); 33813082428Sbill break; 33913082428Sbill } 3405eb3278cSbostic if (t->t_dtyp != NODE_PAREN) { 341cce51c35Schristos doexec(NULL, t); 34213082428Sbill /* NOTREACHED */ 34313082428Sbill } 34413082428Sbill /* 34513082428Sbill * For () commands must put new 0,1,2 in FSH* and recurse 34613082428Sbill */ 34713082428Sbill OLDSTD = dcopy(0, FOLDSTD); 34813082428Sbill SHOUT = dcopy(1, FSHOUT); 349cce51c35Schristos SHERR = dcopy(2, FSHERR); 35043fabe3fSedward (void) close(SHIN); 35143fabe3fSedward SHIN = -1; 35243fabe3fSedward didfds = 0; 35313082428Sbill wanttty = -1; 3545eb3278cSbostic t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 355f3328da7Sbostic execute(t->t_dspr, wanttty, NULL, NULL); 35613082428Sbill exitstat(); 35713082428Sbill 3585eb3278cSbostic case NODE_PIPE: 3595eb3278cSbostic t->t_dcar->t_dflg |= F_PIPEOUT | 3605eb3278cSbostic (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 36113082428Sbill execute(t->t_dcar, wanttty, pipein, pv); 362f3328da7Sbostic t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 3635eb3278cSbostic (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 36413082428Sbill if (wanttty > 0) 36513082428Sbill wanttty = 0; /* got tty already */ 36613082428Sbill execute(t->t_dcdr, wanttty, pv, pipeout); 36713082428Sbill break; 36813082428Sbill 3695eb3278cSbostic case NODE_LIST: 37013082428Sbill if (t->t_dcar) { 3715eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 372f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 37313082428Sbill /* 37413082428Sbill * In strange case of A&B make a new job after A 37513082428Sbill */ 3765eb3278cSbostic if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 3775eb3278cSbostic (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 37813082428Sbill pendjob(); 37913082428Sbill } 38013082428Sbill if (t->t_dcdr) { 381f3328da7Sbostic t->t_dcdr->t_dflg |= t->t_dflg & 382f3328da7Sbostic (F_NOFORK | F_NOINTERRUPT); 383f3328da7Sbostic execute(t->t_dcdr, wanttty, NULL, NULL); 38413082428Sbill } 38513082428Sbill break; 38613082428Sbill 3875eb3278cSbostic case NODE_OR: 3885eb3278cSbostic case NODE_AND: 38913082428Sbill if (t->t_dcar) { 3905eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 391f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 392f3328da7Sbostic if ((getn(value(STRstatus)) == 0) != 3935eb3278cSbostic (t->t_dtyp == NODE_AND)) 39413082428Sbill return; 39513082428Sbill } 39613082428Sbill if (t->t_dcdr) { 397f3328da7Sbostic t->t_dcdr->t_dflg |= t->t_dflg & 398f3328da7Sbostic (F_NOFORK | F_NOINTERRUPT); 399f3328da7Sbostic execute(t->t_dcdr, wanttty, NULL, NULL); 40013082428Sbill } 40113082428Sbill break; 40213082428Sbill } 40313082428Sbill /* 404f3328da7Sbostic * Fall through for all breaks from switch 40513082428Sbill * 406f3328da7Sbostic * If there will be no more executions of this command, flush all file 407f3328da7Sbostic * descriptors. Places that turn on the F_REPEAT bit are responsible for 408f3328da7Sbostic * doing donefds after the last re-execution 40913082428Sbill */ 4105eb3278cSbostic if (didfds && !(t->t_dflg & F_REPEAT)) 41113082428Sbill donefds(); 41213082428Sbill } 41313082428Sbill 414f3328da7Sbostic static void 41523ceb1ffSchristos vffree(i) 41623ceb1ffSchristos int i; 41713082428Sbill { 418f3328da7Sbostic register Char **v; 41913082428Sbill 420f3328da7Sbostic if (v = gargv) { 421f3328da7Sbostic gargv = 0; 422f3328da7Sbostic xfree((ptr_t) v); 423f3328da7Sbostic } 424f3328da7Sbostic if (v = pargv) { 425f3328da7Sbostic pargv = 0; 426f3328da7Sbostic xfree((ptr_t) v); 427f3328da7Sbostic } 42823ceb1ffSchristos _exit(i); 42913082428Sbill } 430f3328da7Sbostic 43113082428Sbill /* 43213082428Sbill * Perform io redirection. 43313082428Sbill * We may or maynot be forked here. 43413082428Sbill */ 435f3328da7Sbostic static void 43613082428Sbill doio(t, pipein, pipeout) 43713082428Sbill register struct command *t; 43813082428Sbill int *pipein, *pipeout; 43913082428Sbill { 440f3328da7Sbostic register int fd; 441c3d0e0dbSchristos register Char *cp, *dp; 44213082428Sbill register int flags = t->t_dflg; 44313082428Sbill 4445eb3278cSbostic if (didfds || (flags & F_REPEAT)) 44513082428Sbill return; 4465eb3278cSbostic if ((flags & F_READ) == 0) {/* F_READ already done */ 44713082428Sbill if (cp = t->t_dlef) { 448e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 449f3328da7Sbostic 450f3328da7Sbostic /* 451f3328da7Sbostic * so < /dev/std{in,out,err} work 452f3328da7Sbostic */ 453f3328da7Sbostic (void) dcopy(SHIN, 0); 454f3328da7Sbostic (void) dcopy(SHOUT, 1); 455cce51c35Schristos (void) dcopy(SHERR, 2); 456c3d0e0dbSchristos cp = globone(dp = Dfix1(cp), G_IGNORE); 457f3328da7Sbostic (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 458e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 459f3328da7Sbostic xfree((ptr_t) cp); 460c3d0e0dbSchristos xfree((ptr_t) dp); 461f3328da7Sbostic if ((fd = open(tmp, O_RDONLY)) < 0) 462f3328da7Sbostic stderror(ERR_SYSTEM, tmp, strerror(errno)); 463f3328da7Sbostic (void) dmove(fd, 0); 464f3328da7Sbostic } 465f3328da7Sbostic else if (flags & F_PIPEIN) { 466f3328da7Sbostic (void) close(0); 46743fabe3fSedward (void) dup(pipein[0]); 46843fabe3fSedward (void) close(pipein[0]); 46943fabe3fSedward (void) close(pipein[1]); 470f3328da7Sbostic } 471f3328da7Sbostic else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 47243fabe3fSedward (void) close(0); 473f3328da7Sbostic (void) open(_PATH_DEVNULL, O_RDONLY); 474f3328da7Sbostic } 475f3328da7Sbostic else { 476f3328da7Sbostic (void) close(0); 477cde959b4Sedward (void) dup(OLDSTD); 4789374f148Sbostic (void) ioctl(0, FIONCLEX, NULL); 47913082428Sbill } 480f3328da7Sbostic } 48113082428Sbill if (cp = t->t_drit) { 482e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 483f3328da7Sbostic 484c3d0e0dbSchristos cp = globone(dp = Dfix1(cp), G_IGNORE); 485e78a8ca9Schristos (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 486e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 487f3328da7Sbostic xfree((ptr_t) cp); 488c3d0e0dbSchristos xfree((ptr_t) dp); 489f3328da7Sbostic /* 490f3328da7Sbostic * so > /dev/std{out,err} work 491f3328da7Sbostic */ 492f3328da7Sbostic (void) dcopy(SHOUT, 1); 493cce51c35Schristos (void) dcopy(SHERR, 2); 494f3328da7Sbostic if ((flags & F_APPEND) && 495f3328da7Sbostic #ifdef O_APPEND 496e78a8ca9Schristos (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); 497f3328da7Sbostic #else 498e78a8ca9Schristos (fd = open(tmp, O_WRONLY)) >= 0) 499f3328da7Sbostic (void) lseek(1, (off_t) 0, L_XTND); 500f3328da7Sbostic #endif 501f3328da7Sbostic else { 502f3328da7Sbostic if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 5035eb3278cSbostic if (flags & F_APPEND) 504e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 505f3328da7Sbostic chkclob(tmp); 50613082428Sbill } 507e78a8ca9Schristos if ((fd = creat(tmp, 0666)) < 0) 508e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 50913082428Sbill } 510f3328da7Sbostic (void) dmove(fd, 1); 511f3328da7Sbostic } 512f3328da7Sbostic else if (flags & F_PIPEOUT) { 513f3328da7Sbostic (void) close(1); 51443fabe3fSedward (void) dup(pipeout[1]); 515f3328da7Sbostic } 516f3328da7Sbostic else { 517f3328da7Sbostic (void) close(1); 518cde959b4Sedward (void) dup(SHOUT); 5199374f148Sbostic (void) ioctl(1, FIONCLEX, NULL); 520f3328da7Sbostic } 52113082428Sbill 52243fabe3fSedward (void) close(2); 523f3328da7Sbostic if (flags & F_STDERR) { 52443fabe3fSedward (void) dup(1); 525f3328da7Sbostic } 526f3328da7Sbostic else { 527cce51c35Schristos (void) dup(SHERR); 5289374f148Sbostic (void) ioctl(2, FIONCLEX, NULL); 529f3328da7Sbostic } 53013082428Sbill didfds = 1; 53113082428Sbill } 53213082428Sbill 533f3328da7Sbostic void 53413082428Sbill mypipe(pv) 53513082428Sbill register int *pv; 53613082428Sbill { 53713082428Sbill 53813082428Sbill if (pipe(pv) < 0) 53913082428Sbill goto oops; 54013082428Sbill pv[0] = dmove(pv[0], -1); 54113082428Sbill pv[1] = dmove(pv[1], -1); 54213082428Sbill if (pv[0] >= 0 && pv[1] >= 0) 54313082428Sbill return; 54413082428Sbill oops: 545f3328da7Sbostic stderror(ERR_PIPE); 54613082428Sbill } 54713082428Sbill 548f3328da7Sbostic static void 54913082428Sbill chkclob(cp) 550e78a8ca9Schristos register char *cp; 55113082428Sbill { 55213082428Sbill struct stat stb; 55313082428Sbill 554e78a8ca9Schristos if (stat(cp, &stb) < 0) 55513082428Sbill return; 55613082428Sbill if ((stb.st_mode & S_IFMT) == S_IFCHR) 55713082428Sbill return; 558e78a8ca9Schristos stderror(ERR_EXISTS, cp); 55913082428Sbill } 560