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*cce51c35Schristos static char sccsid[] = "@(#)sem.c 5.19 (Berkeley) 07/19/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 if (noexec) 8013082428Sbill break; 8113082428Sbill 82f3328da7Sbostic set(STRstatus, Strsave(STR0)); 8313082428Sbill 8413082428Sbill /* 85f3328da7Sbostic * This mess is the necessary kludge to handle the prefix builtins: 86f3328da7Sbostic * nice, nohup, time. These commands can also be used by themselves, 87f3328da7Sbostic * and this is not handled here. This will also work when loops are 88f3328da7Sbostic * parsed. 8913082428Sbill */ 905eb3278cSbostic while (t->t_dtyp == NODE_COMMAND) 91f3328da7Sbostic if (eq(t->t_dcom[0], STRnice)) 9213082428Sbill if (t->t_dcom[1]) 93f3328da7Sbostic if (strchr("+-", t->t_dcom[1][0])) 9413082428Sbill if (t->t_dcom[2]) { 9513082428Sbill setname("nice"); 96f3328da7Sbostic t->t_nice = 97f3328da7Sbostic getn(t->t_dcom[1]); 9813082428Sbill lshift(t->t_dcom, 2); 995eb3278cSbostic t->t_dflg |= F_NICE; 100f3328da7Sbostic } 101f3328da7Sbostic else 10213082428Sbill break; 10313082428Sbill else { 10413082428Sbill t->t_nice = 4; 10513082428Sbill lshift(t->t_dcom, 1); 1065eb3278cSbostic t->t_dflg |= F_NICE; 10713082428Sbill } 10813082428Sbill else 10913082428Sbill break; 110f3328da7Sbostic else if (eq(t->t_dcom[0], STRnohup)) 11113082428Sbill if (t->t_dcom[1]) { 1125eb3278cSbostic t->t_dflg |= F_NOHUP; 11313082428Sbill lshift(t->t_dcom, 1); 114f3328da7Sbostic } 115f3328da7Sbostic else 11613082428Sbill break; 117f3328da7Sbostic else if (eq(t->t_dcom[0], STRtime)) 11813082428Sbill if (t->t_dcom[1]) { 1195eb3278cSbostic t->t_dflg |= F_TIME; 12013082428Sbill lshift(t->t_dcom, 1); 121f3328da7Sbostic } 122f3328da7Sbostic else 12313082428Sbill break; 12413082428Sbill else 12513082428Sbill break; 126f3328da7Sbostic 127f3328da7Sbostic /* is t a command */ 128f3328da7Sbostic if (t->t_dtyp == NODE_COMMAND) { 12913082428Sbill /* 13013082428Sbill * Check if we have a builtin function and remember which one. 13113082428Sbill */ 132f3328da7Sbostic bifunc = isbfunc(t); 133f3328da7Sbostic } 134f3328da7Sbostic else { /* not a command */ 1359374f148Sbostic bifunc = NULL; 136f3328da7Sbostic } 13713082428Sbill 13813082428Sbill /* 139f3328da7Sbostic * We fork only if we are timed, or are not the end of a parenthesized 140f3328da7Sbostic * list and not a simple builtin function. Simple meaning one that is 141f3328da7Sbostic * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 142f3328da7Sbostic * fork in some of these cases. 14313082428Sbill */ 144f3328da7Sbostic /* 145f3328da7Sbostic * Prevent forking cd, pushd, popd, chdir cause this will cause the 146f3328da7Sbostic * shell not to change dir! 147f3328da7Sbostic */ 148f3328da7Sbostic if (bifunc && (bifunc->bfunct == dochngd || 149f3328da7Sbostic bifunc->bfunct == dopushd || 150f3328da7Sbostic bifunc->bfunct == dopopd)) 151f3328da7Sbostic t->t_dflg &= ~(F_NICE); 1525eb3278cSbostic if (((t->t_dflg & F_TIME) || (t->t_dflg & F_NOFORK) == 0 && 153f3328da7Sbostic (!bifunc || t->t_dflg & 154f3328da7Sbostic (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP))) || 155f3328da7Sbostic /* 156f3328da7Sbostic * We have to fork for eval too. 157f3328da7Sbostic */ 158*cce51c35Schristos (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 && 159f3328da7Sbostic bifunc->bfunct == doeval)) 1605eb3278cSbostic if (t->t_dtyp == NODE_PAREN || 161afc71901Sbostic t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) { 162f3328da7Sbostic forked++; 163f3328da7Sbostic /* 164f3328da7Sbostic * We need to block SIGCHLD here, so that if the process does 165f3328da7Sbostic * not die before we can set the process group 166f3328da7Sbostic */ 1675e5c7fccSmarc if (wanttty >= 0 && !nosigchld) { 168f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 1695e5c7fccSmarc nosigchld = 1; 1705e5c7fccSmarc } 1715e5c7fccSmarc 1725e5c7fccSmarc pid = pfork(t, wanttty); 1735e5c7fccSmarc if (pid == 0 && nosigchld) { 174f3328da7Sbostic (void) sigsetmask(csigmask); 1755e5c7fccSmarc nosigchld = 0; 1765e5c7fccSmarc } 1775e5c7fccSmarc } 17813082428Sbill else { 17943fabe3fSedward int ochild, osetintr, ohaderr, odidfds; 180*cce51c35Schristos int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp; 1819374f148Sbostic sigset_t omask; 18213082428Sbill 18315d9e91aSlepreau /* 184f3328da7Sbostic * Prepare for the vfork by saving everything that the child 185f3328da7Sbostic * corrupts before it exec's. Note that in some signal 186f3328da7Sbostic * implementations which keep the signal info in user space 187f3328da7Sbostic * (e.g. Sun's) it will also be necessary to save and restore 188f3328da7Sbostic * the current sigvec's for the signals the child touches 189f3328da7Sbostic * before it exec's. 19015d9e91aSlepreau */ 1915e5c7fccSmarc if (wanttty >= 0 && !nosigchld && !noexec) { 192f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 1935e5c7fccSmarc nosigchld = 1; 1945e5c7fccSmarc } 195f3328da7Sbostic omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT)); 196f3328da7Sbostic ochild = child; 197f3328da7Sbostic osetintr = setintr; 198f3328da7Sbostic ohaderr = haderr; 199f3328da7Sbostic odidfds = didfds; 200f3328da7Sbostic oSHIN = SHIN; 201f3328da7Sbostic oSHOUT = SHOUT; 202*cce51c35Schristos oSHERR = SHERR; 203f3328da7Sbostic oOLDSTD = OLDSTD; 204f3328da7Sbostic otpgrp = tpgrp; 205f3328da7Sbostic ocsigmask = csigmask; 206f3328da7Sbostic onosigchld = nosigchld; 207f3328da7Sbostic Vsav = Vdp = 0; 208f3328da7Sbostic Vexpath = 0; 209f3328da7Sbostic Vt = 0; 21013082428Sbill pid = vfork(); 211f3328da7Sbostic 21213082428Sbill if (pid < 0) { 21343fabe3fSedward (void) sigsetmask(omask); 214f3328da7Sbostic stderror(ERR_NOPROC); 21513082428Sbill } 21613082428Sbill forked++; 21715d9e91aSlepreau if (pid) { /* parent */ 218f3328da7Sbostic child = ochild; 219f3328da7Sbostic setintr = osetintr; 220f3328da7Sbostic haderr = ohaderr; 221f3328da7Sbostic didfds = odidfds; 22243fabe3fSedward SHIN = oSHIN; 223f3328da7Sbostic SHOUT = oSHOUT; 224*cce51c35Schristos SHERR = oSHERR; 225f3328da7Sbostic OLDSTD = oOLDSTD; 226f3328da7Sbostic tpgrp = otpgrp; 227f3328da7Sbostic csigmask = ocsigmask; 228f3328da7Sbostic nosigchld = onosigchld; 229f3328da7Sbostic 230f3328da7Sbostic xfree((ptr_t) Vsav); 231f3328da7Sbostic Vsav = 0; 232f3328da7Sbostic xfree((ptr_t) Vdp); 233f3328da7Sbostic Vdp = 0; 234f3328da7Sbostic xfree((ptr_t) Vexpath); 235f3328da7Sbostic Vexpath = 0; 236f3328da7Sbostic blkfree((Char **) Vt); 237f3328da7Sbostic Vt = 0; 23813082428Sbill /* this is from pfork() */ 23913082428Sbill palloc(pid, t); 24043fabe3fSedward (void) sigsetmask(omask); 241f3328da7Sbostic } 242f3328da7Sbostic else { /* child */ 24313082428Sbill /* this is from pfork() */ 24413082428Sbill int pgrp; 24513082428Sbill bool ignint = 0; 24613082428Sbill 2475e5c7fccSmarc if (nosigchld) { 248f3328da7Sbostic (void) sigsetmask(csigmask); 2495e5c7fccSmarc nosigchld = 0; 2505e5c7fccSmarc } 251f3328da7Sbostic 25213082428Sbill if (setintr) 253f3328da7Sbostic ignint = 254f3328da7Sbostic (tpgrp == -1 && 255f3328da7Sbostic (t->t_dflg & F_NOINTERRUPT)) 256f3328da7Sbostic || gointr && eq(gointr, STRminus); 25713082428Sbill pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 25813082428Sbill child++; 25913082428Sbill if (setintr) { 26013082428Sbill setintr = 0; 261f3328da7Sbostic if (ignint) { 262f3328da7Sbostic (void) signal(SIGINT, SIG_IGN); 263f3328da7Sbostic (void) signal(SIGQUIT, SIG_IGN); 264f3328da7Sbostic } 265f3328da7Sbostic else { 266f3328da7Sbostic (void) signal(SIGINT, vffree); 267f3328da7Sbostic (void) signal(SIGQUIT, SIG_DFL); 268f3328da7Sbostic } 269f3328da7Sbostic 27013082428Sbill if (wanttty >= 0) { 27143fabe3fSedward (void) signal(SIGTSTP, SIG_DFL); 27243fabe3fSedward (void) signal(SIGTTIN, SIG_DFL); 27343fabe3fSedward (void) signal(SIGTTOU, SIG_DFL); 27413082428Sbill } 275f3328da7Sbostic 27643fabe3fSedward (void) signal(SIGTERM, parterm); 277f3328da7Sbostic } 278f3328da7Sbostic else if (tpgrp == -1 && 2795eb3278cSbostic (t->t_dflg & F_NOINTERRUPT)) { 28043fabe3fSedward (void) signal(SIGINT, SIG_IGN); 28143fabe3fSedward (void) signal(SIGQUIT, SIG_IGN); 28213082428Sbill } 283f3328da7Sbostic 284f3328da7Sbostic pgetty(wanttty, pgrp); 2855eb3278cSbostic if (t->t_dflg & F_NOHUP) 28643fabe3fSedward (void) signal(SIGHUP, SIG_IGN); 2875eb3278cSbostic if (t->t_dflg & F_NICE) 288f3328da7Sbostic (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 28913082428Sbill } 29013082428Sbill 29113082428Sbill } 29213082428Sbill if (pid != 0) { 29313082428Sbill /* 294f3328da7Sbostic * It would be better if we could wait for the whole job when we 295f3328da7Sbostic * knew the last process had been started. Pwait, in fact, does 296f3328da7Sbostic * wait for the whole job anyway, but this test doesn't really 297f3328da7Sbostic * express our intentions. 29813082428Sbill */ 2995eb3278cSbostic if (didfds == 0 && t->t_dflg & F_PIPEIN) { 30043fabe3fSedward (void) close(pipein[0]); 30143fabe3fSedward (void) close(pipein[1]); 30243fabe3fSedward } 3035eb3278cSbostic if ((t->t_dflg & F_PIPEOUT) == 0) { 3045e5c7fccSmarc if (nosigchld) { 305f3328da7Sbostic (void) sigsetmask(csigmask); 3065e5c7fccSmarc nosigchld = 0; 3075e5c7fccSmarc } 3085eb3278cSbostic if ((t->t_dflg & F_AMPERSAND) == 0) 30913082428Sbill pwait(); 3105e5c7fccSmarc } 31113082428Sbill break; 31213082428Sbill } 31313082428Sbill doio(t, pipein, pipeout); 3145eb3278cSbostic if (t->t_dflg & F_PIPEOUT) { 31543fabe3fSedward (void) close(pipeout[0]); 31643fabe3fSedward (void) close(pipeout[1]); 31743fabe3fSedward } 31813082428Sbill /* 319f3328da7Sbostic * Perform a builtin function. If we are not forked, arrange for 320f3328da7Sbostic * possible stopping 32113082428Sbill */ 32213082428Sbill if (bifunc) { 32313082428Sbill func(t, bifunc); 32413082428Sbill if (forked) 32513082428Sbill exitstat(); 32613082428Sbill break; 32713082428Sbill } 3285eb3278cSbostic if (t->t_dtyp != NODE_PAREN) { 329*cce51c35Schristos doexec(NULL, t); 33013082428Sbill /* NOTREACHED */ 33113082428Sbill } 33213082428Sbill /* 33313082428Sbill * For () commands must put new 0,1,2 in FSH* and recurse 33413082428Sbill */ 33513082428Sbill OLDSTD = dcopy(0, FOLDSTD); 33613082428Sbill SHOUT = dcopy(1, FSHOUT); 337*cce51c35Schristos SHERR = dcopy(2, FSHERR); 33843fabe3fSedward (void) close(SHIN); 33943fabe3fSedward SHIN = -1; 34043fabe3fSedward didfds = 0; 34113082428Sbill wanttty = -1; 3425eb3278cSbostic t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 343f3328da7Sbostic execute(t->t_dspr, wanttty, NULL, NULL); 34413082428Sbill exitstat(); 34513082428Sbill 3465eb3278cSbostic case NODE_PIPE: 3475eb3278cSbostic t->t_dcar->t_dflg |= F_PIPEOUT | 3485eb3278cSbostic (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 34913082428Sbill execute(t->t_dcar, wanttty, pipein, pv); 350f3328da7Sbostic t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 3515eb3278cSbostic (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 35213082428Sbill if (wanttty > 0) 35313082428Sbill wanttty = 0; /* got tty already */ 35413082428Sbill execute(t->t_dcdr, wanttty, pv, pipeout); 35513082428Sbill break; 35613082428Sbill 3575eb3278cSbostic case NODE_LIST: 35813082428Sbill if (t->t_dcar) { 3595eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 360f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 36113082428Sbill /* 36213082428Sbill * In strange case of A&B make a new job after A 36313082428Sbill */ 3645eb3278cSbostic if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 3655eb3278cSbostic (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 36613082428Sbill pendjob(); 36713082428Sbill } 36813082428Sbill if (t->t_dcdr) { 369f3328da7Sbostic t->t_dcdr->t_dflg |= t->t_dflg & 370f3328da7Sbostic (F_NOFORK | F_NOINTERRUPT); 371f3328da7Sbostic execute(t->t_dcdr, wanttty, NULL, NULL); 37213082428Sbill } 37313082428Sbill break; 37413082428Sbill 3755eb3278cSbostic case NODE_OR: 3765eb3278cSbostic case NODE_AND: 37713082428Sbill if (t->t_dcar) { 3785eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 379f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 380f3328da7Sbostic if ((getn(value(STRstatus)) == 0) != 3815eb3278cSbostic (t->t_dtyp == NODE_AND)) 38213082428Sbill return; 38313082428Sbill } 38413082428Sbill if (t->t_dcdr) { 385f3328da7Sbostic t->t_dcdr->t_dflg |= t->t_dflg & 386f3328da7Sbostic (F_NOFORK | F_NOINTERRUPT); 387f3328da7Sbostic execute(t->t_dcdr, wanttty, NULL, NULL); 38813082428Sbill } 38913082428Sbill break; 39013082428Sbill } 39113082428Sbill /* 392f3328da7Sbostic * Fall through for all breaks from switch 39313082428Sbill * 394f3328da7Sbostic * If there will be no more executions of this command, flush all file 395f3328da7Sbostic * descriptors. Places that turn on the F_REPEAT bit are responsible for 396f3328da7Sbostic * doing donefds after the last re-execution 39713082428Sbill */ 3985eb3278cSbostic if (didfds && !(t->t_dflg & F_REPEAT)) 39913082428Sbill donefds(); 40013082428Sbill } 40113082428Sbill 402f3328da7Sbostic static void 40323ceb1ffSchristos vffree(i) 40423ceb1ffSchristos int i; 40513082428Sbill { 406f3328da7Sbostic register Char **v; 40713082428Sbill 408f3328da7Sbostic if (v = gargv) { 409f3328da7Sbostic gargv = 0; 410f3328da7Sbostic xfree((ptr_t) v); 411f3328da7Sbostic } 412f3328da7Sbostic if (v = pargv) { 413f3328da7Sbostic pargv = 0; 414f3328da7Sbostic xfree((ptr_t) v); 415f3328da7Sbostic } 41623ceb1ffSchristos _exit(i); 41713082428Sbill } 418f3328da7Sbostic 41913082428Sbill /* 42013082428Sbill * Perform io redirection. 42113082428Sbill * We may or maynot be forked here. 42213082428Sbill */ 423f3328da7Sbostic static void 42413082428Sbill doio(t, pipein, pipeout) 42513082428Sbill register struct command *t; 42613082428Sbill int *pipein, *pipeout; 42713082428Sbill { 428f3328da7Sbostic register int fd; 429c3d0e0dbSchristos register Char *cp, *dp; 43013082428Sbill register int flags = t->t_dflg; 43113082428Sbill 4325eb3278cSbostic if (didfds || (flags & F_REPEAT)) 43313082428Sbill return; 4345eb3278cSbostic if ((flags & F_READ) == 0) {/* F_READ already done */ 43513082428Sbill if (cp = t->t_dlef) { 436e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 437f3328da7Sbostic 438f3328da7Sbostic /* 439f3328da7Sbostic * so < /dev/std{in,out,err} work 440f3328da7Sbostic */ 441f3328da7Sbostic (void) dcopy(SHIN, 0); 442f3328da7Sbostic (void) dcopy(SHOUT, 1); 443*cce51c35Schristos (void) dcopy(SHERR, 2); 444c3d0e0dbSchristos cp = globone(dp = Dfix1(cp), G_IGNORE); 445f3328da7Sbostic (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 446e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 447f3328da7Sbostic xfree((ptr_t) cp); 448c3d0e0dbSchristos xfree((ptr_t) dp); 449f3328da7Sbostic if ((fd = open(tmp, O_RDONLY)) < 0) 450f3328da7Sbostic stderror(ERR_SYSTEM, tmp, strerror(errno)); 451f3328da7Sbostic (void) dmove(fd, 0); 452f3328da7Sbostic } 453f3328da7Sbostic else if (flags & F_PIPEIN) { 454f3328da7Sbostic (void) close(0); 45543fabe3fSedward (void) dup(pipein[0]); 45643fabe3fSedward (void) close(pipein[0]); 45743fabe3fSedward (void) close(pipein[1]); 458f3328da7Sbostic } 459f3328da7Sbostic else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 46043fabe3fSedward (void) close(0); 461f3328da7Sbostic (void) open(_PATH_DEVNULL, O_RDONLY); 462f3328da7Sbostic } 463f3328da7Sbostic else { 464f3328da7Sbostic (void) close(0); 465cde959b4Sedward (void) dup(OLDSTD); 4669374f148Sbostic (void) ioctl(0, FIONCLEX, NULL); 46713082428Sbill } 468f3328da7Sbostic } 46913082428Sbill if (cp = t->t_drit) { 470e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 471f3328da7Sbostic 472c3d0e0dbSchristos cp = globone(dp = Dfix1(cp), G_IGNORE); 473e78a8ca9Schristos (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 474e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 475f3328da7Sbostic xfree((ptr_t) cp); 476c3d0e0dbSchristos xfree((ptr_t) dp); 477f3328da7Sbostic /* 478f3328da7Sbostic * so > /dev/std{out,err} work 479f3328da7Sbostic */ 480f3328da7Sbostic (void) dcopy(SHOUT, 1); 481*cce51c35Schristos (void) dcopy(SHERR, 2); 482f3328da7Sbostic if ((flags & F_APPEND) && 483f3328da7Sbostic #ifdef O_APPEND 484e78a8ca9Schristos (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); 485f3328da7Sbostic #else 486e78a8ca9Schristos (fd = open(tmp, O_WRONLY)) >= 0) 487f3328da7Sbostic (void) lseek(1, (off_t) 0, L_XTND); 488f3328da7Sbostic #endif 489f3328da7Sbostic else { 490f3328da7Sbostic if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 4915eb3278cSbostic if (flags & F_APPEND) 492e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 493f3328da7Sbostic chkclob(tmp); 49413082428Sbill } 495e78a8ca9Schristos if ((fd = creat(tmp, 0666)) < 0) 496e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 49713082428Sbill } 498f3328da7Sbostic (void) dmove(fd, 1); 499f3328da7Sbostic } 500f3328da7Sbostic else if (flags & F_PIPEOUT) { 501f3328da7Sbostic (void) close(1); 50243fabe3fSedward (void) dup(pipeout[1]); 503f3328da7Sbostic } 504f3328da7Sbostic else { 505f3328da7Sbostic (void) close(1); 506cde959b4Sedward (void) dup(SHOUT); 5079374f148Sbostic (void) ioctl(1, FIONCLEX, NULL); 508f3328da7Sbostic } 50913082428Sbill 51043fabe3fSedward (void) close(2); 511f3328da7Sbostic if (flags & F_STDERR) { 51243fabe3fSedward (void) dup(1); 513f3328da7Sbostic } 514f3328da7Sbostic else { 515*cce51c35Schristos (void) dup(SHERR); 5169374f148Sbostic (void) ioctl(2, FIONCLEX, NULL); 517f3328da7Sbostic } 51813082428Sbill didfds = 1; 51913082428Sbill } 52013082428Sbill 521f3328da7Sbostic void 52213082428Sbill mypipe(pv) 52313082428Sbill register int *pv; 52413082428Sbill { 52513082428Sbill 52613082428Sbill if (pipe(pv) < 0) 52713082428Sbill goto oops; 52813082428Sbill pv[0] = dmove(pv[0], -1); 52913082428Sbill pv[1] = dmove(pv[1], -1); 53013082428Sbill if (pv[0] >= 0 && pv[1] >= 0) 53113082428Sbill return; 53213082428Sbill oops: 533f3328da7Sbostic stderror(ERR_PIPE); 53413082428Sbill } 53513082428Sbill 536f3328da7Sbostic static void 53713082428Sbill chkclob(cp) 538e78a8ca9Schristos register char *cp; 53913082428Sbill { 54013082428Sbill struct stat stb; 54113082428Sbill 542e78a8ca9Schristos if (stat(cp, &stb) < 0) 54313082428Sbill return; 54413082428Sbill if ((stb.st_mode & S_IFMT) == S_IFCHR) 54513082428Sbill return; 546e78a8ca9Schristos stderror(ERR_EXISTS, cp); 54713082428Sbill } 548