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*8d2f70fbSchristos static char sccsid[] = "@(#)sem.c 5.22 (Berkeley) 11/06/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)); 312ff0ec22Schristos static Char *splicepipe __P((struct command *t, Char *)); 3223ceb1ffSchristos static void doio __P((struct command *t, int *, int *)); 33e78a8ca9Schristos static void chkclob __P((char *)); 3413082428Sbill 35f3328da7Sbostic void 3613082428Sbill execute(t, wanttty, pipein, pipeout) 3713082428Sbill register struct command *t; 3813082428Sbill int wanttty, *pipein, *pipeout; 3913082428Sbill { 4013082428Sbill bool forked = 0; 4113082428Sbill struct biltins *bifunc; 4213082428Sbill int pid = 0; 4313082428Sbill int pv[2]; 4413082428Sbill 459374f148Sbostic static sigset_t csigmask; 46f3328da7Sbostic 479374f148Sbostic static sigset_t ocsigmask; 48f3328da7Sbostic static int onosigchld = 0; 49f3328da7Sbostic static int nosigchld = 0; 50f3328da7Sbostic 5113082428Sbill if (t == 0) 5213082428Sbill return; 53f3328da7Sbostic 54f3328da7Sbostic if (t->t_dflg & F_AMPERSAND) 5513082428Sbill wanttty = 0; 5613082428Sbill switch (t->t_dtyp) { 5713082428Sbill 585eb3278cSbostic case NODE_COMMAND: 5913082428Sbill if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 60f3328da7Sbostic (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 615eb3278cSbostic if ((t->t_dflg & F_REPEAT) == 0) 6213082428Sbill Dfix(t); /* $ " ' \ */ 6313082428Sbill if (t->t_dcom[0] == 0) 6413082428Sbill return; 6513082428Sbill /* fall into... */ 6613082428Sbill 675eb3278cSbostic case NODE_PAREN: 685eb3278cSbostic if (t->t_dflg & F_PIPEOUT) 6913082428Sbill mypipe(pipeout); 7013082428Sbill /* 71f3328da7Sbostic * Must do << early so parent will know where input pointer should be. 7213082428Sbill * If noexec then this is all we do. 7313082428Sbill */ 745eb3278cSbostic if (t->t_dflg & F_READ) { 7543fabe3fSedward (void) close(0); 7613082428Sbill heredoc(t->t_dlef); 7713082428Sbill if (noexec) 7843fabe3fSedward (void) close(0); 7913082428Sbill } 8013082428Sbill 81f3328da7Sbostic set(STRstatus, Strsave(STR0)); 8213082428Sbill 8313082428Sbill /* 84f3328da7Sbostic * This mess is the necessary kludge to handle the prefix builtins: 85f3328da7Sbostic * nice, nohup, time. These commands can also be used by themselves, 86f3328da7Sbostic * and this is not handled here. This will also work when loops are 87f3328da7Sbostic * parsed. 8813082428Sbill */ 895eb3278cSbostic while (t->t_dtyp == NODE_COMMAND) 90f3328da7Sbostic if (eq(t->t_dcom[0], STRnice)) 9113082428Sbill if (t->t_dcom[1]) 92f3328da7Sbostic if (strchr("+-", t->t_dcom[1][0])) 9313082428Sbill if (t->t_dcom[2]) { 9413082428Sbill setname("nice"); 95f3328da7Sbostic t->t_nice = 96f3328da7Sbostic getn(t->t_dcom[1]); 9713082428Sbill lshift(t->t_dcom, 2); 985eb3278cSbostic t->t_dflg |= F_NICE; 99f3328da7Sbostic } 100f3328da7Sbostic else 10113082428Sbill break; 10213082428Sbill else { 10313082428Sbill t->t_nice = 4; 10413082428Sbill lshift(t->t_dcom, 1); 1055eb3278cSbostic t->t_dflg |= F_NICE; 10613082428Sbill } 10713082428Sbill else 10813082428Sbill break; 109f3328da7Sbostic else if (eq(t->t_dcom[0], STRnohup)) 11013082428Sbill if (t->t_dcom[1]) { 1115eb3278cSbostic t->t_dflg |= F_NOHUP; 11213082428Sbill lshift(t->t_dcom, 1); 113f3328da7Sbostic } 114f3328da7Sbostic else 11513082428Sbill break; 116f3328da7Sbostic else if (eq(t->t_dcom[0], STRtime)) 11713082428Sbill if (t->t_dcom[1]) { 1185eb3278cSbostic t->t_dflg |= F_TIME; 11913082428Sbill lshift(t->t_dcom, 1); 120f3328da7Sbostic } 121f3328da7Sbostic else 12213082428Sbill break; 12313082428Sbill else 12413082428Sbill break; 125f3328da7Sbostic 126336c1b24Schristos /* is it a command */ 127f3328da7Sbostic if (t->t_dtyp == NODE_COMMAND) { 12813082428Sbill /* 12913082428Sbill * Check if we have a builtin function and remember which one. 13013082428Sbill */ 131f3328da7Sbostic bifunc = isbfunc(t); 132336c1b24Schristos if (noexec) { 133336c1b24Schristos /* 134336c1b24Schristos * Continue for builtins that are part of the scripting language 135336c1b24Schristos */ 136336c1b24Schristos if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin && 137336c1b24Schristos bifunc->bfunct != doelse && bifunc->bfunct != doend && 138336c1b24Schristos bifunc->bfunct != doforeach && bifunc->bfunct != dogoto && 139336c1b24Schristos bifunc->bfunct != doif && bifunc->bfunct != dorepeat && 140336c1b24Schristos bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch && 141336c1b24Schristos bifunc->bfunct != dowhile && bifunc->bfunct != dozip) 142336c1b24Schristos break; 143336c1b24Schristos } 144f3328da7Sbostic } 145f3328da7Sbostic else { /* not a command */ 1469374f148Sbostic bifunc = NULL; 147336c1b24Schristos if (noexec) 148336c1b24Schristos break; 149f3328da7Sbostic } 15013082428Sbill 15113082428Sbill /* 152f3328da7Sbostic * We fork only if we are timed, or are not the end of a parenthesized 153f3328da7Sbostic * list and not a simple builtin function. Simple meaning one that is 154f3328da7Sbostic * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 155f3328da7Sbostic * fork in some of these cases. 15613082428Sbill */ 157f3328da7Sbostic /* 158f3328da7Sbostic * Prevent forking cd, pushd, popd, chdir cause this will cause the 159f3328da7Sbostic * shell not to change dir! 160f3328da7Sbostic */ 161f3328da7Sbostic if (bifunc && (bifunc->bfunct == dochngd || 162f3328da7Sbostic bifunc->bfunct == dopushd || 163f3328da7Sbostic bifunc->bfunct == dopopd)) 164f3328da7Sbostic t->t_dflg &= ~(F_NICE); 1655eb3278cSbostic if (((t->t_dflg & F_TIME) || (t->t_dflg & F_NOFORK) == 0 && 166f3328da7Sbostic (!bifunc || t->t_dflg & 167f3328da7Sbostic (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP))) || 168f3328da7Sbostic /* 169f3328da7Sbostic * We have to fork for eval too. 170f3328da7Sbostic */ 171cce51c35Schristos (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 && 172f3328da7Sbostic bifunc->bfunct == doeval)) 1735eb3278cSbostic if (t->t_dtyp == NODE_PAREN || 174afc71901Sbostic t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) { 175f3328da7Sbostic forked++; 176f3328da7Sbostic /* 177f3328da7Sbostic * We need to block SIGCHLD here, so that if the process does 178f3328da7Sbostic * not die before we can set the process group 179f3328da7Sbostic */ 1805e5c7fccSmarc if (wanttty >= 0 && !nosigchld) { 181f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 1825e5c7fccSmarc nosigchld = 1; 1835e5c7fccSmarc } 1845e5c7fccSmarc 1855e5c7fccSmarc pid = pfork(t, wanttty); 1865e5c7fccSmarc if (pid == 0 && nosigchld) { 187f3328da7Sbostic (void) sigsetmask(csigmask); 1885e5c7fccSmarc nosigchld = 0; 1895e5c7fccSmarc } 1902ff0ec22Schristos else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) 1912ff0ec22Schristos backpid = pid; 1922ff0ec22Schristos 1935e5c7fccSmarc } 19413082428Sbill else { 19543fabe3fSedward int ochild, osetintr, ohaderr, odidfds; 196cce51c35Schristos int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp; 1979374f148Sbostic sigset_t omask; 19813082428Sbill 19915d9e91aSlepreau /* 200f3328da7Sbostic * Prepare for the vfork by saving everything that the child 201f3328da7Sbostic * corrupts before it exec's. Note that in some signal 202f3328da7Sbostic * implementations which keep the signal info in user space 203f3328da7Sbostic * (e.g. Sun's) it will also be necessary to save and restore 204f3328da7Sbostic * the current sigvec's for the signals the child touches 205f3328da7Sbostic * before it exec's. 20615d9e91aSlepreau */ 2075e5c7fccSmarc if (wanttty >= 0 && !nosigchld && !noexec) { 208f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 2095e5c7fccSmarc nosigchld = 1; 2105e5c7fccSmarc } 211f3328da7Sbostic omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT)); 212f3328da7Sbostic ochild = child; 213f3328da7Sbostic osetintr = setintr; 214f3328da7Sbostic ohaderr = haderr; 215f3328da7Sbostic odidfds = didfds; 216f3328da7Sbostic oSHIN = SHIN; 217f3328da7Sbostic oSHOUT = SHOUT; 218cce51c35Schristos oSHERR = SHERR; 219f3328da7Sbostic oOLDSTD = OLDSTD; 220f3328da7Sbostic otpgrp = tpgrp; 221f3328da7Sbostic ocsigmask = csigmask; 222f3328da7Sbostic onosigchld = nosigchld; 223f3328da7Sbostic Vsav = Vdp = 0; 224f3328da7Sbostic Vexpath = 0; 225f3328da7Sbostic Vt = 0; 22613082428Sbill pid = vfork(); 227f3328da7Sbostic 22813082428Sbill if (pid < 0) { 22943fabe3fSedward (void) sigsetmask(omask); 230f3328da7Sbostic stderror(ERR_NOPROC); 23113082428Sbill } 23213082428Sbill forked++; 23315d9e91aSlepreau if (pid) { /* parent */ 234f3328da7Sbostic child = ochild; 235f3328da7Sbostic setintr = osetintr; 236f3328da7Sbostic haderr = ohaderr; 237f3328da7Sbostic didfds = odidfds; 23843fabe3fSedward SHIN = oSHIN; 239f3328da7Sbostic SHOUT = oSHOUT; 240cce51c35Schristos SHERR = oSHERR; 241f3328da7Sbostic OLDSTD = oOLDSTD; 242f3328da7Sbostic tpgrp = otpgrp; 243f3328da7Sbostic csigmask = ocsigmask; 244f3328da7Sbostic nosigchld = onosigchld; 245f3328da7Sbostic 246f3328da7Sbostic xfree((ptr_t) Vsav); 247f3328da7Sbostic Vsav = 0; 248f3328da7Sbostic xfree((ptr_t) Vdp); 249f3328da7Sbostic Vdp = 0; 250f3328da7Sbostic xfree((ptr_t) Vexpath); 251f3328da7Sbostic Vexpath = 0; 252f3328da7Sbostic blkfree((Char **) Vt); 253f3328da7Sbostic Vt = 0; 25413082428Sbill /* this is from pfork() */ 25513082428Sbill palloc(pid, t); 25643fabe3fSedward (void) sigsetmask(omask); 257f3328da7Sbostic } 258f3328da7Sbostic else { /* child */ 25913082428Sbill /* this is from pfork() */ 26013082428Sbill int pgrp; 26113082428Sbill bool ignint = 0; 26213082428Sbill 2635e5c7fccSmarc if (nosigchld) { 264f3328da7Sbostic (void) sigsetmask(csigmask); 2655e5c7fccSmarc nosigchld = 0; 2665e5c7fccSmarc } 267f3328da7Sbostic 26813082428Sbill if (setintr) 269f3328da7Sbostic ignint = 270f3328da7Sbostic (tpgrp == -1 && 271f3328da7Sbostic (t->t_dflg & F_NOINTERRUPT)) 272f3328da7Sbostic || gointr && eq(gointr, STRminus); 27313082428Sbill pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 27413082428Sbill child++; 27513082428Sbill if (setintr) { 27613082428Sbill setintr = 0; 277f3328da7Sbostic if (ignint) { 278f3328da7Sbostic (void) signal(SIGINT, SIG_IGN); 279f3328da7Sbostic (void) signal(SIGQUIT, SIG_IGN); 280f3328da7Sbostic } 281f3328da7Sbostic else { 282f3328da7Sbostic (void) signal(SIGINT, vffree); 283f3328da7Sbostic (void) signal(SIGQUIT, SIG_DFL); 284f3328da7Sbostic } 285f3328da7Sbostic 28613082428Sbill if (wanttty >= 0) { 28743fabe3fSedward (void) signal(SIGTSTP, SIG_DFL); 28843fabe3fSedward (void) signal(SIGTTIN, SIG_DFL); 28943fabe3fSedward (void) signal(SIGTTOU, SIG_DFL); 29013082428Sbill } 291f3328da7Sbostic 29243fabe3fSedward (void) signal(SIGTERM, parterm); 293f3328da7Sbostic } 294f3328da7Sbostic else if (tpgrp == -1 && 2955eb3278cSbostic (t->t_dflg & F_NOINTERRUPT)) { 29643fabe3fSedward (void) signal(SIGINT, SIG_IGN); 29743fabe3fSedward (void) signal(SIGQUIT, SIG_IGN); 29813082428Sbill } 299f3328da7Sbostic 300f3328da7Sbostic pgetty(wanttty, pgrp); 3015eb3278cSbostic if (t->t_dflg & F_NOHUP) 30243fabe3fSedward (void) signal(SIGHUP, SIG_IGN); 3035eb3278cSbostic if (t->t_dflg & F_NICE) 304f3328da7Sbostic (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 30513082428Sbill } 30613082428Sbill 30713082428Sbill } 30813082428Sbill if (pid != 0) { 30913082428Sbill /* 310f3328da7Sbostic * It would be better if we could wait for the whole job when we 311f3328da7Sbostic * knew the last process had been started. Pwait, in fact, does 312f3328da7Sbostic * wait for the whole job anyway, but this test doesn't really 313f3328da7Sbostic * express our intentions. 31413082428Sbill */ 3155eb3278cSbostic if (didfds == 0 && t->t_dflg & F_PIPEIN) { 31643fabe3fSedward (void) close(pipein[0]); 31743fabe3fSedward (void) close(pipein[1]); 31843fabe3fSedward } 3195eb3278cSbostic if ((t->t_dflg & F_PIPEOUT) == 0) { 3205e5c7fccSmarc if (nosigchld) { 321f3328da7Sbostic (void) sigsetmask(csigmask); 3225e5c7fccSmarc nosigchld = 0; 3235e5c7fccSmarc } 3245eb3278cSbostic if ((t->t_dflg & F_AMPERSAND) == 0) 32513082428Sbill pwait(); 3265e5c7fccSmarc } 32713082428Sbill break; 32813082428Sbill } 32913082428Sbill doio(t, pipein, pipeout); 3305eb3278cSbostic if (t->t_dflg & F_PIPEOUT) { 33143fabe3fSedward (void) close(pipeout[0]); 33243fabe3fSedward (void) close(pipeout[1]); 33343fabe3fSedward } 33413082428Sbill /* 335f3328da7Sbostic * Perform a builtin function. If we are not forked, arrange for 336f3328da7Sbostic * possible stopping 33713082428Sbill */ 33813082428Sbill if (bifunc) { 33913082428Sbill func(t, bifunc); 34013082428Sbill if (forked) 34113082428Sbill exitstat(); 34213082428Sbill break; 34313082428Sbill } 3445eb3278cSbostic if (t->t_dtyp != NODE_PAREN) { 345cce51c35Schristos doexec(NULL, t); 34613082428Sbill /* NOTREACHED */ 34713082428Sbill } 34813082428Sbill /* 34913082428Sbill * For () commands must put new 0,1,2 in FSH* and recurse 35013082428Sbill */ 35113082428Sbill OLDSTD = dcopy(0, FOLDSTD); 35213082428Sbill SHOUT = dcopy(1, FSHOUT); 353cce51c35Schristos SHERR = dcopy(2, FSHERR); 35443fabe3fSedward (void) close(SHIN); 35543fabe3fSedward SHIN = -1; 35643fabe3fSedward didfds = 0; 35713082428Sbill wanttty = -1; 3585eb3278cSbostic t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 359f3328da7Sbostic execute(t->t_dspr, wanttty, NULL, NULL); 36013082428Sbill exitstat(); 36113082428Sbill 3625eb3278cSbostic case NODE_PIPE: 3635eb3278cSbostic t->t_dcar->t_dflg |= F_PIPEOUT | 3645eb3278cSbostic (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 36513082428Sbill execute(t->t_dcar, wanttty, pipein, pv); 366f3328da7Sbostic t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 3675eb3278cSbostic (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 36813082428Sbill if (wanttty > 0) 36913082428Sbill wanttty = 0; /* got tty already */ 37013082428Sbill execute(t->t_dcdr, wanttty, pv, pipeout); 37113082428Sbill break; 37213082428Sbill 3735eb3278cSbostic case NODE_LIST: 37413082428Sbill if (t->t_dcar) { 3755eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 376f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 37713082428Sbill /* 37813082428Sbill * In strange case of A&B make a new job after A 37913082428Sbill */ 3805eb3278cSbostic if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 3815eb3278cSbostic (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 38213082428Sbill pendjob(); 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 3915eb3278cSbostic case NODE_OR: 3925eb3278cSbostic case NODE_AND: 39313082428Sbill if (t->t_dcar) { 3945eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 395f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 396f3328da7Sbostic if ((getn(value(STRstatus)) == 0) != 3975eb3278cSbostic (t->t_dtyp == NODE_AND)) 39813082428Sbill return; 39913082428Sbill } 40013082428Sbill if (t->t_dcdr) { 401f3328da7Sbostic t->t_dcdr->t_dflg |= t->t_dflg & 402f3328da7Sbostic (F_NOFORK | F_NOINTERRUPT); 403f3328da7Sbostic execute(t->t_dcdr, wanttty, NULL, NULL); 40413082428Sbill } 40513082428Sbill break; 40613082428Sbill } 40713082428Sbill /* 408f3328da7Sbostic * Fall through for all breaks from switch 40913082428Sbill * 410f3328da7Sbostic * If there will be no more executions of this command, flush all file 411f3328da7Sbostic * descriptors. Places that turn on the F_REPEAT bit are responsible for 412f3328da7Sbostic * doing donefds after the last re-execution 41313082428Sbill */ 4145eb3278cSbostic if (didfds && !(t->t_dflg & F_REPEAT)) 41513082428Sbill donefds(); 41613082428Sbill } 41713082428Sbill 418f3328da7Sbostic static void 41923ceb1ffSchristos vffree(i) 42023ceb1ffSchristos int i; 42113082428Sbill { 422f3328da7Sbostic register Char **v; 42313082428Sbill 424f3328da7Sbostic if (v = gargv) { 425f3328da7Sbostic gargv = 0; 426f3328da7Sbostic xfree((ptr_t) v); 427f3328da7Sbostic } 428f3328da7Sbostic if (v = pargv) { 429f3328da7Sbostic pargv = 0; 430f3328da7Sbostic xfree((ptr_t) v); 431f3328da7Sbostic } 43223ceb1ffSchristos _exit(i); 43313082428Sbill } 434f3328da7Sbostic 43513082428Sbill /* 4362ff0ec22Schristos * Expand and glob the words after an i/o redirection. 4372ff0ec22Schristos * If more than one word is generated, then update the command vector. 4382ff0ec22Schristos * 4392ff0ec22Schristos * This is done differently in all the shells: 4402ff0ec22Schristos * 1. in the bourne shell and ksh globbing is not performed 4412ff0ec22Schristos * 2. Bash/csh say ambiguous 4422ff0ec22Schristos * 3. zsh does i/o to/from all the files 4432ff0ec22Schristos * 4. itcsh concatenates the words. 4442ff0ec22Schristos * 4452ff0ec22Schristos * I don't know what is best to do. I think that Ambiguous is better 4462ff0ec22Schristos * than restructuring the command vector, because the user can get 4472ff0ec22Schristos * unexpected results. In any case, the command vector restructuring 4482ff0ec22Schristos * code is present and the user can choose it by setting noambiguous 4492ff0ec22Schristos */ 4502ff0ec22Schristos static Char * 4512ff0ec22Schristos splicepipe(t, cp) 4522ff0ec22Schristos register struct command *t; 4532ff0ec22Schristos Char *cp; /* word after < or > */ 4542ff0ec22Schristos { 4552ff0ec22Schristos Char *blk[2]; 4562ff0ec22Schristos 4572ff0ec22Schristos if (adrof(STRnoambiguous)) { 4582ff0ec22Schristos Char **pv; 4592ff0ec22Schristos 4602ff0ec22Schristos blk[0] = Dfix1(cp); /* expand $ */ 4612ff0ec22Schristos blk[1] = NULL; 4622ff0ec22Schristos 4632ff0ec22Schristos gflag = 0, tglob(blk); 4642ff0ec22Schristos if (gflag) { 4652ff0ec22Schristos pv = globall(blk); 4662ff0ec22Schristos if (pv == NULL) { 467*8d2f70fbSchristos setname(vis_str(blk[0])); 4682ff0ec22Schristos xfree((ptr_t) blk[0]); 4692ff0ec22Schristos stderror(ERR_NAME | ERR_NOMATCH); 4702ff0ec22Schristos } 4712ff0ec22Schristos gargv = NULL; 4722ff0ec22Schristos if (pv[1] != NULL) { /* we need to fix the command vector */ 4732ff0ec22Schristos Char **av = blkspl(t->t_dcom, &pv[1]); 4742ff0ec22Schristos xfree((ptr_t) t->t_dcom); 4752ff0ec22Schristos t->t_dcom = av; 4762ff0ec22Schristos } 4772ff0ec22Schristos xfree((ptr_t) blk[0]); 4782ff0ec22Schristos blk[0] = pv[0]; 4792ff0ec22Schristos xfree((ptr_t) pv); 4802ff0ec22Schristos } 4812ff0ec22Schristos } 4822ff0ec22Schristos else { 4832ff0ec22Schristos blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR); 4842ff0ec22Schristos xfree((ptr_t) blk[1]); 4852ff0ec22Schristos } 4862ff0ec22Schristos return(blk[0]); 4872ff0ec22Schristos } 4882ff0ec22Schristos 4892ff0ec22Schristos /* 49013082428Sbill * Perform io redirection. 49113082428Sbill * We may or maynot be forked here. 49213082428Sbill */ 493f3328da7Sbostic static void 49413082428Sbill doio(t, pipein, pipeout) 49513082428Sbill register struct command *t; 49613082428Sbill int *pipein, *pipeout; 49713082428Sbill { 498f3328da7Sbostic register int fd; 4992ff0ec22Schristos register Char *cp; 50013082428Sbill register int flags = t->t_dflg; 50113082428Sbill 5025eb3278cSbostic if (didfds || (flags & F_REPEAT)) 50313082428Sbill return; 5045eb3278cSbostic if ((flags & F_READ) == 0) {/* F_READ already done */ 5052ff0ec22Schristos if (t->t_dlef) { 506e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 507f3328da7Sbostic 508f3328da7Sbostic /* 509f3328da7Sbostic * so < /dev/std{in,out,err} work 510f3328da7Sbostic */ 511f3328da7Sbostic (void) dcopy(SHIN, 0); 512f3328da7Sbostic (void) dcopy(SHOUT, 1); 513cce51c35Schristos (void) dcopy(SHERR, 2); 5142ff0ec22Schristos cp = splicepipe(t, t->t_dlef); 515f3328da7Sbostic (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 516e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 517f3328da7Sbostic xfree((ptr_t) cp); 518f3328da7Sbostic if ((fd = open(tmp, O_RDONLY)) < 0) 519f3328da7Sbostic stderror(ERR_SYSTEM, tmp, strerror(errno)); 520f3328da7Sbostic (void) dmove(fd, 0); 521f3328da7Sbostic } 522f3328da7Sbostic else if (flags & F_PIPEIN) { 523f3328da7Sbostic (void) close(0); 52443fabe3fSedward (void) dup(pipein[0]); 52543fabe3fSedward (void) close(pipein[0]); 52643fabe3fSedward (void) close(pipein[1]); 527f3328da7Sbostic } 528f3328da7Sbostic else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 52943fabe3fSedward (void) close(0); 530f3328da7Sbostic (void) open(_PATH_DEVNULL, O_RDONLY); 531f3328da7Sbostic } 532f3328da7Sbostic else { 533f3328da7Sbostic (void) close(0); 534cde959b4Sedward (void) dup(OLDSTD); 5359374f148Sbostic (void) ioctl(0, FIONCLEX, NULL); 53613082428Sbill } 537f3328da7Sbostic } 5382ff0ec22Schristos if (t->t_drit) { 539e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 540f3328da7Sbostic 5412ff0ec22Schristos cp = splicepipe(t, t->t_drit); 542e78a8ca9Schristos (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 543e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 544f3328da7Sbostic xfree((ptr_t) cp); 545f3328da7Sbostic /* 546f3328da7Sbostic * so > /dev/std{out,err} work 547f3328da7Sbostic */ 548f3328da7Sbostic (void) dcopy(SHOUT, 1); 549cce51c35Schristos (void) dcopy(SHERR, 2); 550f3328da7Sbostic if ((flags & F_APPEND) && 551f3328da7Sbostic #ifdef O_APPEND 552e78a8ca9Schristos (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); 553f3328da7Sbostic #else 554e78a8ca9Schristos (fd = open(tmp, O_WRONLY)) >= 0) 555f3328da7Sbostic (void) lseek(1, (off_t) 0, L_XTND); 556f3328da7Sbostic #endif 557f3328da7Sbostic else { 558f3328da7Sbostic if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 5595eb3278cSbostic if (flags & F_APPEND) 560e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 561f3328da7Sbostic chkclob(tmp); 56213082428Sbill } 563e78a8ca9Schristos if ((fd = creat(tmp, 0666)) < 0) 564e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 56513082428Sbill } 566f3328da7Sbostic (void) dmove(fd, 1); 567f3328da7Sbostic } 568f3328da7Sbostic else if (flags & F_PIPEOUT) { 569f3328da7Sbostic (void) close(1); 57043fabe3fSedward (void) dup(pipeout[1]); 571f3328da7Sbostic } 572f3328da7Sbostic else { 573f3328da7Sbostic (void) close(1); 574cde959b4Sedward (void) dup(SHOUT); 5759374f148Sbostic (void) ioctl(1, FIONCLEX, NULL); 576f3328da7Sbostic } 57713082428Sbill 57843fabe3fSedward (void) close(2); 579f3328da7Sbostic if (flags & F_STDERR) { 58043fabe3fSedward (void) dup(1); 581f3328da7Sbostic } 582f3328da7Sbostic else { 583cce51c35Schristos (void) dup(SHERR); 5849374f148Sbostic (void) ioctl(2, FIONCLEX, NULL); 585f3328da7Sbostic } 58613082428Sbill didfds = 1; 58713082428Sbill } 58813082428Sbill 589f3328da7Sbostic void 59013082428Sbill mypipe(pv) 59113082428Sbill register int *pv; 59213082428Sbill { 59313082428Sbill 59413082428Sbill if (pipe(pv) < 0) 59513082428Sbill goto oops; 59613082428Sbill pv[0] = dmove(pv[0], -1); 59713082428Sbill pv[1] = dmove(pv[1], -1); 59813082428Sbill if (pv[0] >= 0 && pv[1] >= 0) 59913082428Sbill return; 60013082428Sbill oops: 601f3328da7Sbostic stderror(ERR_PIPE); 60213082428Sbill } 60313082428Sbill 604f3328da7Sbostic static void 60513082428Sbill chkclob(cp) 606e78a8ca9Schristos register char *cp; 60713082428Sbill { 60813082428Sbill struct stat stb; 60913082428Sbill 610e78a8ca9Schristos if (stat(cp, &stb) < 0) 61113082428Sbill return; 6122ff0ec22Schristos if (S_ISCHR(stb.st_mode)) 61313082428Sbill return; 614e78a8ca9Schristos stderror(ERR_EXISTS, cp); 61513082428Sbill } 616