sh.sem.c revision 69408
177696Sbrian/* $Header: /src/pub/tcsh/sh.sem.c,v 3.51 2000/11/11 23:03:38 christos Exp $ */ 236321Samurai/* 377696Sbrian * sh.sem.c: I/O redirections and job forking. A touchy issue! 477696Sbrian * Most stuff with builtins is incorrect 536321Samurai */ 677696Sbrian/*- 777696Sbrian * Copyright (c) 1980, 1991 The Regents of the University of California. 877696Sbrian * All rights reserved. 977696Sbrian * 1077696Sbrian * Redistribution and use in source and binary forms, with or without 1177696Sbrian * modification, are permitted provided that the following conditions 1277696Sbrian * are met: 1377696Sbrian * 1. Redistributions of source code must retain the above copyright 1436321Samurai * notice, this list of conditions and the following disclaimer. 1577696Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1677696Sbrian * notice, this list of conditions and the following disclaimer in the 1777696Sbrian * documentation and/or other materials provided with the distribution. 1877696Sbrian * 3. All advertising materials mentioning features or use of this software 1977696Sbrian * must display the following acknowledgement: 2077696Sbrian * This product includes software developed by the University of 2177696Sbrian * California, Berkeley and its contributors. 2277696Sbrian * 4. Neither the name of the University nor the names of its contributors 2377696Sbrian * may be used to endorse or promote products derived from this software 2477696Sbrian * without specific prior written permission. 2577696Sbrian * 2636321Samurai * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2799207Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2836321Samurai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2936321Samurai * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3084195Sdillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3184195Sdillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3284195Sdillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3384195Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3436321Samurai * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3536321Samurai * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3636321Samurai * SUCH DAMAGE. 3736321Samurai */ 3836321Samurai#include "sh.h" 3936321Samurai 4036321SamuraiRCSID("$Id: sh.sem.c,v 3.51 2000/11/11 23:03:38 christos Exp $") 4136321Samurai 4236321Samurai#include "tc.h" 4336321Samurai#include "tw.h" 44145921Sglebius#ifdef WINNT_NATIVE 45145921Sglebius#include "nt.const.h" 46162674Spiso#endif /*WINNT_NATIVE*/ 47162674Spiso 48162674Spiso#ifdef CLOSE_ON_EXEC 49145921Sglebius# ifndef SUNOS4 50162674Spiso# ifndef CLEX_DUPS 51145921Sglebius# define CLEX_DUPS 5299207Sbrian# endif /* CLEX_DUPS */ 53187304Spiso# endif /* !SUNOS4 */ 54145921Sglebius#endif /* CLOSE_ON_EXEC */ 55145921Sglebius 5636321Samurai#if defined(__sparc__) || defined(sparc) 5736321Samurai# if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(linux) 5836321Samurai# include <vfork.h> 5936321Samurai# endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 && !linux */ 6036321Samurai#endif /* __sparc__ || sparc */ 61145921Sglebius 62145921Sglebius#ifdef VFORK 63162674Spisostatic sigret_t vffree __P((int)); 64145921Sglebius#endif 6536321Samuraistatic Char *splicepipe __P((struct command *, Char *)); 66162674Spisostatic void doio __P((struct command *, int *, int *)); 67145921Sglebiusstatic void chkclob __P((char *)); 6836321Samurai 69162674Spiso/* 70162674Spiso * C shell 71162674Spiso */ 72162674Spiso 73162674Spiso/* 74162674Spiso * For SVR4, there are problems with pipelines having the first process as 75162674Spiso * the group leader. The problem occurs when the first process exits before 76162674Spiso * the others have a chance to setpgid(). This is because in SVR4 you can't 77162674Spiso * have a zombie as a group leader. The solution I have used is to reverse 78162674Spiso * the order in which pipelines are started, making the last process the 79162674Spiso * group leader. (Note I am not using 'pipeline' in the generic sense -- I 80162674Spiso * mean processes connected by '|'.) I don't know yet if this causes other 81162674Spiso * problems. 82162674Spiso * 83162674Spiso * All the changes for this are in execute(), and are enclosed in 84162674Spiso * '#ifdef BACKPIPE' 85162674Spiso * 86162674Spiso * David Dawes (dawes@physics.su.oz.au) Oct 1991 87162674Spiso */ 88162674Spiso 89162674Spiso/*VARARGS 1*/ 90162674Spisovoid 91162674Spisoexecute(t, wanttty, pipein, pipeout) 92162674Spiso register struct command *t; 93162674Spiso int wanttty; 94162674Spiso int *pipein, *pipeout; 95162674Spiso{ 96162674Spiso#ifdef VFORK 97162674Spiso extern bool use_fork; /* use fork() instead of vfork()? */ 98162674Spiso#endif 99162674Spiso 100162674Spiso bool forked = 0; 101162674Spiso struct biltins *bifunc; 102162674Spiso int pid = 0; 103162674Spiso int pv[2]; 104162674Spiso#ifdef BSDSIGS 105162674Spiso static sigmask_t csigmask; 106162674Spiso#endif /* BSDSIGS */ 107162674Spiso#ifdef VFORK 108162674Spiso static int onosigchld = 0; 109162674Spiso#endif /* VFORK */ 110162674Spiso static int nosigchld = 0; 111162674Spiso 112162674Spiso (void) &wanttty; 113162674Spiso (void) &forked; 114162674Spiso (void) &bifunc; 115162674Spiso 116162674Spiso if (t == 0) 117162674Spiso return; 118162674Spiso 119162674Spiso#ifdef WINNT_NATIVE 120162674Spiso { 121162674Spiso if ((varval(STRNTslowexec) == STRNULL) && 122162674Spiso !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds && 123162674Spiso (intty || intact) && (t->t_dtyp == NODE_COMMAND) && 124162674Spiso !isbfunc(t)) { 125162674Spiso if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 126162674Spiso (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 127162674Spiso Dfix(t); 128162674Spiso if (nt_try_fast_exec(t) == 0) 129162674Spiso return; 130162674Spiso } 131162674Spiso } 132162674Spiso#endif /* WINNT_NATIVE */ 133162674Spiso 134162674Spiso /* 135162674Spiso * Ed hutchins@sgi.com & Dominic dbg@sgi.com 136162674Spiso * Sat Feb 25 03:13:11 PST 1995 137162674Spiso * try implicit cd if we have a 1 word command 138162674Spiso */ 139162674Spiso if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] && 140162674Spiso t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) { 141162674Spiso Char sCName[MAXPATHLEN]; 142162674Spiso Char *pCN; 143162674Spiso struct stat stbuf; 144162674Spiso char *pathname; 145162674Spiso 146162674Spiso dollar(sCName, t->t_dcom[0]); 147162674Spiso pCN = sCName; 148162674Spiso if (pCN[0] == '~') { 149162674Spiso Char sCPath[MAXPATHLEN]; 150162674Spiso Char *pCP = sCPath; 151162674Spiso 152162674Spiso ++pCN; 153162674Spiso while (*pCN && *pCN != '/') 154162674Spiso *pCP++ = *pCN++; 155162674Spiso *pCP = 0; 156162674Spiso if (sCPath[0]) 157162674Spiso gethdir(sCPath); 158162674Spiso else 159162674Spiso (void) Strcpy(sCPath, varval(STRhome)); 160162674Spiso catn(sCPath, pCN, MAXPATHLEN); 161162674Spiso (void) Strcpy(sCName, sCPath); 162162674Spiso } 163162674Spiso 164162674Spiso pathname = short2str(sCName); 165162674Spiso /* if this is a dir, tack a "cd" on as the first arg */ 166162674Spiso if ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode)) 167162674Spiso#ifdef WINNT_NATIVE 168162674Spiso || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0') 169162674Spiso#endif /* WINNT_NATIVE */ 170162674Spiso ) { 171162674Spiso Char *vCD[2]; 172162674Spiso Char **ot_dcom = t->t_dcom; 173162674Spiso 174162674Spiso vCD[0] = Strsave(STRcd); 175162674Spiso vCD[1] = NULL; 176162674Spiso t->t_dcom = blkspl(vCD, ot_dcom); 177162674Spiso if (implicit_cd > 1) { 178162674Spiso blkpr(t->t_dcom); 179162674Spiso xputchar( '\n' ); 180162674Spiso } 181162674Spiso xfree((ptr_t) ot_dcom); 182162674Spiso } 183162674Spiso } 184162674Spiso 185162674Spiso /* 186162674Spiso * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 187162674Spiso * Don't check for wantty > 0... 188162674Spiso */ 189162674Spiso if (t->t_dflg & F_AMPERSAND) 19036321Samurai wanttty = 0; 191127094Sdes switch (t->t_dtyp) { 192127094Sdes 193127094Sdes case NODE_COMMAND: 194127094Sdes if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 195127094Sdes (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 196127094Sdes if ((t->t_dflg & F_REPEAT) == 0) 19736321Samurai Dfix(t); /* $ " ' \ */ 19836321Samurai if (t->t_dcom[0] == 0) { 199127094Sdes return; 200127094Sdes } 201127094Sdes /*FALLTHROUGH*/ 202127094Sdes 203127094Sdes case NODE_PAREN: 204127094Sdes#ifdef BACKPIPE 205127094Sdes if (t->t_dflg & F_PIPEIN) 206127094Sdes mypipe(pipein); 20736321Samurai#else /* !BACKPIPE */ 20836321Samurai if (t->t_dflg & F_PIPEOUT) 20936321Samurai mypipe(pipeout); 21036321Samurai#endif /* BACKPIPE */ 21136321Samurai /* 21236321Samurai * Must do << early so parent will know where input pointer should be. 21336321Samurai * If noexec then this is all we do. 21436321Samurai */ 215127094Sdes if (t->t_dflg & F_READ) { 216127094Sdes (void) close(0); 217127094Sdes heredoc(t->t_dlef); 218127094Sdes if (noexec) 219127094Sdes (void) close(0); 220127094Sdes } 221127094Sdes 22236321Samurai set(STRstatus, Strsave(STR0), VAR_READWRITE); 22336321Samurai 22436321Samurai /* 22536321Samurai * This mess is the necessary kludge to handle the prefix builtins: 22636321Samurai * nice, nohup, time. These commands can also be used by themselves, 22736321Samurai * and this is not handled here. This will also work when loops are 22836321Samurai * parsed. 22936321Samurai */ 23036321Samurai while (t->t_dtyp == NODE_COMMAND) 231145961Sglebius if (eq(t->t_dcom[0], STRnice)) { 232127094Sdes if (t->t_dcom[1]) { 233127094Sdes if (strchr("+-", t->t_dcom[1][0])) { 234127094Sdes if (t->t_dcom[2]) { 23536321Samurai setname("nice"); 23636321Samurai t->t_nice = 23736321Samurai getn(t->t_dcom[1]); 238127094Sdes lshift(t->t_dcom, 2); 239127094Sdes t->t_dflg |= F_NICE; 240127094Sdes } 241127094Sdes else 242127094Sdes break; 243127094Sdes } 244127094Sdes else { 245127094Sdes t->t_nice = 4; 246127094Sdes lshift(t->t_dcom, 1); 247127094Sdes t->t_dflg |= F_NICE; 248127094Sdes } 249127094Sdes } 250127094Sdes else 25136321Samurai break; 25299207Sbrian } 25336321Samurai else if (eq(t->t_dcom[0], STRnohup)) { 254127094Sdes if (t->t_dcom[1]) { 25544616Sbrian t->t_dflg |= F_NOHUP; 25636321Samurai lshift(t->t_dcom, 1); 25736321Samurai } 25836321Samurai else 259127094Sdes break; 260127094Sdes } 261127094Sdes else if (eq(t->t_dcom[0], STRhup)) { 26236321Samurai if (t->t_dcom[1]) { 26336321Samurai t->t_dflg |= F_HUP; 26436321Samurai lshift(t->t_dcom, 1); 265127094Sdes } 26636321Samurai else 26736321Samurai break; 26841759Sdillon } 26941759Sdillon else if (eq(t->t_dcom[0], STRtime)) { 270127094Sdes if (t->t_dcom[1]) { 27141759Sdillon t->t_dflg |= F_TIME; 272127094Sdes lshift(t->t_dcom, 1); 27336321Samurai } 27441759Sdillon else 275127094Sdes break; 276127094Sdes } 27736321Samurai#ifdef F_VER 278127094Sdes else if (eq(t->t_dcom[0], STRver)) 27936321Samurai if (t->t_dcom[1] && t->t_dcom[2]) { 280127094Sdes setname("ver"); 28136321Samurai t->t_systype = getv(t->t_dcom[1]); 28236321Samurai lshift(t->t_dcom, 2); 28336321Samurai t->t_dflg |= F_VER; 28499207Sbrian } 285127094Sdes else 286127094Sdes break; 28741759Sdillon#endif /* F_VER */ 28841759Sdillon else 28941759Sdillon break; 29041759Sdillon 291145961Sglebius /* is it a command */ 29236321Samurai if (t->t_dtyp == NODE_COMMAND) { 29336321Samurai /* 29436321Samurai * Check if we have a builtin function and remember which one. 295127094Sdes */ 296127094Sdes bifunc = isbfunc(t); 297145961Sglebius if (noexec && bifunc) { 298127094Sdes /* 299127094Sdes * Continue for builtins that are part of the scripting language 30036321Samurai */ 301127094Sdes if (bifunc->bfunct != (bfunc_t)dobreak && 30236321Samurai bifunc->bfunct != (bfunc_t)docontin && 303127094Sdes bifunc->bfunct != (bfunc_t)doelse && 30436321Samurai bifunc->bfunct != (bfunc_t)doend && 305145961Sglebius bifunc->bfunct != (bfunc_t)doforeach&& 30636321Samurai bifunc->bfunct != (bfunc_t)dogoto && 30736321Samurai bifunc->bfunct != (bfunc_t)doif && 30836321Samurai bifunc->bfunct != (bfunc_t)dorepeat && 30936321Samurai bifunc->bfunct != (bfunc_t)doswbrk && 31036321Samurai bifunc->bfunct != (bfunc_t)doswitch && 311145961Sglebius bifunc->bfunct != (bfunc_t)dowhile && 31236321Samurai bifunc->bfunct != (bfunc_t)dozip) 313145928Sglebius break; 31436321Samurai } 315127094Sdes } 31636321Samurai else { /* not a command */ 31736321Samurai bifunc = NULL; 31841759Sdillon if (noexec) 319127094Sdes break; 32041759Sdillon } 321127094Sdes 322127094Sdes /* 32336321Samurai * We fork only if we are timed, or are not the end of a parenthesized 32436321Samurai * list and not a simple builtin function. Simple meaning one that is 32599207Sbrian * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 32636321Samurai * fork in some of these cases. 32736321Samurai */ 32836321Samurai /* 32936321Samurai * Prevent forking cd, pushd, popd, chdir cause this will cause the 33036321Samurai * shell not to change dir! 33136321Samurai */ 33236321Samurai#ifdef BACKPIPE 33336321Samurai /* 33436321Samurai * Can't have NOFORK for the tail of a pipe - because it is not the 33536321Samurai * last command spawned (even if it is at the end of a parenthesised 336162674Spiso * list). 337127094Sdes */ 338127094Sdes if (t->t_dflg & F_PIPEIN) 339127094Sdes t->t_dflg &= ~(F_NOFORK); 340131614Sdes#endif /* BACKPIPE */ 341127094Sdes if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd || 342127094Sdes bifunc->bfunct == (bfunc_t)dopushd || 343127094Sdes bifunc->bfunct == (bfunc_t)dopopd)) 344127094Sdes t->t_dflg &= ~(F_NICE); 345127094Sdes if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && 346127094Sdes (!bifunc || t->t_dflg & 347127094Sdes (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) || 348127094Sdes /* 34999207Sbrian * We have to fork for eval too. 350131614Sdes */ 351131614Sdes (bifunc && (t->t_dflg & F_PIPEIN) != 0 && 352131614Sdes bifunc->bfunct == (bfunc_t)doeval)) { 353127094Sdes#ifdef VFORK 354131699Sdes if (t->t_dtyp == NODE_PAREN || 355127094Sdes t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) 35641759Sdillon#endif /* VFORK */ 357131699Sdes { 358127094Sdes forked++; 359127094Sdes /* 360145961Sglebius * We need to block SIGCHLD here, so that if the process does 361127094Sdes * not die before we can set the process group 36236321Samurai */ 363127094Sdes if (wanttty >= 0 && !nosigchld) { 364127094Sdes#ifdef BSDSIGS 365127094Sdes csigmask = sigblock(sigmask(SIGCHLD)); 366127094Sdes#else /* !BSDSIGS */ 367127094Sdes (void) sighold(SIGCHLD); 368127094Sdes#endif /* BSDSIGS */ 369127094Sdes 370127094Sdes nosigchld = 1; 371127094Sdes } 372127094Sdes 373127094Sdes pid = pfork(t, wanttty); 374127094Sdes if (pid == 0 && nosigchld) { 375127094Sdes#ifdef BSDSIGS 376127094Sdes (void) sigsetmask(csigmask); 377127094Sdes#else /* !BSDSIGS */ 378127094Sdes (void) sigrelse(SIGCHLD); 379127094Sdes#endif /* BSDSIGS */ 38036321Samurai nosigchld = 0; 381127094Sdes } 382127094Sdes else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) 383145961Sglebius backpid = pid; 384127094Sdes } 38536321Samurai 386108533Sschweikh#ifdef VFORK 387127094Sdes else { 388127094Sdes int ochild, osetintr, ohaderr, odidfds; 389127094Sdes int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; 390127094Sdes int oisoutatty, oisdiagatty; 391127094Sdes 39236321Samurai# ifndef CLOSE_ON_EXEC 393127094Sdes int odidcch; 39436321Samurai# endif /* !CLOSE_ON_EXEC */ 39536321Samurai# ifdef BSDSIGS 39636321Samurai sigmask_t omask, ocsigmask; 39736321Samurai# endif /* BSDSIGS */ 39836321Samurai 39974778Sbrian /* 40036321Samurai * Prepare for the vfork by saving everything that the child 401127094Sdes * corrupts before it exec's. Note that in some signal 402127094Sdes * implementations which keep the signal info in user space 403145961Sglebius * (e.g. Sun's) it will also be necessary to save and restore 404127094Sdes * the current sigvec's for the signals the child touches 40536321Samurai * before it exec's. 40636321Samurai */ 407127094Sdes 40836321Samurai /* 409127094Sdes * Sooooo true... If this is a Sun, save the sigvec's. (Skip 41036321Samurai * Gilbrech - 11/22/87) 41136321Samurai */ 41236321Samurai# ifdef SAVESIGVEC 41336321Samurai sigvec_t savesv[NSIGSAVED]; 41436321Samurai sigmask_t savesm; 415127094Sdes 416127094Sdes# endif /* SAVESIGVEC */ 417127094Sdes if (wanttty >= 0 && !nosigchld && !noexec) { 41836321Samurai# ifdef BSDSIGS 419127094Sdes csigmask = sigblock(sigmask(SIGCHLD)); 42041759Sdillon# else /* !BSDSIGS */ 42141759Sdillon (void) sighold(SIGCHLD); 422127094Sdes# endif /* BSDSIGS */ 42341759Sdillon nosigchld = 1; 424127094Sdes } 42536321Samurai# ifdef BSDSIGS 42636321Samurai omask = sigblock(sigmask(SIGCHLD)|sigmask(SIGINT)); 427131614Sdes# else /* !BSDSIGS */ 428131614Sdes (void) sighold(SIGCHLD); 429127094Sdes (void) sighold(SIGINT); 43036321Samurai# endif /* BSDSIGS */ 431127094Sdes ochild = child; 43236321Samurai osetintr = setintr; 43341759Sdillon ohaderr = haderr; 43441759Sdillon odidfds = didfds; 43541759Sdillon# ifndef CLOSE_ON_EXEC 43641759Sdillon odidcch = didcch; 43736321Samurai# endif /* !CLOSE_ON_EXEC */ 438127094Sdes oSHIN = SHIN; 439127094Sdes oSHOUT = SHOUT; 440127094Sdes oSHDIAG = SHDIAG; 441127094Sdes oOLDSTD = OLDSTD; 44236321Samurai otpgrp = tpgrp; 443127094Sdes oisoutatty = isoutatty; 444145961Sglebius oisdiagatty = isdiagatty; 445127094Sdes# ifdef BSDSIGS 44644616Sbrian ocsigmask = csigmask; 44736321Samurai# endif /* BSDSIGS */ 44836321Samurai onosigchld = nosigchld; 44936321Samurai Vsav = Vdp = 0; 45036321Samurai Vexpath = 0; 45136321Samurai Vt = 0; 45236321Samurai# ifdef SAVESIGVEC 453127094Sdes savesm = savesigvec(savesv); 45436321Samurai# endif /* SAVESIGVEC */ 45536321Samurai if (use_fork) 45636321Samurai pid = fork(); 45736321Samurai else 45836321Samurai pid = vfork(); 45936321Samurai 46036321Samurai if (pid < 0) { 46136321Samurai# ifdef BSDSIGS 46236321Samurai# ifdef SAVESIGVEC 46336321Samurai restoresigvec(savesv, savesm); 46436321Samurai# endif /* SAVESIGVEC */ 465127094Sdes (void) sigsetmask(omask); 466127094Sdes# else /* !BSDSIGS */ 467127094Sdes (void) sigrelse(SIGCHLD); 468127094Sdes (void) sigrelse(SIGINT); 469127094Sdes# endif /* BSDSIGS */ 47036321Samurai stderror(ERR_NOPROC); 47136321Samurai } 47236321Samurai forked++; 473127094Sdes if (pid) { /* parent */ 474127094Sdes# ifdef SAVESIGVEC 475127094Sdes restoresigvec(savesv, savesm); 47636321Samurai# endif /* SAVESIGVEC */ 477127094Sdes child = ochild; 47899207Sbrian setintr = osetintr; 479127094Sdes haderr = ohaderr; 48099207Sbrian didfds = odidfds; 481127094Sdes SHIN = oSHIN; 48236321Samurai# ifndef CLOSE_ON_EXEC 483127094Sdes didcch = odidcch; 48436321Samurai# endif /* !CLOSE_ON_EXEC */ 48536321Samurai SHOUT = oSHOUT; 48641759Sdillon SHDIAG = oSHDIAG; 487127094Sdes OLDSTD = oOLDSTD; 48836321Samurai tpgrp = otpgrp; 48936321Samurai isoutatty = oisoutatty; 49036321Samurai isdiagatty = oisdiagatty; 49136321Samurai# ifdef BSDSIGS 492127094Sdes csigmask = ocsigmask; 49336321Samurai# endif /* BSDSIGS */ 49436321Samurai nosigchld = onosigchld; 495145961Sglebius 49636321Samurai xfree((ptr_t) Vsav); 497127094Sdes Vsav = 0; 49836321Samurai xfree((ptr_t) Vdp); 499127094Sdes Vdp = 0; 50041759Sdillon xfree((ptr_t) Vexpath); 50141759Sdillon Vexpath = 0; 50241759Sdillon blkfree((Char **) Vt); 50341759Sdillon Vt = 0; 504145961Sglebius /* this is from pfork() */ 505127094Sdes palloc(pid, t); 50636321Samurai# ifdef BSDSIGS 507127094Sdes (void) sigsetmask(omask); 508127094Sdes# else /* !BSDSIGS */ 509127094Sdes (void) sigrelse(SIGCHLD); 510127094Sdes (void) sigrelse(SIGINT); 51136321Samurai# endif /* BSDSIGS */ 512127094Sdes } 513127094Sdes else { /* child */ 514127094Sdes /* this is from pfork() */ 515127094Sdes int pgrp; 516127094Sdes bool ignint = 0; 517127094Sdes if (nosigchld) { 518127094Sdes# ifdef BSDSIGS 51936321Samurai (void) sigsetmask(csigmask); 52036321Samurai# else /* !BSDSIGS */ 521145961Sglebius (void) sigrelse(SIGCHLD); 52236321Samurai# endif /* BSDSIGS */ 52336321Samurai nosigchld = 0; 52436321Samurai } 525145961Sglebius 526127094Sdes if (setintr) 52736321Samurai ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 52836321Samurai || (gointr && eq(gointr, STRminus)); 52936321Samurai pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 530127094Sdes child++; 531127094Sdes if (setintr) { 53236321Samurai setintr = 0; 53341759Sdillon/* 53441759Sdillon * casts made right for SunOS 4.0 by Douglas C. Schmidt 53541759Sdillon * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU> 536127094Sdes * (thanks! -- PWP) 53736321Samurai * 53836321Samurai * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET> 53936321Samurai * (thanks again) 54036321Samurai */ 541127094Sdes if (ignint) { 542127094Sdes (void) signal(SIGINT, SIG_IGN); 54336321Samurai (void) signal(SIGQUIT, SIG_IGN); 544127094Sdes } 54599207Sbrian else { 546127094Sdes (void) signal(SIGINT, vffree); 54741759Sdillon (void) signal(SIGQUIT, SIG_DFL); 548127094Sdes } 54936321Samurai# ifdef BSDJOBS 550127094Sdes if (wanttty >= 0) { 55136321Samurai (void) signal(SIGTSTP, SIG_DFL); 55236321Samurai (void) signal(SIGTTIN, SIG_DFL); 55341759Sdillon (void) signal(SIGTTOU, SIG_DFL); 554127094Sdes } 55541759Sdillon# endif /* BSDJOBS */ 55636321Samurai 557127094Sdes (void) signal(SIGTERM, parterm); 55836321Samurai } 55936321Samurai else if (tpgrp == -1 && 56036321Samurai (t->t_dflg & F_NOINTERRUPT)) { 56136321Samurai (void) signal(SIGINT, SIG_IGN); 56236321Samurai (void) signal(SIGQUIT, SIG_IGN); 563145961Sglebius } 56436321Samurai 565127094Sdes pgetty(wanttty, pgrp); 56636321Samurai 567127094Sdes if (t->t_dflg & F_NOHUP) 56841759Sdillon (void) signal(SIGHUP, SIG_IGN); 569127094Sdes if (t->t_dflg & F_HUP) 570145961Sglebius (void) signal(SIGHUP, SIG_DFL); 571127094Sdes if (t->t_dflg & F_NICE) { 57236321Samurai int nval = SIGN_EXTEND_CHAR(t->t_nice); 573127094Sdes# ifdef BSDNICE 574127094Sdes (void) setpriority(PRIO_PROCESS, 0, nval); 575127094Sdes# else /* !BSDNICE */ 576127094Sdes (void) nice(nval); 57736321Samurai# endif /* BSDNICE */ 578127094Sdes } 579127094Sdes# ifdef F_VER 580127094Sdes if (t->t_dflg & F_VER) { 581127094Sdes tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53); 582127094Sdes dohash(NULL, NULL); 583127094Sdes } 584127094Sdes# endif /* F_VER */ 58536321Samurai } 58636321Samurai 58736321Samurai } 588127094Sdes#endif /* VFORK */ 58936321Samurai } 59036321Samurai if (pid != 0) { 59141759Sdillon /* 592127094Sdes * It would be better if we could wait for the whole job when we 593127094Sdes * knew the last process had been started. Pwait, in fact, does 59436321Samurai * wait for the whole job anyway, but this test doesn't really 59536321Samurai * express our intentions. 59636321Samurai */ 597127094Sdes#ifdef BACKPIPE 598127094Sdes if (didfds == 0 && t->t_dflg & F_PIPEOUT) { 59936321Samurai (void) close(pipeout[0]); 600127094Sdes (void) close(pipeout[1]); 60199207Sbrian } 602127094Sdes if ((t->t_dflg & F_PIPEIN) != 0) 60341759Sdillon break; 604127094Sdes#else /* !BACKPIPE */ 60536321Samurai if (didfds == 0 && t->t_dflg & F_PIPEIN) { 606127094Sdes (void) close(pipein[0]); 60736321Samurai (void) close(pipein[1]); 60836321Samurai } 609131614Sdes if ((t->t_dflg & F_PIPEOUT) != 0) 610131614Sdes break; 61141759Sdillon#endif /* BACKPIPE */ 612127094Sdes 61341759Sdillon if (nosigchld) { 61436321Samurai#ifdef BSDSIGS 615127094Sdes (void) sigsetmask(csigmask); 61636321Samurai#else /* !BSDSIGS */ 61736321Samurai (void) sigrelse(SIGCHLD); 61836321Samurai#endif /* BSDSIGS */ 61936321Samurai nosigchld = 0; 62036321Samurai } 621127094Sdes if ((t->t_dflg & F_AMPERSAND) == 0) 62241759Sdillon pwait(); 62341759Sdillon break; 62441759Sdillon } 62541759Sdillon 62636321Samurai doio(t, pipein, pipeout); 62736321Samurai#ifdef BACKPIPE 62836321Samurai if (t->t_dflg & F_PIPEIN) { 62941759Sdillon (void) close(pipein[0]); 63041759Sdillon (void) close(pipein[1]); 63136321Samurai } 632127094Sdes#else /* !BACKPIPE */ 63336321Samurai if (t->t_dflg & F_PIPEOUT) { 63436321Samurai (void) close(pipeout[0]); 635127094Sdes (void) close(pipeout[1]); 63699207Sbrian } 637127094Sdes#endif /* BACKPIPE */ 63841759Sdillon /* 639127094Sdes * Perform a builtin function. If we are not forked, arrange for 64036321Samurai * possible stopping 641127094Sdes */ 64236321Samurai if (bifunc) { 64336321Samurai func(t, bifunc); 644131614Sdes if (forked) 645131614Sdes exitstat(); 64641759Sdillon break; 647127094Sdes } 64841759Sdillon if (t->t_dtyp != NODE_PAREN) { 64936321Samurai doexec(t); 650127094Sdes /* NOTREACHED */ 65136321Samurai } 65236321Samurai /* 65336321Samurai * For () commands must put new 0,1,2 in FSH* and recurse 65436321Samurai */ 65536321Samurai OLDSTD = dcopy(0, FOLDSTD); 656127094Sdes SHOUT = dcopy(1, FSHOUT); 65736321Samurai isoutatty = isatty(SHOUT); 658127094Sdes SHDIAG = dcopy(2, FSHDIAG); 659127094Sdes isdiagatty = isatty(SHDIAG); 66041759Sdillon (void) close(SHIN); 661127094Sdes SHIN = -1; 66236321Samurai#ifndef CLOSE_ON_EXEC 66336321Samurai didcch = 0; 66436321Samurai#endif /* !CLOSE_ON_EXEC */ 665127094Sdes didfds = 0; 666127094Sdes wanttty = -1; 66736321Samurai t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 668127094Sdes execute(t->t_dspr, wanttty, NULL, NULL); 66941759Sdillon exitstat(); 670127094Sdes 67141759Sdillon case NODE_PIPE: 672127094Sdes#ifdef BACKPIPE 67336321Samurai t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 674127094Sdes (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 67536321Samurai execute(t->t_dcdr, wanttty, pv, pipeout); 67636321Samurai t->t_dcar->t_dflg |= F_PIPEOUT | 677131614Sdes (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 678131614Sdes execute(t->t_dcar, wanttty, pipein, pv); 67941759Sdillon#else /* !BACKPIPE */ 680127094Sdes t->t_dcar->t_dflg |= F_PIPEOUT | 68141759Sdillon (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 68236321Samurai execute(t->t_dcar, wanttty, pipein, pv); 683127094Sdes t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 68436321Samurai (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 68536321Samurai execute(t->t_dcdr, wanttty, pv, pipeout); 68636321Samurai#endif /* BACKPIPE */ 68736321Samurai break; 688127094Sdes 689127094Sdes case NODE_LIST: 69041759Sdillon if (t->t_dcar) { 691127094Sdes t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 69236321Samurai execute(t->t_dcar, wanttty, NULL, NULL); 69336321Samurai /* 694127094Sdes * In strange case of A&B make a new job after A 69541759Sdillon */ 69699207Sbrian if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 697127094Sdes (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 69841759Sdillon pendjob(); 69999207Sbrian } 700127094Sdes if (t->t_dcdr) { 70136321Samurai t->t_dcdr->t_dflg |= t->t_dflg & 702127094Sdes (F_NOFORK | F_NOINTERRUPT); 70336321Samurai execute(t->t_dcdr, wanttty, NULL, NULL); 704127094Sdes } 70541759Sdillon break; 70641759Sdillon 70741759Sdillon case NODE_OR: 708145961Sglebius case NODE_AND: 709127094Sdes if (t->t_dcar) { 71036321Samurai t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 71136321Samurai execute(t->t_dcar, wanttty, NULL, NULL); 71236321Samurai if ((getn(varval(STRstatus)) == 0) != 713127094Sdes (t->t_dtyp == NODE_AND)) { 714127094Sdes return; 715127094Sdes } 716127094Sdes } 717127094Sdes if (t->t_dcdr) { 718127094Sdes t->t_dcdr->t_dflg |= t->t_dflg & 719127094Sdes (F_NOFORK | F_NOINTERRUPT); 720127094Sdes execute(t->t_dcdr, wanttty, NULL, NULL); 721127094Sdes } 722127094Sdes break; 723127094Sdes 724127094Sdes default: 725127094Sdes break; 726127094Sdes } 727127094Sdes /* 728127094Sdes * Fall through for all breaks from switch 729127094Sdes * 730127094Sdes * If there will be no more executions of this command, flush all file 731127094Sdes * descriptors. Places that turn on the F_REPEAT bit are responsible for 732127094Sdes * doing donefds after the last re-execution 733127094Sdes */ 734127094Sdes if (didfds && !(t->t_dflg & F_REPEAT)) 735127094Sdes donefds(); 736127094Sdes} 737127094Sdes 738127094Sdes#ifdef VFORK 739127094Sdesstatic sigret_t 740127094Sdes/*ARGSUSED*/ 741127094Sdesvffree(snum) 742127094Sdesint snum; 743127094Sdes{ 744127094Sdes register Char **v; 745127094Sdes 746127094Sdes USE(snum); 747127094Sdes if ((v = gargv) != 0) { 748127094Sdes gargv = 0; 749127094Sdes xfree((ptr_t) v); 750145961Sglebius } 751127094Sdes 752127094Sdes if ((v = pargv) != 0) { 753127094Sdes pargv = 0; 754127094Sdes xfree((ptr_t) v); 755145928Sglebius } 75644616Sbrian 757127094Sdes _exit(1); 75836321Samurai#ifndef SIGVOID 75936321Samurai /*NOTREACHED*/ 76036321Samurai return(0); 761127094Sdes#endif /* SIGVOID */ 76236321Samurai} 76336321Samurai#endif /* VFORK */ 764162674Spiso 765127094Sdes/* 766127094Sdes * Expand and glob the words after an i/o redirection. 767127094Sdes * If more than one word is generated, then update the command vector. 768131614Sdes * 769127094Sdes * This is done differently in all the shells: 770127094Sdes * 1. in the bourne shell and ksh globbing is not performed 771127094Sdes * 2. Bash/csh say ambiguous 772127094Sdes * 3. zsh does i/o to/from all the files 77336321Samurai * 4. itcsh concatenates the words. 774127094Sdes * 775127094Sdes * I don't know what is best to do. I think that Ambiguous is better 776127094Sdes * than restructuring the command vector, because the user can get 777127094Sdes * unexpected results. In any case, the command vector restructuring 778127094Sdes * code is present and the user can choose it by setting noambiguous 77936321Samurai */ 780131614Sdesstatic Char * 781131614Sdessplicepipe(t, cp) 782131614Sdes register struct command *t; 78399207Sbrian Char *cp; /* word after < or > */ 784127094Sdes{ 785127094Sdes Char *blk[2]; 786127094Sdes 787127094Sdes if (adrof(STRnoambiguous)) { 78836321Samurai Char **pv; 789127094Sdes 790131699Sdes blk[0] = Dfix1(cp); /* expand $ */ 791127094Sdes blk[1] = NULL; 792131699Sdes 793127094Sdes gflag = 0, tglob(blk); 794127094Sdes if (gflag) { 79536321Samurai pv = globall(blk); 796127094Sdes if (pv == NULL) { 797127094Sdes setname(short2str(blk[0])); 79841759Sdillon xfree((ptr_t) blk[0]); 799145961Sglebius stderror(ERR_NAME | ERR_NOMATCH); 800127094Sdes } 801127094Sdes gargv = NULL; 802127094Sdes if (pv[1] != NULL) { /* we need to fix the command vector */ 803127094Sdes Char **av = blkspl(t->t_dcom, &pv[1]); 804127094Sdes xfree((ptr_t) t->t_dcom); 805127094Sdes t->t_dcom = av; 806127094Sdes } 807127094Sdes xfree((ptr_t) blk[0]); 808127094Sdes blk[0] = pv[0]; 809127094Sdes xfree((ptr_t) pv); 810127094Sdes } 811127094Sdes } 812127094Sdes else { 81336321Samurai Char buf[BUFSIZE]; 81436321Samurai 81536321Samurai (void) Strcpy(buf, blk[1] = Dfix1(cp)); 816127094Sdes xfree((ptr_t) blk[1]); 817127094Sdes blk[0] = globone(buf, G_ERROR); 818127094Sdes } 819127094Sdes return(blk[0]); 820127094Sdes} 821127094Sdes 822127094Sdes/* 82336321Samurai * Perform io redirection. 82436321Samurai * We may or maynot be forked here. 825127094Sdes */ 826127094Sdesstatic void 827127094Sdesdoio(t, pipein, pipeout) 828127094Sdes register struct command *t; 829127094Sdes int *pipein, *pipeout; 830127094Sdes{ 831127094Sdes register int fd; 83236321Samurai register Char *cp; 83336321Samurai register unsigned long flags = t->t_dflg; 834127094Sdes 835127094Sdes if (didfds || (flags & F_REPEAT)) 836127094Sdes return; 837127094Sdes if ((flags & F_READ) == 0) {/* F_READ already done */ 838127094Sdes if (t->t_dlef) { 839127094Sdes char tmp[MAXPATHLEN+1]; 840127094Sdes 84136321Samurai /* 84236321Samurai * so < /dev/std{in,out,err} work 843127094Sdes */ 844127094Sdes (void) dcopy(SHIN, 0); 845127094Sdes (void) dcopy(SHOUT, 1); 846127094Sdes (void) dcopy(SHDIAG, 2); 847127094Sdes cp = splicepipe(t, t->t_dlef); 848127094Sdes (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 849127094Sdes tmp[MAXPATHLEN] = '\0'; 85036321Samurai xfree((ptr_t) cp); 851145961Sglebius if ((fd = open(tmp, O_RDONLY)) < 0) 852127094Sdes stderror(ERR_SYSTEM, tmp, strerror(errno)); 85336321Samurai#ifdef O_LARGEFILE 854127094Sdes /* allow input files larger than 2Gb */ 85536321Samurai (void) fcntl(fd, O_LARGEFILE, 0); 856#endif /* O_LARGEFILE */ 857 (void) dmove(fd, 0); 858 } 859 else if (flags & F_PIPEIN) { 860 (void) close(0); 861 (void) dup(pipein[0]); 862 (void) close(pipein[0]); 863 (void) close(pipein[1]); 864 } 865 else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 866 (void) close(0); 867 (void) open(_PATH_DEVNULL, O_RDONLY); 868 } 869 else { 870 (void) close(0); 871 (void) dup(OLDSTD); 872#if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 873 /* 874 * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved 875 * across dup()s, so we have to UNSET it here or else we get a 876 * command with NO stdin, stdout, or stderr at all (a bad thing 877 * indeed) 878 */ 879 (void) close_on_exec(0, 0); 880#endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 881 } 882 } 883 if (t->t_drit) { 884 char tmp[MAXPATHLEN+1]; 885 886 cp = splicepipe(t, t->t_drit); 887 (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 888 tmp[MAXPATHLEN] = '\0'; 889 xfree((ptr_t) cp); 890 /* 891 * so > /dev/std{out,err} work 892 */ 893 (void) dcopy(SHOUT, 1); 894 (void) dcopy(SHDIAG, 2); 895 if ((flags & F_APPEND) != 0) { 896#ifdef O_APPEND 897 fd = open(tmp, O_WRONLY | O_APPEND); 898#else /* !O_APPEND */ 899 fd = open(tmp, O_WRONLY); 900 (void) lseek(fd, (off_t) 0, L_XTND); 901#endif /* O_APPEND */ 902 } 903 else 904 fd = 0; 905 if ((flags & F_APPEND) == 0 || fd == -1) { 906 if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 907 if (flags & F_APPEND) 908 stderror(ERR_SYSTEM, tmp, strerror(errno)); 909 chkclob(tmp); 910 } 911 if ((fd = creat(tmp, 0666)) < 0) 912 stderror(ERR_SYSTEM, tmp, strerror(errno)); 913#ifdef O_LARGEFILE 914 /* allow input files larger than 2Gb */ 915 (void) fcntl(fd, O_LARGEFILE, 0); 916#endif /* O_LARGEFILE */ 917 } 918 (void) dmove(fd, 1); 919 is1atty = isatty(1); 920 } 921 else if (flags & F_PIPEOUT) { 922 (void) close(1); 923 (void) dup(pipeout[1]); 924 is1atty = 0; 925 } 926 else { 927 (void) close(1); 928 (void) dup(SHOUT); 929 is1atty = isoutatty; 930# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 931 (void) close_on_exec(1, 0); 932# endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 933 } 934 935 (void) close(2); 936 if (flags & F_STDERR) { 937 (void) dup(1); 938 is2atty = is1atty; 939 } 940 else { 941 (void) dup(SHDIAG); 942 is2atty = isdiagatty; 943# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 944 (void) close_on_exec(2, 0); 945# endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 946 } 947 didfds = 1; 948} 949 950void 951mypipe(pv) 952 register int *pv; 953{ 954 955 if (pipe(pv) < 0) 956 goto oops; 957 pv[0] = dmove(pv[0], -1); 958 pv[1] = dmove(pv[1], -1); 959 if (pv[0] >= 0 && pv[1] >= 0) 960 return; 961oops: 962 stderror(ERR_PIPE); 963} 964 965static void 966chkclob(cp) 967 register char *cp; 968{ 969 struct stat stb; 970 971 if (stat(cp, &stb) < 0) 972 return; 973 if (S_ISCHR(stb.st_mode)) 974 return; 975 stderror(ERR_EXISTS, cp); 976} 977