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*50cee248Schristos static char sccsid[] = "@(#)sem.c 5.23 (Berkeley) 05/22/93"; 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 51*50cee248Schristos UNREGISTER(forked); 52*50cee248Schristos UNREGISTER(bifunc); 53*50cee248Schristos UNREGISTER(wanttty); 54*50cee248Schristos 5513082428Sbill if (t == 0) 5613082428Sbill return; 57f3328da7Sbostic 58f3328da7Sbostic if (t->t_dflg & F_AMPERSAND) 5913082428Sbill wanttty = 0; 6013082428Sbill switch (t->t_dtyp) { 6113082428Sbill 625eb3278cSbostic case NODE_COMMAND: 6313082428Sbill if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 64f3328da7Sbostic (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 655eb3278cSbostic if ((t->t_dflg & F_REPEAT) == 0) 6613082428Sbill Dfix(t); /* $ " ' \ */ 6713082428Sbill if (t->t_dcom[0] == 0) 6813082428Sbill return; 6913082428Sbill /* fall into... */ 7013082428Sbill 715eb3278cSbostic case NODE_PAREN: 725eb3278cSbostic if (t->t_dflg & F_PIPEOUT) 7313082428Sbill mypipe(pipeout); 7413082428Sbill /* 75f3328da7Sbostic * Must do << early so parent will know where input pointer should be. 7613082428Sbill * If noexec then this is all we do. 7713082428Sbill */ 785eb3278cSbostic if (t->t_dflg & F_READ) { 7943fabe3fSedward (void) close(0); 8013082428Sbill heredoc(t->t_dlef); 8113082428Sbill if (noexec) 8243fabe3fSedward (void) close(0); 8313082428Sbill } 8413082428Sbill 85f3328da7Sbostic set(STRstatus, Strsave(STR0)); 8613082428Sbill 8713082428Sbill /* 88f3328da7Sbostic * This mess is the necessary kludge to handle the prefix builtins: 89f3328da7Sbostic * nice, nohup, time. These commands can also be used by themselves, 90f3328da7Sbostic * and this is not handled here. This will also work when loops are 91f3328da7Sbostic * parsed. 9213082428Sbill */ 935eb3278cSbostic while (t->t_dtyp == NODE_COMMAND) 94f3328da7Sbostic if (eq(t->t_dcom[0], STRnice)) 9513082428Sbill if (t->t_dcom[1]) 96f3328da7Sbostic if (strchr("+-", t->t_dcom[1][0])) 9713082428Sbill if (t->t_dcom[2]) { 9813082428Sbill setname("nice"); 99f3328da7Sbostic t->t_nice = 100f3328da7Sbostic getn(t->t_dcom[1]); 10113082428Sbill lshift(t->t_dcom, 2); 1025eb3278cSbostic t->t_dflg |= F_NICE; 103f3328da7Sbostic } 104f3328da7Sbostic else 10513082428Sbill break; 10613082428Sbill else { 10713082428Sbill t->t_nice = 4; 10813082428Sbill lshift(t->t_dcom, 1); 1095eb3278cSbostic t->t_dflg |= F_NICE; 11013082428Sbill } 11113082428Sbill else 11213082428Sbill break; 113f3328da7Sbostic else if (eq(t->t_dcom[0], STRnohup)) 11413082428Sbill if (t->t_dcom[1]) { 1155eb3278cSbostic t->t_dflg |= F_NOHUP; 11613082428Sbill lshift(t->t_dcom, 1); 117f3328da7Sbostic } 118f3328da7Sbostic else 11913082428Sbill break; 120f3328da7Sbostic else if (eq(t->t_dcom[0], STRtime)) 12113082428Sbill if (t->t_dcom[1]) { 1225eb3278cSbostic t->t_dflg |= F_TIME; 12313082428Sbill lshift(t->t_dcom, 1); 124f3328da7Sbostic } 125f3328da7Sbostic else 12613082428Sbill break; 12713082428Sbill else 12813082428Sbill break; 129f3328da7Sbostic 130336c1b24Schristos /* is it a command */ 131f3328da7Sbostic if (t->t_dtyp == NODE_COMMAND) { 13213082428Sbill /* 13313082428Sbill * Check if we have a builtin function and remember which one. 13413082428Sbill */ 135f3328da7Sbostic bifunc = isbfunc(t); 136336c1b24Schristos if (noexec) { 137336c1b24Schristos /* 138336c1b24Schristos * Continue for builtins that are part of the scripting language 139336c1b24Schristos */ 140336c1b24Schristos if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin && 141336c1b24Schristos bifunc->bfunct != doelse && bifunc->bfunct != doend && 142336c1b24Schristos bifunc->bfunct != doforeach && bifunc->bfunct != dogoto && 143336c1b24Schristos bifunc->bfunct != doif && bifunc->bfunct != dorepeat && 144336c1b24Schristos bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch && 145336c1b24Schristos bifunc->bfunct != dowhile && bifunc->bfunct != dozip) 146336c1b24Schristos break; 147336c1b24Schristos } 148f3328da7Sbostic } 149f3328da7Sbostic else { /* not a command */ 1509374f148Sbostic bifunc = NULL; 151336c1b24Schristos if (noexec) 152336c1b24Schristos break; 153f3328da7Sbostic } 15413082428Sbill 15513082428Sbill /* 156f3328da7Sbostic * We fork only if we are timed, or are not the end of a parenthesized 157f3328da7Sbostic * list and not a simple builtin function. Simple meaning one that is 158f3328da7Sbostic * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 159f3328da7Sbostic * fork in some of these cases. 16013082428Sbill */ 161f3328da7Sbostic /* 162f3328da7Sbostic * Prevent forking cd, pushd, popd, chdir cause this will cause the 163f3328da7Sbostic * shell not to change dir! 164f3328da7Sbostic */ 165f3328da7Sbostic if (bifunc && (bifunc->bfunct == dochngd || 166f3328da7Sbostic bifunc->bfunct == dopushd || 167f3328da7Sbostic bifunc->bfunct == dopopd)) 168f3328da7Sbostic t->t_dflg &= ~(F_NICE); 169*50cee248Schristos if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && 170f3328da7Sbostic (!bifunc || t->t_dflg & 171*50cee248Schristos (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) || 172f3328da7Sbostic /* 173f3328da7Sbostic * We have to fork for eval too. 174f3328da7Sbostic */ 175cce51c35Schristos (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 && 176f3328da7Sbostic bifunc->bfunct == doeval)) 1775eb3278cSbostic if (t->t_dtyp == NODE_PAREN || 178afc71901Sbostic t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) { 179f3328da7Sbostic forked++; 180f3328da7Sbostic /* 181f3328da7Sbostic * We need to block SIGCHLD here, so that if the process does 182f3328da7Sbostic * not die before we can set the process group 183f3328da7Sbostic */ 1845e5c7fccSmarc if (wanttty >= 0 && !nosigchld) { 185f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 1865e5c7fccSmarc nosigchld = 1; 1875e5c7fccSmarc } 1885e5c7fccSmarc 1895e5c7fccSmarc pid = pfork(t, wanttty); 1905e5c7fccSmarc if (pid == 0 && nosigchld) { 191f3328da7Sbostic (void) sigsetmask(csigmask); 1925e5c7fccSmarc nosigchld = 0; 1935e5c7fccSmarc } 1942ff0ec22Schristos else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) 1952ff0ec22Schristos backpid = pid; 1962ff0ec22Schristos 1975e5c7fccSmarc } 19813082428Sbill else { 19943fabe3fSedward int ochild, osetintr, ohaderr, odidfds; 200cce51c35Schristos int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp; 2019374f148Sbostic sigset_t omask; 20213082428Sbill 20315d9e91aSlepreau /* 204f3328da7Sbostic * Prepare for the vfork by saving everything that the child 205f3328da7Sbostic * corrupts before it exec's. Note that in some signal 206f3328da7Sbostic * implementations which keep the signal info in user space 207f3328da7Sbostic * (e.g. Sun's) it will also be necessary to save and restore 208f3328da7Sbostic * the current sigvec's for the signals the child touches 209f3328da7Sbostic * before it exec's. 21015d9e91aSlepreau */ 2115e5c7fccSmarc if (wanttty >= 0 && !nosigchld && !noexec) { 212f3328da7Sbostic csigmask = sigblock(sigmask(SIGCHLD)); 2135e5c7fccSmarc nosigchld = 1; 2145e5c7fccSmarc } 215f3328da7Sbostic omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT)); 216f3328da7Sbostic ochild = child; 217f3328da7Sbostic osetintr = setintr; 218f3328da7Sbostic ohaderr = haderr; 219f3328da7Sbostic odidfds = didfds; 220f3328da7Sbostic oSHIN = SHIN; 221f3328da7Sbostic oSHOUT = SHOUT; 222cce51c35Schristos oSHERR = SHERR; 223f3328da7Sbostic oOLDSTD = OLDSTD; 224f3328da7Sbostic otpgrp = tpgrp; 225f3328da7Sbostic ocsigmask = csigmask; 226f3328da7Sbostic onosigchld = nosigchld; 227f3328da7Sbostic Vsav = Vdp = 0; 228f3328da7Sbostic Vexpath = 0; 229f3328da7Sbostic Vt = 0; 23013082428Sbill pid = vfork(); 231f3328da7Sbostic 23213082428Sbill if (pid < 0) { 23343fabe3fSedward (void) sigsetmask(omask); 234f3328da7Sbostic stderror(ERR_NOPROC); 23513082428Sbill } 23613082428Sbill forked++; 23715d9e91aSlepreau if (pid) { /* parent */ 238f3328da7Sbostic child = ochild; 239f3328da7Sbostic setintr = osetintr; 240f3328da7Sbostic haderr = ohaderr; 241f3328da7Sbostic didfds = odidfds; 24243fabe3fSedward SHIN = oSHIN; 243f3328da7Sbostic SHOUT = oSHOUT; 244cce51c35Schristos SHERR = oSHERR; 245f3328da7Sbostic OLDSTD = oOLDSTD; 246f3328da7Sbostic tpgrp = otpgrp; 247f3328da7Sbostic csigmask = ocsigmask; 248f3328da7Sbostic nosigchld = onosigchld; 249f3328da7Sbostic 250f3328da7Sbostic xfree((ptr_t) Vsav); 251f3328da7Sbostic Vsav = 0; 252f3328da7Sbostic xfree((ptr_t) Vdp); 253f3328da7Sbostic Vdp = 0; 254f3328da7Sbostic xfree((ptr_t) Vexpath); 255f3328da7Sbostic Vexpath = 0; 256f3328da7Sbostic blkfree((Char **) Vt); 257f3328da7Sbostic Vt = 0; 25813082428Sbill /* this is from pfork() */ 25913082428Sbill palloc(pid, t); 26043fabe3fSedward (void) sigsetmask(omask); 261f3328da7Sbostic } 262f3328da7Sbostic else { /* child */ 26313082428Sbill /* this is from pfork() */ 26413082428Sbill int pgrp; 26513082428Sbill bool ignint = 0; 26613082428Sbill 2675e5c7fccSmarc if (nosigchld) { 268f3328da7Sbostic (void) sigsetmask(csigmask); 2695e5c7fccSmarc nosigchld = 0; 2705e5c7fccSmarc } 271f3328da7Sbostic 27213082428Sbill if (setintr) 273f3328da7Sbostic ignint = 274f3328da7Sbostic (tpgrp == -1 && 275f3328da7Sbostic (t->t_dflg & F_NOINTERRUPT)) 276*50cee248Schristos || (gointr && eq(gointr, STRminus)); 27713082428Sbill pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 27813082428Sbill child++; 27913082428Sbill if (setintr) { 28013082428Sbill setintr = 0; 281f3328da7Sbostic if (ignint) { 282f3328da7Sbostic (void) signal(SIGINT, SIG_IGN); 283f3328da7Sbostic (void) signal(SIGQUIT, SIG_IGN); 284f3328da7Sbostic } 285f3328da7Sbostic else { 286f3328da7Sbostic (void) signal(SIGINT, vffree); 287f3328da7Sbostic (void) signal(SIGQUIT, SIG_DFL); 288f3328da7Sbostic } 289f3328da7Sbostic 29013082428Sbill if (wanttty >= 0) { 29143fabe3fSedward (void) signal(SIGTSTP, SIG_DFL); 29243fabe3fSedward (void) signal(SIGTTIN, SIG_DFL); 29343fabe3fSedward (void) signal(SIGTTOU, SIG_DFL); 29413082428Sbill } 295f3328da7Sbostic 29643fabe3fSedward (void) signal(SIGTERM, parterm); 297f3328da7Sbostic } 298f3328da7Sbostic else if (tpgrp == -1 && 2995eb3278cSbostic (t->t_dflg & F_NOINTERRUPT)) { 30043fabe3fSedward (void) signal(SIGINT, SIG_IGN); 30143fabe3fSedward (void) signal(SIGQUIT, SIG_IGN); 30213082428Sbill } 303f3328da7Sbostic 304f3328da7Sbostic pgetty(wanttty, pgrp); 3055eb3278cSbostic if (t->t_dflg & F_NOHUP) 30643fabe3fSedward (void) signal(SIGHUP, SIG_IGN); 3075eb3278cSbostic if (t->t_dflg & F_NICE) 308f3328da7Sbostic (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 30913082428Sbill } 31013082428Sbill 31113082428Sbill } 31213082428Sbill if (pid != 0) { 31313082428Sbill /* 314f3328da7Sbostic * It would be better if we could wait for the whole job when we 315f3328da7Sbostic * knew the last process had been started. Pwait, in fact, does 316f3328da7Sbostic * wait for the whole job anyway, but this test doesn't really 317f3328da7Sbostic * express our intentions. 31813082428Sbill */ 3195eb3278cSbostic if (didfds == 0 && t->t_dflg & F_PIPEIN) { 32043fabe3fSedward (void) close(pipein[0]); 32143fabe3fSedward (void) close(pipein[1]); 32243fabe3fSedward } 3235eb3278cSbostic if ((t->t_dflg & F_PIPEOUT) == 0) { 3245e5c7fccSmarc if (nosigchld) { 325f3328da7Sbostic (void) sigsetmask(csigmask); 3265e5c7fccSmarc nosigchld = 0; 3275e5c7fccSmarc } 3285eb3278cSbostic if ((t->t_dflg & F_AMPERSAND) == 0) 32913082428Sbill pwait(); 3305e5c7fccSmarc } 33113082428Sbill break; 33213082428Sbill } 33313082428Sbill doio(t, pipein, pipeout); 3345eb3278cSbostic if (t->t_dflg & F_PIPEOUT) { 33543fabe3fSedward (void) close(pipeout[0]); 33643fabe3fSedward (void) close(pipeout[1]); 33743fabe3fSedward } 33813082428Sbill /* 339f3328da7Sbostic * Perform a builtin function. If we are not forked, arrange for 340f3328da7Sbostic * possible stopping 34113082428Sbill */ 34213082428Sbill if (bifunc) { 34313082428Sbill func(t, bifunc); 34413082428Sbill if (forked) 34513082428Sbill exitstat(); 34613082428Sbill break; 34713082428Sbill } 3485eb3278cSbostic if (t->t_dtyp != NODE_PAREN) { 349cce51c35Schristos doexec(NULL, t); 35013082428Sbill /* NOTREACHED */ 35113082428Sbill } 35213082428Sbill /* 35313082428Sbill * For () commands must put new 0,1,2 in FSH* and recurse 35413082428Sbill */ 35513082428Sbill OLDSTD = dcopy(0, FOLDSTD); 35613082428Sbill SHOUT = dcopy(1, FSHOUT); 357cce51c35Schristos SHERR = dcopy(2, FSHERR); 35843fabe3fSedward (void) close(SHIN); 35943fabe3fSedward SHIN = -1; 36043fabe3fSedward didfds = 0; 36113082428Sbill wanttty = -1; 3625eb3278cSbostic t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 363f3328da7Sbostic execute(t->t_dspr, wanttty, NULL, NULL); 36413082428Sbill exitstat(); 36513082428Sbill 3665eb3278cSbostic case NODE_PIPE: 3675eb3278cSbostic t->t_dcar->t_dflg |= F_PIPEOUT | 3685eb3278cSbostic (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 36913082428Sbill execute(t->t_dcar, wanttty, pipein, pv); 370f3328da7Sbostic t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 3715eb3278cSbostic (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 37213082428Sbill if (wanttty > 0) 37313082428Sbill wanttty = 0; /* got tty already */ 37413082428Sbill execute(t->t_dcdr, wanttty, pv, pipeout); 37513082428Sbill break; 37613082428Sbill 3775eb3278cSbostic case NODE_LIST: 37813082428Sbill if (t->t_dcar) { 3795eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 380f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 38113082428Sbill /* 38213082428Sbill * In strange case of A&B make a new job after A 38313082428Sbill */ 3845eb3278cSbostic if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 3855eb3278cSbostic (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 38613082428Sbill pendjob(); 38713082428Sbill } 38813082428Sbill if (t->t_dcdr) { 389f3328da7Sbostic t->t_dcdr->t_dflg |= t->t_dflg & 390f3328da7Sbostic (F_NOFORK | F_NOINTERRUPT); 391f3328da7Sbostic execute(t->t_dcdr, wanttty, NULL, NULL); 39213082428Sbill } 39313082428Sbill break; 39413082428Sbill 3955eb3278cSbostic case NODE_OR: 3965eb3278cSbostic case NODE_AND: 39713082428Sbill if (t->t_dcar) { 3985eb3278cSbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 399f3328da7Sbostic execute(t->t_dcar, wanttty, NULL, NULL); 400f3328da7Sbostic if ((getn(value(STRstatus)) == 0) != 4015eb3278cSbostic (t->t_dtyp == NODE_AND)) 40213082428Sbill return; 40313082428Sbill } 40413082428Sbill if (t->t_dcdr) { 405f3328da7Sbostic t->t_dcdr->t_dflg |= t->t_dflg & 406f3328da7Sbostic (F_NOFORK | F_NOINTERRUPT); 407f3328da7Sbostic execute(t->t_dcdr, wanttty, NULL, NULL); 40813082428Sbill } 40913082428Sbill break; 41013082428Sbill } 41113082428Sbill /* 412f3328da7Sbostic * Fall through for all breaks from switch 41313082428Sbill * 414f3328da7Sbostic * If there will be no more executions of this command, flush all file 415f3328da7Sbostic * descriptors. Places that turn on the F_REPEAT bit are responsible for 416f3328da7Sbostic * doing donefds after the last re-execution 41713082428Sbill */ 4185eb3278cSbostic if (didfds && !(t->t_dflg & F_REPEAT)) 41913082428Sbill donefds(); 42013082428Sbill } 42113082428Sbill 422f3328da7Sbostic static void 42323ceb1ffSchristos vffree(i) 42423ceb1ffSchristos int i; 42513082428Sbill { 426f3328da7Sbostic register Char **v; 42713082428Sbill 428*50cee248Schristos if ((v = gargv) != NULL) { 429f3328da7Sbostic gargv = 0; 430f3328da7Sbostic xfree((ptr_t) v); 431f3328da7Sbostic } 432*50cee248Schristos if ((v = pargv) != NULL) { 433f3328da7Sbostic pargv = 0; 434f3328da7Sbostic xfree((ptr_t) v); 435f3328da7Sbostic } 43623ceb1ffSchristos _exit(i); 43713082428Sbill } 438f3328da7Sbostic 43913082428Sbill /* 4402ff0ec22Schristos * Expand and glob the words after an i/o redirection. 4412ff0ec22Schristos * If more than one word is generated, then update the command vector. 4422ff0ec22Schristos * 4432ff0ec22Schristos * This is done differently in all the shells: 4442ff0ec22Schristos * 1. in the bourne shell and ksh globbing is not performed 4452ff0ec22Schristos * 2. Bash/csh say ambiguous 4462ff0ec22Schristos * 3. zsh does i/o to/from all the files 4472ff0ec22Schristos * 4. itcsh concatenates the words. 4482ff0ec22Schristos * 4492ff0ec22Schristos * I don't know what is best to do. I think that Ambiguous is better 4502ff0ec22Schristos * than restructuring the command vector, because the user can get 4512ff0ec22Schristos * unexpected results. In any case, the command vector restructuring 4522ff0ec22Schristos * code is present and the user can choose it by setting noambiguous 4532ff0ec22Schristos */ 4542ff0ec22Schristos static Char * 4552ff0ec22Schristos splicepipe(t, cp) 4562ff0ec22Schristos register struct command *t; 4572ff0ec22Schristos Char *cp; /* word after < or > */ 4582ff0ec22Schristos { 4592ff0ec22Schristos Char *blk[2]; 4602ff0ec22Schristos 4612ff0ec22Schristos if (adrof(STRnoambiguous)) { 4622ff0ec22Schristos Char **pv; 4632ff0ec22Schristos 4642ff0ec22Schristos blk[0] = Dfix1(cp); /* expand $ */ 4652ff0ec22Schristos blk[1] = NULL; 4662ff0ec22Schristos 4672ff0ec22Schristos gflag = 0, tglob(blk); 4682ff0ec22Schristos if (gflag) { 4692ff0ec22Schristos pv = globall(blk); 4702ff0ec22Schristos if (pv == NULL) { 4718d2f70fbSchristos setname(vis_str(blk[0])); 4722ff0ec22Schristos xfree((ptr_t) blk[0]); 4732ff0ec22Schristos stderror(ERR_NAME | ERR_NOMATCH); 4742ff0ec22Schristos } 4752ff0ec22Schristos gargv = NULL; 4762ff0ec22Schristos if (pv[1] != NULL) { /* we need to fix the command vector */ 4772ff0ec22Schristos Char **av = blkspl(t->t_dcom, &pv[1]); 4782ff0ec22Schristos xfree((ptr_t) t->t_dcom); 4792ff0ec22Schristos t->t_dcom = av; 4802ff0ec22Schristos } 4812ff0ec22Schristos xfree((ptr_t) blk[0]); 4822ff0ec22Schristos blk[0] = pv[0]; 4832ff0ec22Schristos xfree((ptr_t) pv); 4842ff0ec22Schristos } 4852ff0ec22Schristos } 4862ff0ec22Schristos else { 4872ff0ec22Schristos blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR); 4882ff0ec22Schristos xfree((ptr_t) blk[1]); 4892ff0ec22Schristos } 4902ff0ec22Schristos return(blk[0]); 4912ff0ec22Schristos } 4922ff0ec22Schristos 4932ff0ec22Schristos /* 49413082428Sbill * Perform io redirection. 49513082428Sbill * We may or maynot be forked here. 49613082428Sbill */ 497f3328da7Sbostic static void 49813082428Sbill doio(t, pipein, pipeout) 49913082428Sbill register struct command *t; 50013082428Sbill int *pipein, *pipeout; 50113082428Sbill { 502f3328da7Sbostic register int fd; 5032ff0ec22Schristos register Char *cp; 50413082428Sbill register int flags = t->t_dflg; 50513082428Sbill 5065eb3278cSbostic if (didfds || (flags & F_REPEAT)) 50713082428Sbill return; 5085eb3278cSbostic if ((flags & F_READ) == 0) {/* F_READ already done */ 5092ff0ec22Schristos if (t->t_dlef) { 510e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 511f3328da7Sbostic 512f3328da7Sbostic /* 513f3328da7Sbostic * so < /dev/std{in,out,err} work 514f3328da7Sbostic */ 515f3328da7Sbostic (void) dcopy(SHIN, 0); 516f3328da7Sbostic (void) dcopy(SHOUT, 1); 517cce51c35Schristos (void) dcopy(SHERR, 2); 5182ff0ec22Schristos cp = splicepipe(t, t->t_dlef); 519f3328da7Sbostic (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 520e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 521f3328da7Sbostic xfree((ptr_t) cp); 522f3328da7Sbostic if ((fd = open(tmp, O_RDONLY)) < 0) 523f3328da7Sbostic stderror(ERR_SYSTEM, tmp, strerror(errno)); 524f3328da7Sbostic (void) dmove(fd, 0); 525f3328da7Sbostic } 526f3328da7Sbostic else if (flags & F_PIPEIN) { 527f3328da7Sbostic (void) close(0); 52843fabe3fSedward (void) dup(pipein[0]); 52943fabe3fSedward (void) close(pipein[0]); 53043fabe3fSedward (void) close(pipein[1]); 531f3328da7Sbostic } 532f3328da7Sbostic else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 53343fabe3fSedward (void) close(0); 534f3328da7Sbostic (void) open(_PATH_DEVNULL, O_RDONLY); 535f3328da7Sbostic } 536f3328da7Sbostic else { 537f3328da7Sbostic (void) close(0); 538cde959b4Sedward (void) dup(OLDSTD); 5399374f148Sbostic (void) ioctl(0, FIONCLEX, NULL); 54013082428Sbill } 541f3328da7Sbostic } 5422ff0ec22Schristos if (t->t_drit) { 543e78a8ca9Schristos char tmp[MAXPATHLEN+1]; 544f3328da7Sbostic 5452ff0ec22Schristos cp = splicepipe(t, t->t_drit); 546e78a8ca9Schristos (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 547e78a8ca9Schristos tmp[MAXPATHLEN] = '\0'; 548f3328da7Sbostic xfree((ptr_t) cp); 549f3328da7Sbostic /* 550f3328da7Sbostic * so > /dev/std{out,err} work 551f3328da7Sbostic */ 552f3328da7Sbostic (void) dcopy(SHOUT, 1); 553cce51c35Schristos (void) dcopy(SHERR, 2); 554f3328da7Sbostic if ((flags & F_APPEND) && 555f3328da7Sbostic #ifdef O_APPEND 556e78a8ca9Schristos (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); 557f3328da7Sbostic #else 558e78a8ca9Schristos (fd = open(tmp, O_WRONLY)) >= 0) 559f3328da7Sbostic (void) lseek(1, (off_t) 0, L_XTND); 560f3328da7Sbostic #endif 561f3328da7Sbostic else { 562f3328da7Sbostic if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 5635eb3278cSbostic if (flags & F_APPEND) 564e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 565f3328da7Sbostic chkclob(tmp); 56613082428Sbill } 567e78a8ca9Schristos if ((fd = creat(tmp, 0666)) < 0) 568e78a8ca9Schristos stderror(ERR_SYSTEM, tmp, strerror(errno)); 56913082428Sbill } 570f3328da7Sbostic (void) dmove(fd, 1); 571f3328da7Sbostic } 572f3328da7Sbostic else if (flags & F_PIPEOUT) { 573f3328da7Sbostic (void) close(1); 57443fabe3fSedward (void) dup(pipeout[1]); 575f3328da7Sbostic } 576f3328da7Sbostic else { 577f3328da7Sbostic (void) close(1); 578cde959b4Sedward (void) dup(SHOUT); 5799374f148Sbostic (void) ioctl(1, FIONCLEX, NULL); 580f3328da7Sbostic } 58113082428Sbill 58243fabe3fSedward (void) close(2); 583f3328da7Sbostic if (flags & F_STDERR) { 58443fabe3fSedward (void) dup(1); 585f3328da7Sbostic } 586f3328da7Sbostic else { 587cce51c35Schristos (void) dup(SHERR); 5889374f148Sbostic (void) ioctl(2, FIONCLEX, NULL); 589f3328da7Sbostic } 59013082428Sbill didfds = 1; 59113082428Sbill } 59213082428Sbill 593f3328da7Sbostic void 59413082428Sbill mypipe(pv) 59513082428Sbill register int *pv; 59613082428Sbill { 59713082428Sbill 59813082428Sbill if (pipe(pv) < 0) 59913082428Sbill goto oops; 60013082428Sbill pv[0] = dmove(pv[0], -1); 60113082428Sbill pv[1] = dmove(pv[1], -1); 60213082428Sbill if (pv[0] >= 0 && pv[1] >= 0) 60313082428Sbill return; 60413082428Sbill oops: 605f3328da7Sbostic stderror(ERR_PIPE); 60613082428Sbill } 60713082428Sbill 608f3328da7Sbostic static void 60913082428Sbill chkclob(cp) 610e78a8ca9Schristos register char *cp; 61113082428Sbill { 61213082428Sbill struct stat stb; 61313082428Sbill 614e78a8ca9Schristos if (stat(cp, &stb) < 0) 61513082428Sbill return; 6162ff0ec22Schristos if (S_ISCHR(stb.st_mode)) 61713082428Sbill return; 618e78a8ca9Schristos stderror(ERR_EXISTS, cp); 61913082428Sbill } 620