129301572SMark Peek /* $Header: /src/pub/tcsh/sh.sem.c,v 3.56 2002/03/08 17:36:46 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * sh.sem.c: I/O redirections and job forking. A touchy issue! 4c80476e4SDavid E. O'Brien * Most stuff with builtins is incorrect 5c80476e4SDavid E. O'Brien */ 6c80476e4SDavid E. O'Brien /*- 7c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 8c80476e4SDavid E. O'Brien * All rights reserved. 9c80476e4SDavid E. O'Brien * 10c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 11c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 12c80476e4SDavid E. O'Brien * are met: 13c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 15c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 16c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 17c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1829301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 19c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 20c80476e4SDavid E. O'Brien * without specific prior written permission. 21c80476e4SDavid E. O'Brien * 22c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32c80476e4SDavid E. O'Brien * SUCH DAMAGE. 33c80476e4SDavid E. O'Brien */ 34c80476e4SDavid E. O'Brien #include "sh.h" 35c80476e4SDavid E. O'Brien 3629301572SMark Peek RCSID("$Id: sh.sem.c,v 3.56 2002/03/08 17:36:46 christos Exp $") 37c80476e4SDavid E. O'Brien 38c80476e4SDavid E. O'Brien #include "tc.h" 39c80476e4SDavid E. O'Brien #include "tw.h" 403b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 41c80476e4SDavid E. O'Brien #include "nt.const.h" 423b6eaa7bSAndrey A. Chernov #endif /*WINNT_NATIVE*/ 43c80476e4SDavid E. O'Brien 44c80476e4SDavid E. O'Brien #ifdef CLOSE_ON_EXEC 45c80476e4SDavid E. O'Brien # ifndef SUNOS4 46c80476e4SDavid E. O'Brien # ifndef CLEX_DUPS 47c80476e4SDavid E. O'Brien # define CLEX_DUPS 48c80476e4SDavid E. O'Brien # endif /* CLEX_DUPS */ 49c80476e4SDavid E. O'Brien # endif /* !SUNOS4 */ 50c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC */ 51c80476e4SDavid E. O'Brien 52c80476e4SDavid E. O'Brien #if defined(__sparc__) || defined(sparc) 53c80476e4SDavid E. O'Brien # if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(linux) 54c80476e4SDavid E. O'Brien # include <vfork.h> 55c80476e4SDavid E. O'Brien # endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 && !linux */ 56c80476e4SDavid E. O'Brien #endif /* __sparc__ || sparc */ 57c80476e4SDavid E. O'Brien 58c80476e4SDavid E. O'Brien #ifdef VFORK 59c80476e4SDavid E. O'Brien static sigret_t vffree __P((int)); 60c80476e4SDavid E. O'Brien #endif 61c80476e4SDavid E. O'Brien static Char *splicepipe __P((struct command *, Char *)); 62c80476e4SDavid E. O'Brien static void doio __P((struct command *, int *, int *)); 63c80476e4SDavid E. O'Brien static void chkclob __P((char *)); 64c80476e4SDavid E. O'Brien 65c80476e4SDavid E. O'Brien /* 66c80476e4SDavid E. O'Brien * C shell 67c80476e4SDavid E. O'Brien */ 68c80476e4SDavid E. O'Brien 69c80476e4SDavid E. O'Brien /* 70c80476e4SDavid E. O'Brien * For SVR4, there are problems with pipelines having the first process as 71c80476e4SDavid E. O'Brien * the group leader. The problem occurs when the first process exits before 72c80476e4SDavid E. O'Brien * the others have a chance to setpgid(). This is because in SVR4 you can't 73c80476e4SDavid E. O'Brien * have a zombie as a group leader. The solution I have used is to reverse 74c80476e4SDavid E. O'Brien * the order in which pipelines are started, making the last process the 75c80476e4SDavid E. O'Brien * group leader. (Note I am not using 'pipeline' in the generic sense -- I 76c80476e4SDavid E. O'Brien * mean processes connected by '|'.) I don't know yet if this causes other 77c80476e4SDavid E. O'Brien * problems. 78c80476e4SDavid E. O'Brien * 79c80476e4SDavid E. O'Brien * All the changes for this are in execute(), and are enclosed in 80c80476e4SDavid E. O'Brien * '#ifdef BACKPIPE' 81c80476e4SDavid E. O'Brien * 82c80476e4SDavid E. O'Brien * David Dawes (dawes@physics.su.oz.au) Oct 1991 83c80476e4SDavid E. O'Brien */ 84c80476e4SDavid E. O'Brien 85c80476e4SDavid E. O'Brien /*VARARGS 1*/ 86c80476e4SDavid E. O'Brien void 8729301572SMark Peek execute(t, wanttty, pipein, pipeout, do_glob) 88c80476e4SDavid E. O'Brien register struct command *t; 89c80476e4SDavid E. O'Brien int wanttty; 90c80476e4SDavid E. O'Brien int *pipein, *pipeout; 9129301572SMark Peek bool do_glob; 92c80476e4SDavid E. O'Brien { 93c80476e4SDavid E. O'Brien #ifdef VFORK 94c80476e4SDavid E. O'Brien extern bool use_fork; /* use fork() instead of vfork()? */ 95c80476e4SDavid E. O'Brien #endif 96c80476e4SDavid E. O'Brien 97c80476e4SDavid E. O'Brien bool forked = 0; 98c80476e4SDavid E. O'Brien struct biltins *bifunc; 99c80476e4SDavid E. O'Brien int pid = 0; 100c80476e4SDavid E. O'Brien int pv[2]; 101c80476e4SDavid E. O'Brien #ifdef BSDSIGS 102c80476e4SDavid E. O'Brien static sigmask_t csigmask; 103c80476e4SDavid E. O'Brien #endif /* BSDSIGS */ 104c80476e4SDavid E. O'Brien #ifdef VFORK 105c80476e4SDavid E. O'Brien static int onosigchld = 0; 106c80476e4SDavid E. O'Brien #endif /* VFORK */ 107c80476e4SDavid E. O'Brien static int nosigchld = 0; 108c80476e4SDavid E. O'Brien 109c80476e4SDavid E. O'Brien (void) &wanttty; 110c80476e4SDavid E. O'Brien (void) &forked; 111c80476e4SDavid E. O'Brien (void) &bifunc; 112c80476e4SDavid E. O'Brien 113c80476e4SDavid E. O'Brien if (t == 0) 114c80476e4SDavid E. O'Brien return; 115c80476e4SDavid E. O'Brien 1163b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 117c80476e4SDavid E. O'Brien { 118c80476e4SDavid E. O'Brien if ((varval(STRNTslowexec) == STRNULL) && 119c80476e4SDavid E. O'Brien !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds && 120c80476e4SDavid E. O'Brien (intty || intact) && (t->t_dtyp == NODE_COMMAND) && 121c80476e4SDavid E. O'Brien !isbfunc(t)) { 122c80476e4SDavid E. O'Brien if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 123c80476e4SDavid E. O'Brien (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 124c80476e4SDavid E. O'Brien Dfix(t); 125c80476e4SDavid E. O'Brien if (nt_try_fast_exec(t) == 0) 126c80476e4SDavid E. O'Brien return; 127c80476e4SDavid E. O'Brien } 128c80476e4SDavid E. O'Brien } 1293b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 130c80476e4SDavid E. O'Brien 131c80476e4SDavid E. O'Brien /* 132c80476e4SDavid E. O'Brien * Ed hutchins@sgi.com & Dominic dbg@sgi.com 133c80476e4SDavid E. O'Brien * Sat Feb 25 03:13:11 PST 1995 134c80476e4SDavid E. O'Brien * try implicit cd if we have a 1 word command 135c80476e4SDavid E. O'Brien */ 136c80476e4SDavid E. O'Brien if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] && 137c80476e4SDavid E. O'Brien t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) { 138c80476e4SDavid E. O'Brien Char sCName[MAXPATHLEN]; 139c80476e4SDavid E. O'Brien Char *pCN; 140c80476e4SDavid E. O'Brien struct stat stbuf; 141c80476e4SDavid E. O'Brien char *pathname; 142c80476e4SDavid E. O'Brien 143c80476e4SDavid E. O'Brien dollar(sCName, t->t_dcom[0]); 144c80476e4SDavid E. O'Brien pCN = sCName; 145c80476e4SDavid E. O'Brien if (pCN[0] == '~') { 146c80476e4SDavid E. O'Brien Char sCPath[MAXPATHLEN]; 147c80476e4SDavid E. O'Brien Char *pCP = sCPath; 148c80476e4SDavid E. O'Brien 149c80476e4SDavid E. O'Brien ++pCN; 150c80476e4SDavid E. O'Brien while (*pCN && *pCN != '/') 151c80476e4SDavid E. O'Brien *pCP++ = *pCN++; 152c80476e4SDavid E. O'Brien *pCP = 0; 153c80476e4SDavid E. O'Brien if (sCPath[0]) 154c80476e4SDavid E. O'Brien gethdir(sCPath); 155c80476e4SDavid E. O'Brien else 156c80476e4SDavid E. O'Brien (void) Strcpy(sCPath, varval(STRhome)); 157c80476e4SDavid E. O'Brien catn(sCPath, pCN, MAXPATHLEN); 158c80476e4SDavid E. O'Brien (void) Strcpy(sCName, sCPath); 159c80476e4SDavid E. O'Brien } 160c80476e4SDavid E. O'Brien 161c80476e4SDavid E. O'Brien pathname = short2str(sCName); 162c80476e4SDavid E. O'Brien /* if this is a dir, tack a "cd" on as the first arg */ 163c80476e4SDavid E. O'Brien if ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode)) 1643b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 165c80476e4SDavid E. O'Brien || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0') 1663b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 167c80476e4SDavid E. O'Brien ) { 168c80476e4SDavid E. O'Brien Char *vCD[2]; 169c80476e4SDavid E. O'Brien Char **ot_dcom = t->t_dcom; 170c80476e4SDavid E. O'Brien 171c80476e4SDavid E. O'Brien vCD[0] = Strsave(STRcd); 172c80476e4SDavid E. O'Brien vCD[1] = NULL; 173c80476e4SDavid E. O'Brien t->t_dcom = blkspl(vCD, ot_dcom); 174c80476e4SDavid E. O'Brien if (implicit_cd > 1) { 175c80476e4SDavid E. O'Brien blkpr(t->t_dcom); 176c80476e4SDavid E. O'Brien xputchar( '\n' ); 177c80476e4SDavid E. O'Brien } 178c80476e4SDavid E. O'Brien xfree((ptr_t) ot_dcom); 179c80476e4SDavid E. O'Brien } 180c80476e4SDavid E. O'Brien } 181c80476e4SDavid E. O'Brien 182c80476e4SDavid E. O'Brien /* 183c80476e4SDavid E. O'Brien * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 184c80476e4SDavid E. O'Brien * Don't check for wantty > 0... 185c80476e4SDavid E. O'Brien */ 186c80476e4SDavid E. O'Brien if (t->t_dflg & F_AMPERSAND) 187c80476e4SDavid E. O'Brien wanttty = 0; 188c80476e4SDavid E. O'Brien switch (t->t_dtyp) { 189c80476e4SDavid E. O'Brien 190c80476e4SDavid E. O'Brien case NODE_COMMAND: 191c80476e4SDavid E. O'Brien if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 192c80476e4SDavid E. O'Brien (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 193c80476e4SDavid E. O'Brien if ((t->t_dflg & F_REPEAT) == 0) 194c80476e4SDavid E. O'Brien Dfix(t); /* $ " ' \ */ 195c80476e4SDavid E. O'Brien if (t->t_dcom[0] == 0) { 196c80476e4SDavid E. O'Brien return; 197c80476e4SDavid E. O'Brien } 198c80476e4SDavid E. O'Brien /*FALLTHROUGH*/ 199c80476e4SDavid E. O'Brien 200c80476e4SDavid E. O'Brien case NODE_PAREN: 201c80476e4SDavid E. O'Brien #ifdef BACKPIPE 202c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEIN) 203c80476e4SDavid E. O'Brien mypipe(pipein); 204c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 205c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEOUT) 206c80476e4SDavid E. O'Brien mypipe(pipeout); 207c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 208c80476e4SDavid E. O'Brien /* 209c80476e4SDavid E. O'Brien * Must do << early so parent will know where input pointer should be. 210c80476e4SDavid E. O'Brien * If noexec then this is all we do. 211c80476e4SDavid E. O'Brien */ 212c80476e4SDavid E. O'Brien if (t->t_dflg & F_READ) { 213c80476e4SDavid E. O'Brien (void) close(0); 214c80476e4SDavid E. O'Brien heredoc(t->t_dlef); 215c80476e4SDavid E. O'Brien if (noexec) 216c80476e4SDavid E. O'Brien (void) close(0); 217c80476e4SDavid E. O'Brien } 218c80476e4SDavid E. O'Brien 219c80476e4SDavid E. O'Brien set(STRstatus, Strsave(STR0), VAR_READWRITE); 220c80476e4SDavid E. O'Brien 221c80476e4SDavid E. O'Brien /* 222c80476e4SDavid E. O'Brien * This mess is the necessary kludge to handle the prefix builtins: 223c80476e4SDavid E. O'Brien * nice, nohup, time. These commands can also be used by themselves, 224c80476e4SDavid E. O'Brien * and this is not handled here. This will also work when loops are 225c80476e4SDavid E. O'Brien * parsed. 226c80476e4SDavid E. O'Brien */ 227c80476e4SDavid E. O'Brien while (t->t_dtyp == NODE_COMMAND) 228c80476e4SDavid E. O'Brien if (eq(t->t_dcom[0], STRnice)) { 229c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 230c80476e4SDavid E. O'Brien if (strchr("+-", t->t_dcom[1][0])) { 231c80476e4SDavid E. O'Brien if (t->t_dcom[2]) { 232c80476e4SDavid E. O'Brien setname("nice"); 233c80476e4SDavid E. O'Brien t->t_nice = 234c80476e4SDavid E. O'Brien getn(t->t_dcom[1]); 235c80476e4SDavid E. O'Brien lshift(t->t_dcom, 2); 236c80476e4SDavid E. O'Brien t->t_dflg |= F_NICE; 237c80476e4SDavid E. O'Brien } 238c80476e4SDavid E. O'Brien else 239c80476e4SDavid E. O'Brien break; 240c80476e4SDavid E. O'Brien } 241c80476e4SDavid E. O'Brien else { 242c80476e4SDavid E. O'Brien t->t_nice = 4; 243c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 244c80476e4SDavid E. O'Brien t->t_dflg |= F_NICE; 245c80476e4SDavid E. O'Brien } 246c80476e4SDavid E. O'Brien } 247c80476e4SDavid E. O'Brien else 248c80476e4SDavid E. O'Brien break; 249c80476e4SDavid E. O'Brien } 250c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRnohup)) { 251c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 252c80476e4SDavid E. O'Brien t->t_dflg |= F_NOHUP; 253c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 254c80476e4SDavid E. O'Brien } 255c80476e4SDavid E. O'Brien else 256c80476e4SDavid E. O'Brien break; 257c80476e4SDavid E. O'Brien } 258c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRhup)) { 259c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 260c80476e4SDavid E. O'Brien t->t_dflg |= F_HUP; 261c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 262c80476e4SDavid E. O'Brien } 263c80476e4SDavid E. O'Brien else 264c80476e4SDavid E. O'Brien break; 265c80476e4SDavid E. O'Brien } 266c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRtime)) { 267c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 268c80476e4SDavid E. O'Brien t->t_dflg |= F_TIME; 269c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 270c80476e4SDavid E. O'Brien } 271c80476e4SDavid E. O'Brien else 272c80476e4SDavid E. O'Brien break; 273c80476e4SDavid E. O'Brien } 274c80476e4SDavid E. O'Brien #ifdef F_VER 275c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRver)) 276c80476e4SDavid E. O'Brien if (t->t_dcom[1] && t->t_dcom[2]) { 277c80476e4SDavid E. O'Brien setname("ver"); 278c80476e4SDavid E. O'Brien t->t_systype = getv(t->t_dcom[1]); 279c80476e4SDavid E. O'Brien lshift(t->t_dcom, 2); 280c80476e4SDavid E. O'Brien t->t_dflg |= F_VER; 281c80476e4SDavid E. O'Brien } 282c80476e4SDavid E. O'Brien else 283c80476e4SDavid E. O'Brien break; 284c80476e4SDavid E. O'Brien #endif /* F_VER */ 285c80476e4SDavid E. O'Brien else 286c80476e4SDavid E. O'Brien break; 287c80476e4SDavid E. O'Brien 288c80476e4SDavid E. O'Brien /* is it a command */ 289c80476e4SDavid E. O'Brien if (t->t_dtyp == NODE_COMMAND) { 290c80476e4SDavid E. O'Brien /* 291c80476e4SDavid E. O'Brien * Check if we have a builtin function and remember which one. 292c80476e4SDavid E. O'Brien */ 293c80476e4SDavid E. O'Brien bifunc = isbfunc(t); 294c80476e4SDavid E. O'Brien if (noexec && bifunc) { 295c80476e4SDavid E. O'Brien /* 296c80476e4SDavid E. O'Brien * Continue for builtins that are part of the scripting language 297c80476e4SDavid E. O'Brien */ 298c80476e4SDavid E. O'Brien if (bifunc->bfunct != (bfunc_t)dobreak && 299c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)docontin && 300c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doelse && 301c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doend && 302c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doforeach&& 303c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dogoto && 304c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doif && 305c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dorepeat && 306c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doswbrk && 307c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doswitch && 308c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dowhile && 309c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dozip) 310c80476e4SDavid E. O'Brien break; 311c80476e4SDavid E. O'Brien } 312c80476e4SDavid E. O'Brien } 313c80476e4SDavid E. O'Brien else { /* not a command */ 314c80476e4SDavid E. O'Brien bifunc = NULL; 315c80476e4SDavid E. O'Brien if (noexec) 316c80476e4SDavid E. O'Brien break; 317c80476e4SDavid E. O'Brien } 318c80476e4SDavid E. O'Brien 319c80476e4SDavid E. O'Brien /* 3206767bd61SMark Peek * GrP Executing a command - run jobcmd hook 3216767bd61SMark Peek * Don't run for builtins 3226767bd61SMark Peek * Don't run if we're not in a tty 3236767bd61SMark Peek * Don't run if we're not really executing 3246767bd61SMark Peek */ 3256767bd61SMark Peek if (t->t_dtyp == NODE_COMMAND && !bifunc && !noexec && intty) { 3266767bd61SMark Peek Char *cmd = unparse(t); 3276767bd61SMark Peek job_cmd(cmd); 3286767bd61SMark Peek xfree(cmd); 3296767bd61SMark Peek } 3306767bd61SMark Peek 3316767bd61SMark Peek /* 332c80476e4SDavid E. O'Brien * We fork only if we are timed, or are not the end of a parenthesized 333c80476e4SDavid E. O'Brien * list and not a simple builtin function. Simple meaning one that is 334c80476e4SDavid E. O'Brien * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 335c80476e4SDavid E. O'Brien * fork in some of these cases. 336c80476e4SDavid E. O'Brien */ 337c80476e4SDavid E. O'Brien /* 338c80476e4SDavid E. O'Brien * Prevent forking cd, pushd, popd, chdir cause this will cause the 339c80476e4SDavid E. O'Brien * shell not to change dir! 340c80476e4SDavid E. O'Brien */ 341c80476e4SDavid E. O'Brien #ifdef BACKPIPE 342c80476e4SDavid E. O'Brien /* 343c80476e4SDavid E. O'Brien * Can't have NOFORK for the tail of a pipe - because it is not the 344c80476e4SDavid E. O'Brien * last command spawned (even if it is at the end of a parenthesised 345c80476e4SDavid E. O'Brien * list). 346c80476e4SDavid E. O'Brien */ 347c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEIN) 348c80476e4SDavid E. O'Brien t->t_dflg &= ~(F_NOFORK); 349c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 350c80476e4SDavid E. O'Brien if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd || 351c80476e4SDavid E. O'Brien bifunc->bfunct == (bfunc_t)dopushd || 352c80476e4SDavid E. O'Brien bifunc->bfunct == (bfunc_t)dopopd)) 353c80476e4SDavid E. O'Brien t->t_dflg &= ~(F_NICE); 354c80476e4SDavid E. O'Brien if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && 355c80476e4SDavid E. O'Brien (!bifunc || t->t_dflg & 356c80476e4SDavid E. O'Brien (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) || 357c80476e4SDavid E. O'Brien /* 358c80476e4SDavid E. O'Brien * We have to fork for eval too. 359c80476e4SDavid E. O'Brien */ 360c80476e4SDavid E. O'Brien (bifunc && (t->t_dflg & F_PIPEIN) != 0 && 3613b6eaa7bSAndrey A. Chernov bifunc->bfunct == (bfunc_t)doeval)) { 362c80476e4SDavid E. O'Brien #ifdef VFORK 363c80476e4SDavid E. O'Brien if (t->t_dtyp == NODE_PAREN || 364c80476e4SDavid E. O'Brien t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) 365c80476e4SDavid E. O'Brien #endif /* VFORK */ 366c80476e4SDavid E. O'Brien { 367c80476e4SDavid E. O'Brien forked++; 368c80476e4SDavid E. O'Brien /* 369c80476e4SDavid E. O'Brien * We need to block SIGCHLD here, so that if the process does 370c80476e4SDavid E. O'Brien * not die before we can set the process group 371c80476e4SDavid E. O'Brien */ 372c80476e4SDavid E. O'Brien if (wanttty >= 0 && !nosigchld) { 373c80476e4SDavid E. O'Brien #ifdef BSDSIGS 374c80476e4SDavid E. O'Brien csigmask = sigblock(sigmask(SIGCHLD)); 375c80476e4SDavid E. O'Brien #else /* !BSDSIGS */ 376c80476e4SDavid E. O'Brien (void) sighold(SIGCHLD); 377c80476e4SDavid E. O'Brien #endif /* BSDSIGS */ 378c80476e4SDavid E. O'Brien 379c80476e4SDavid E. O'Brien nosigchld = 1; 380c80476e4SDavid E. O'Brien } 381c80476e4SDavid E. O'Brien 382c80476e4SDavid E. O'Brien pid = pfork(t, wanttty); 383c80476e4SDavid E. O'Brien if (pid == 0 && nosigchld) { 384c80476e4SDavid E. O'Brien #ifdef BSDSIGS 385c80476e4SDavid E. O'Brien (void) sigsetmask(csigmask); 386c80476e4SDavid E. O'Brien #else /* !BSDSIGS */ 387c80476e4SDavid E. O'Brien (void) sigrelse(SIGCHLD); 388c80476e4SDavid E. O'Brien #endif /* BSDSIGS */ 389c80476e4SDavid E. O'Brien nosigchld = 0; 390c80476e4SDavid E. O'Brien } 391c80476e4SDavid E. O'Brien else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) 392c80476e4SDavid E. O'Brien backpid = pid; 393c80476e4SDavid E. O'Brien } 394c80476e4SDavid E. O'Brien 395c80476e4SDavid E. O'Brien #ifdef VFORK 396c80476e4SDavid E. O'Brien else { 397c80476e4SDavid E. O'Brien int ochild, osetintr, ohaderr, odidfds; 398c80476e4SDavid E. O'Brien int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; 399c80476e4SDavid E. O'Brien int oisoutatty, oisdiagatty; 400c80476e4SDavid E. O'Brien 401c80476e4SDavid E. O'Brien # ifndef CLOSE_ON_EXEC 402c80476e4SDavid E. O'Brien int odidcch; 403c80476e4SDavid E. O'Brien # endif /* !CLOSE_ON_EXEC */ 404c80476e4SDavid E. O'Brien # ifdef BSDSIGS 405c80476e4SDavid E. O'Brien sigmask_t omask, ocsigmask; 406c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 407c80476e4SDavid E. O'Brien 408c80476e4SDavid E. O'Brien /* 409c80476e4SDavid E. O'Brien * Prepare for the vfork by saving everything that the child 410c80476e4SDavid E. O'Brien * corrupts before it exec's. Note that in some signal 411c80476e4SDavid E. O'Brien * implementations which keep the signal info in user space 412c80476e4SDavid E. O'Brien * (e.g. Sun's) it will also be necessary to save and restore 413c80476e4SDavid E. O'Brien * the current sigvec's for the signals the child touches 414c80476e4SDavid E. O'Brien * before it exec's. 415c80476e4SDavid E. O'Brien */ 416c80476e4SDavid E. O'Brien 417c80476e4SDavid E. O'Brien /* 418c80476e4SDavid E. O'Brien * Sooooo true... If this is a Sun, save the sigvec's. (Skip 419c80476e4SDavid E. O'Brien * Gilbrech - 11/22/87) 420c80476e4SDavid E. O'Brien */ 421c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 422c80476e4SDavid E. O'Brien sigvec_t savesv[NSIGSAVED]; 423c80476e4SDavid E. O'Brien sigmask_t savesm; 424c80476e4SDavid E. O'Brien 425c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 426c80476e4SDavid E. O'Brien if (wanttty >= 0 && !nosigchld && !noexec) { 427c80476e4SDavid E. O'Brien # ifdef BSDSIGS 428c80476e4SDavid E. O'Brien csigmask = sigblock(sigmask(SIGCHLD)); 429c80476e4SDavid E. O'Brien # else /* !BSDSIGS */ 430c80476e4SDavid E. O'Brien (void) sighold(SIGCHLD); 431c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 432c80476e4SDavid E. O'Brien nosigchld = 1; 433c80476e4SDavid E. O'Brien } 434c80476e4SDavid E. O'Brien # ifdef BSDSIGS 435c80476e4SDavid E. O'Brien omask = sigblock(sigmask(SIGCHLD)|sigmask(SIGINT)); 436c80476e4SDavid E. O'Brien # else /* !BSDSIGS */ 437c80476e4SDavid E. O'Brien (void) sighold(SIGCHLD); 438c80476e4SDavid E. O'Brien (void) sighold(SIGINT); 439c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 440c80476e4SDavid E. O'Brien ochild = child; 441c80476e4SDavid E. O'Brien osetintr = setintr; 442c80476e4SDavid E. O'Brien ohaderr = haderr; 443c80476e4SDavid E. O'Brien odidfds = didfds; 444c80476e4SDavid E. O'Brien # ifndef CLOSE_ON_EXEC 445c80476e4SDavid E. O'Brien odidcch = didcch; 446c80476e4SDavid E. O'Brien # endif /* !CLOSE_ON_EXEC */ 447c80476e4SDavid E. O'Brien oSHIN = SHIN; 448c80476e4SDavid E. O'Brien oSHOUT = SHOUT; 449c80476e4SDavid E. O'Brien oSHDIAG = SHDIAG; 450c80476e4SDavid E. O'Brien oOLDSTD = OLDSTD; 451c80476e4SDavid E. O'Brien otpgrp = tpgrp; 452c80476e4SDavid E. O'Brien oisoutatty = isoutatty; 453c80476e4SDavid E. O'Brien oisdiagatty = isdiagatty; 454c80476e4SDavid E. O'Brien # ifdef BSDSIGS 455c80476e4SDavid E. O'Brien ocsigmask = csigmask; 456c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 457c80476e4SDavid E. O'Brien onosigchld = nosigchld; 458c80476e4SDavid E. O'Brien Vsav = Vdp = 0; 459c80476e4SDavid E. O'Brien Vexpath = 0; 460c80476e4SDavid E. O'Brien Vt = 0; 461c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 462c80476e4SDavid E. O'Brien savesm = savesigvec(savesv); 463c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 464c80476e4SDavid E. O'Brien if (use_fork) 465c80476e4SDavid E. O'Brien pid = fork(); 466c80476e4SDavid E. O'Brien else 467c80476e4SDavid E. O'Brien pid = vfork(); 468c80476e4SDavid E. O'Brien 469c80476e4SDavid E. O'Brien if (pid < 0) { 470c80476e4SDavid E. O'Brien # ifdef BSDSIGS 471c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 472c80476e4SDavid E. O'Brien restoresigvec(savesv, savesm); 473c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 474c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 475c80476e4SDavid E. O'Brien # else /* !BSDSIGS */ 476c80476e4SDavid E. O'Brien (void) sigrelse(SIGCHLD); 477c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 478c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 479c80476e4SDavid E. O'Brien stderror(ERR_NOPROC); 480c80476e4SDavid E. O'Brien } 481c80476e4SDavid E. O'Brien forked++; 482c80476e4SDavid E. O'Brien if (pid) { /* parent */ 483c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 484c80476e4SDavid E. O'Brien restoresigvec(savesv, savesm); 485c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 486c80476e4SDavid E. O'Brien child = ochild; 487c80476e4SDavid E. O'Brien setintr = osetintr; 488c80476e4SDavid E. O'Brien haderr = ohaderr; 489c80476e4SDavid E. O'Brien didfds = odidfds; 490c80476e4SDavid E. O'Brien SHIN = oSHIN; 491c80476e4SDavid E. O'Brien # ifndef CLOSE_ON_EXEC 492c80476e4SDavid E. O'Brien didcch = odidcch; 493c80476e4SDavid E. O'Brien # endif /* !CLOSE_ON_EXEC */ 494c80476e4SDavid E. O'Brien SHOUT = oSHOUT; 495c80476e4SDavid E. O'Brien SHDIAG = oSHDIAG; 496c80476e4SDavid E. O'Brien OLDSTD = oOLDSTD; 497c80476e4SDavid E. O'Brien tpgrp = otpgrp; 498c80476e4SDavid E. O'Brien isoutatty = oisoutatty; 499c80476e4SDavid E. O'Brien isdiagatty = oisdiagatty; 500c80476e4SDavid E. O'Brien # ifdef BSDSIGS 501c80476e4SDavid E. O'Brien csigmask = ocsigmask; 502c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 503c80476e4SDavid E. O'Brien nosigchld = onosigchld; 504c80476e4SDavid E. O'Brien 505c80476e4SDavid E. O'Brien xfree((ptr_t) Vsav); 506c80476e4SDavid E. O'Brien Vsav = 0; 507c80476e4SDavid E. O'Brien xfree((ptr_t) Vdp); 508c80476e4SDavid E. O'Brien Vdp = 0; 509c80476e4SDavid E. O'Brien xfree((ptr_t) Vexpath); 510c80476e4SDavid E. O'Brien Vexpath = 0; 511c80476e4SDavid E. O'Brien blkfree((Char **) Vt); 512c80476e4SDavid E. O'Brien Vt = 0; 513c80476e4SDavid E. O'Brien /* this is from pfork() */ 514c80476e4SDavid E. O'Brien palloc(pid, t); 515c80476e4SDavid E. O'Brien # ifdef BSDSIGS 516c80476e4SDavid E. O'Brien (void) sigsetmask(omask); 517c80476e4SDavid E. O'Brien # else /* !BSDSIGS */ 518c80476e4SDavid E. O'Brien (void) sigrelse(SIGCHLD); 519c80476e4SDavid E. O'Brien (void) sigrelse(SIGINT); 520c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 521c80476e4SDavid E. O'Brien } 522c80476e4SDavid E. O'Brien else { /* child */ 523c80476e4SDavid E. O'Brien /* this is from pfork() */ 524c80476e4SDavid E. O'Brien int pgrp; 525c80476e4SDavid E. O'Brien bool ignint = 0; 526c80476e4SDavid E. O'Brien if (nosigchld) { 527c80476e4SDavid E. O'Brien # ifdef BSDSIGS 528c80476e4SDavid E. O'Brien (void) sigsetmask(csigmask); 529c80476e4SDavid E. O'Brien # else /* !BSDSIGS */ 530c80476e4SDavid E. O'Brien (void) sigrelse(SIGCHLD); 531c80476e4SDavid E. O'Brien # endif /* BSDSIGS */ 532c80476e4SDavid E. O'Brien nosigchld = 0; 533c80476e4SDavid E. O'Brien } 534c80476e4SDavid E. O'Brien 535c80476e4SDavid E. O'Brien if (setintr) 536c80476e4SDavid E. O'Brien ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 537c80476e4SDavid E. O'Brien || (gointr && eq(gointr, STRminus)); 538c80476e4SDavid E. O'Brien pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 539c80476e4SDavid E. O'Brien child++; 540c80476e4SDavid E. O'Brien if (setintr) { 541c80476e4SDavid E. O'Brien setintr = 0; 542c80476e4SDavid E. O'Brien /* 543c80476e4SDavid E. O'Brien * casts made right for SunOS 4.0 by Douglas C. Schmidt 544c80476e4SDavid E. O'Brien * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU> 545c80476e4SDavid E. O'Brien * (thanks! -- PWP) 546c80476e4SDavid E. O'Brien * 547c80476e4SDavid E. O'Brien * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET> 548c80476e4SDavid E. O'Brien * (thanks again) 549c80476e4SDavid E. O'Brien */ 550c80476e4SDavid E. O'Brien if (ignint) { 551c80476e4SDavid E. O'Brien (void) signal(SIGINT, SIG_IGN); 552c80476e4SDavid E. O'Brien (void) signal(SIGQUIT, SIG_IGN); 553c80476e4SDavid E. O'Brien } 554c80476e4SDavid E. O'Brien else { 555c80476e4SDavid E. O'Brien (void) signal(SIGINT, vffree); 556c80476e4SDavid E. O'Brien (void) signal(SIGQUIT, SIG_DFL); 557c80476e4SDavid E. O'Brien } 558c80476e4SDavid E. O'Brien # ifdef BSDJOBS 559c80476e4SDavid E. O'Brien if (wanttty >= 0) { 560c80476e4SDavid E. O'Brien (void) signal(SIGTSTP, SIG_DFL); 561c80476e4SDavid E. O'Brien (void) signal(SIGTTIN, SIG_DFL); 562c80476e4SDavid E. O'Brien (void) signal(SIGTTOU, SIG_DFL); 563c80476e4SDavid E. O'Brien } 564c80476e4SDavid E. O'Brien # endif /* BSDJOBS */ 565c80476e4SDavid E. O'Brien 566c80476e4SDavid E. O'Brien (void) signal(SIGTERM, parterm); 567c80476e4SDavid E. O'Brien } 568c80476e4SDavid E. O'Brien else if (tpgrp == -1 && 569c80476e4SDavid E. O'Brien (t->t_dflg & F_NOINTERRUPT)) { 570c80476e4SDavid E. O'Brien (void) signal(SIGINT, SIG_IGN); 571c80476e4SDavid E. O'Brien (void) signal(SIGQUIT, SIG_IGN); 572c80476e4SDavid E. O'Brien } 573c80476e4SDavid E. O'Brien 574c80476e4SDavid E. O'Brien pgetty(wanttty, pgrp); 575c80476e4SDavid E. O'Brien 576c80476e4SDavid E. O'Brien if (t->t_dflg & F_NOHUP) 577c80476e4SDavid E. O'Brien (void) signal(SIGHUP, SIG_IGN); 578c80476e4SDavid E. O'Brien if (t->t_dflg & F_HUP) 579c80476e4SDavid E. O'Brien (void) signal(SIGHUP, SIG_DFL); 580c80476e4SDavid E. O'Brien if (t->t_dflg & F_NICE) { 581c80476e4SDavid E. O'Brien int nval = SIGN_EXTEND_CHAR(t->t_nice); 582c80476e4SDavid E. O'Brien # ifdef BSDNICE 5836767bd61SMark Peek if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno) 5846767bd61SMark Peek stderror(ERR_SYSTEM, "setpriority", 5856767bd61SMark Peek strerror(errno)); 586c80476e4SDavid E. O'Brien # else /* !BSDNICE */ 587c80476e4SDavid E. O'Brien (void) nice(nval); 588c80476e4SDavid E. O'Brien # endif /* BSDNICE */ 589c80476e4SDavid E. O'Brien } 590c80476e4SDavid E. O'Brien # ifdef F_VER 591c80476e4SDavid E. O'Brien if (t->t_dflg & F_VER) { 592c80476e4SDavid E. O'Brien tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53); 593c80476e4SDavid E. O'Brien dohash(NULL, NULL); 594c80476e4SDavid E. O'Brien } 595c80476e4SDavid E. O'Brien # endif /* F_VER */ 596c80476e4SDavid E. O'Brien } 597c80476e4SDavid E. O'Brien 598c80476e4SDavid E. O'Brien } 599c80476e4SDavid E. O'Brien #endif /* VFORK */ 6003b6eaa7bSAndrey A. Chernov } 601c80476e4SDavid E. O'Brien if (pid != 0) { 602c80476e4SDavid E. O'Brien /* 603c80476e4SDavid E. O'Brien * It would be better if we could wait for the whole job when we 604c80476e4SDavid E. O'Brien * knew the last process had been started. Pwait, in fact, does 605c80476e4SDavid E. O'Brien * wait for the whole job anyway, but this test doesn't really 606c80476e4SDavid E. O'Brien * express our intentions. 607c80476e4SDavid E. O'Brien */ 608c80476e4SDavid E. O'Brien #ifdef BACKPIPE 609c80476e4SDavid E. O'Brien if (didfds == 0 && t->t_dflg & F_PIPEOUT) { 610c80476e4SDavid E. O'Brien (void) close(pipeout[0]); 611c80476e4SDavid E. O'Brien (void) close(pipeout[1]); 612c80476e4SDavid E. O'Brien } 613c80476e4SDavid E. O'Brien if ((t->t_dflg & F_PIPEIN) != 0) 614c80476e4SDavid E. O'Brien break; 615c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 616c80476e4SDavid E. O'Brien if (didfds == 0 && t->t_dflg & F_PIPEIN) { 617c80476e4SDavid E. O'Brien (void) close(pipein[0]); 618c80476e4SDavid E. O'Brien (void) close(pipein[1]); 619c80476e4SDavid E. O'Brien } 620c80476e4SDavid E. O'Brien if ((t->t_dflg & F_PIPEOUT) != 0) 621c80476e4SDavid E. O'Brien break; 622c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 623c80476e4SDavid E. O'Brien 624c80476e4SDavid E. O'Brien if (nosigchld) { 625c80476e4SDavid E. O'Brien #ifdef BSDSIGS 626c80476e4SDavid E. O'Brien (void) sigsetmask(csigmask); 627c80476e4SDavid E. O'Brien #else /* !BSDSIGS */ 628c80476e4SDavid E. O'Brien (void) sigrelse(SIGCHLD); 629c80476e4SDavid E. O'Brien #endif /* BSDSIGS */ 630c80476e4SDavid E. O'Brien nosigchld = 0; 631c80476e4SDavid E. O'Brien } 632c80476e4SDavid E. O'Brien if ((t->t_dflg & F_AMPERSAND) == 0) 633c80476e4SDavid E. O'Brien pwait(); 634c80476e4SDavid E. O'Brien break; 635c80476e4SDavid E. O'Brien } 636c80476e4SDavid E. O'Brien 637c80476e4SDavid E. O'Brien doio(t, pipein, pipeout); 638c80476e4SDavid E. O'Brien #ifdef BACKPIPE 639c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEIN) { 640c80476e4SDavid E. O'Brien (void) close(pipein[0]); 641c80476e4SDavid E. O'Brien (void) close(pipein[1]); 642c80476e4SDavid E. O'Brien } 643c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 644c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEOUT) { 645c80476e4SDavid E. O'Brien (void) close(pipeout[0]); 646c80476e4SDavid E. O'Brien (void) close(pipeout[1]); 647c80476e4SDavid E. O'Brien } 648c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 649c80476e4SDavid E. O'Brien /* 650c80476e4SDavid E. O'Brien * Perform a builtin function. If we are not forked, arrange for 651c80476e4SDavid E. O'Brien * possible stopping 652c80476e4SDavid E. O'Brien */ 653c80476e4SDavid E. O'Brien if (bifunc) { 654c80476e4SDavid E. O'Brien func(t, bifunc); 655c80476e4SDavid E. O'Brien if (forked) 656c80476e4SDavid E. O'Brien exitstat(); 657c80476e4SDavid E. O'Brien break; 658c80476e4SDavid E. O'Brien } 659c80476e4SDavid E. O'Brien if (t->t_dtyp != NODE_PAREN) { 66029301572SMark Peek doexec(t, do_glob); 661c80476e4SDavid E. O'Brien /* NOTREACHED */ 662c80476e4SDavid E. O'Brien } 663c80476e4SDavid E. O'Brien /* 664c80476e4SDavid E. O'Brien * For () commands must put new 0,1,2 in FSH* and recurse 665c80476e4SDavid E. O'Brien */ 666c80476e4SDavid E. O'Brien OLDSTD = dcopy(0, FOLDSTD); 667c80476e4SDavid E. O'Brien SHOUT = dcopy(1, FSHOUT); 668c80476e4SDavid E. O'Brien isoutatty = isatty(SHOUT); 669c80476e4SDavid E. O'Brien SHDIAG = dcopy(2, FSHDIAG); 670c80476e4SDavid E. O'Brien isdiagatty = isatty(SHDIAG); 671c80476e4SDavid E. O'Brien (void) close(SHIN); 672c80476e4SDavid E. O'Brien SHIN = -1; 673c80476e4SDavid E. O'Brien #ifndef CLOSE_ON_EXEC 674c80476e4SDavid E. O'Brien didcch = 0; 675c80476e4SDavid E. O'Brien #endif /* !CLOSE_ON_EXEC */ 676c80476e4SDavid E. O'Brien didfds = 0; 677c80476e4SDavid E. O'Brien wanttty = -1; 678c80476e4SDavid E. O'Brien t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 67929301572SMark Peek execute(t->t_dspr, wanttty, NULL, NULL, do_glob); 680c80476e4SDavid E. O'Brien exitstat(); 681c80476e4SDavid E. O'Brien 682c80476e4SDavid E. O'Brien case NODE_PIPE: 683c80476e4SDavid E. O'Brien #ifdef BACKPIPE 684c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 685c80476e4SDavid E. O'Brien (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 68629301572SMark Peek execute(t->t_dcdr, wanttty, pv, pipeout, do_glob); 687c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= F_PIPEOUT | 688c80476e4SDavid E. O'Brien (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 68929301572SMark Peek execute(t->t_dcar, wanttty, pipein, pv, do_glob); 690c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 691c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= F_PIPEOUT | 692c80476e4SDavid E. O'Brien (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 69329301572SMark Peek execute(t->t_dcar, wanttty, pipein, pv, do_glob); 694c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 695c80476e4SDavid E. O'Brien (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 69629301572SMark Peek execute(t->t_dcdr, wanttty, pv, pipeout, do_glob); 697c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 698c80476e4SDavid E. O'Brien break; 699c80476e4SDavid E. O'Brien 700c80476e4SDavid E. O'Brien case NODE_LIST: 701c80476e4SDavid E. O'Brien if (t->t_dcar) { 702c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 70329301572SMark Peek execute(t->t_dcar, wanttty, NULL, NULL, do_glob); 704c80476e4SDavid E. O'Brien /* 705c80476e4SDavid E. O'Brien * In strange case of A&B make a new job after A 706c80476e4SDavid E. O'Brien */ 707c80476e4SDavid E. O'Brien if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 708c80476e4SDavid E. O'Brien (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 709c80476e4SDavid E. O'Brien pendjob(); 710c80476e4SDavid E. O'Brien } 711c80476e4SDavid E. O'Brien if (t->t_dcdr) { 712c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= t->t_dflg & 713c80476e4SDavid E. O'Brien (F_NOFORK | F_NOINTERRUPT); 71429301572SMark Peek execute(t->t_dcdr, wanttty, NULL, NULL, do_glob); 715c80476e4SDavid E. O'Brien } 716c80476e4SDavid E. O'Brien break; 717c80476e4SDavid E. O'Brien 718c80476e4SDavid E. O'Brien case NODE_OR: 719c80476e4SDavid E. O'Brien case NODE_AND: 720c80476e4SDavid E. O'Brien if (t->t_dcar) { 721c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 72229301572SMark Peek execute(t->t_dcar, wanttty, NULL, NULL, do_glob); 723c80476e4SDavid E. O'Brien if ((getn(varval(STRstatus)) == 0) != 724c80476e4SDavid E. O'Brien (t->t_dtyp == NODE_AND)) { 725c80476e4SDavid E. O'Brien return; 726c80476e4SDavid E. O'Brien } 727c80476e4SDavid E. O'Brien } 728c80476e4SDavid E. O'Brien if (t->t_dcdr) { 729c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= t->t_dflg & 730c80476e4SDavid E. O'Brien (F_NOFORK | F_NOINTERRUPT); 73129301572SMark Peek execute(t->t_dcdr, wanttty, NULL, NULL, do_glob); 732c80476e4SDavid E. O'Brien } 733c80476e4SDavid E. O'Brien break; 734c80476e4SDavid E. O'Brien 735c80476e4SDavid E. O'Brien default: 736c80476e4SDavid E. O'Brien break; 737c80476e4SDavid E. O'Brien } 738c80476e4SDavid E. O'Brien /* 739c80476e4SDavid E. O'Brien * Fall through for all breaks from switch 740c80476e4SDavid E. O'Brien * 741c80476e4SDavid E. O'Brien * If there will be no more executions of this command, flush all file 742c80476e4SDavid E. O'Brien * descriptors. Places that turn on the F_REPEAT bit are responsible for 743c80476e4SDavid E. O'Brien * doing donefds after the last re-execution 744c80476e4SDavid E. O'Brien */ 745c80476e4SDavid E. O'Brien if (didfds && !(t->t_dflg & F_REPEAT)) 746c80476e4SDavid E. O'Brien donefds(); 747c80476e4SDavid E. O'Brien } 748c80476e4SDavid E. O'Brien 749c80476e4SDavid E. O'Brien #ifdef VFORK 750c80476e4SDavid E. O'Brien static sigret_t 751c80476e4SDavid E. O'Brien /*ARGSUSED*/ 752c80476e4SDavid E. O'Brien vffree(snum) 753c80476e4SDavid E. O'Brien int snum; 754c80476e4SDavid E. O'Brien { 755c80476e4SDavid E. O'Brien register Char **v; 756c80476e4SDavid E. O'Brien 757c80476e4SDavid E. O'Brien USE(snum); 758c80476e4SDavid E. O'Brien if ((v = gargv) != 0) { 759c80476e4SDavid E. O'Brien gargv = 0; 760c80476e4SDavid E. O'Brien xfree((ptr_t) v); 761c80476e4SDavid E. O'Brien } 762c80476e4SDavid E. O'Brien 763c80476e4SDavid E. O'Brien if ((v = pargv) != 0) { 764c80476e4SDavid E. O'Brien pargv = 0; 765c80476e4SDavid E. O'Brien xfree((ptr_t) v); 766c80476e4SDavid E. O'Brien } 767c80476e4SDavid E. O'Brien 768c80476e4SDavid E. O'Brien _exit(1); 769c80476e4SDavid E. O'Brien #ifndef SIGVOID 770c80476e4SDavid E. O'Brien /*NOTREACHED*/ 771c80476e4SDavid E. O'Brien return(0); 772c80476e4SDavid E. O'Brien #endif /* SIGVOID */ 773c80476e4SDavid E. O'Brien } 774c80476e4SDavid E. O'Brien #endif /* VFORK */ 775c80476e4SDavid E. O'Brien 776c80476e4SDavid E. O'Brien /* 777c80476e4SDavid E. O'Brien * Expand and glob the words after an i/o redirection. 778c80476e4SDavid E. O'Brien * If more than one word is generated, then update the command vector. 779c80476e4SDavid E. O'Brien * 780c80476e4SDavid E. O'Brien * This is done differently in all the shells: 781c80476e4SDavid E. O'Brien * 1. in the bourne shell and ksh globbing is not performed 782c80476e4SDavid E. O'Brien * 2. Bash/csh say ambiguous 783c80476e4SDavid E. O'Brien * 3. zsh does i/o to/from all the files 784c80476e4SDavid E. O'Brien * 4. itcsh concatenates the words. 785c80476e4SDavid E. O'Brien * 786c80476e4SDavid E. O'Brien * I don't know what is best to do. I think that Ambiguous is better 787c80476e4SDavid E. O'Brien * than restructuring the command vector, because the user can get 788c80476e4SDavid E. O'Brien * unexpected results. In any case, the command vector restructuring 789c80476e4SDavid E. O'Brien * code is present and the user can choose it by setting noambiguous 790c80476e4SDavid E. O'Brien */ 791c80476e4SDavid E. O'Brien static Char * 792c80476e4SDavid E. O'Brien splicepipe(t, cp) 793c80476e4SDavid E. O'Brien register struct command *t; 794c80476e4SDavid E. O'Brien Char *cp; /* word after < or > */ 795c80476e4SDavid E. O'Brien { 796c80476e4SDavid E. O'Brien Char *blk[2]; 797c80476e4SDavid E. O'Brien 798c80476e4SDavid E. O'Brien if (adrof(STRnoambiguous)) { 799c80476e4SDavid E. O'Brien Char **pv; 800c80476e4SDavid E. O'Brien 801c80476e4SDavid E. O'Brien blk[0] = Dfix1(cp); /* expand $ */ 802c80476e4SDavid E. O'Brien blk[1] = NULL; 803c80476e4SDavid E. O'Brien 804c80476e4SDavid E. O'Brien gflag = 0, tglob(blk); 805c80476e4SDavid E. O'Brien if (gflag) { 806c80476e4SDavid E. O'Brien pv = globall(blk); 807c80476e4SDavid E. O'Brien if (pv == NULL) { 808c80476e4SDavid E. O'Brien setname(short2str(blk[0])); 809c80476e4SDavid E. O'Brien xfree((ptr_t) blk[0]); 810c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_NOMATCH); 811c80476e4SDavid E. O'Brien } 812c80476e4SDavid E. O'Brien gargv = NULL; 813c80476e4SDavid E. O'Brien if (pv[1] != NULL) { /* we need to fix the command vector */ 814c80476e4SDavid E. O'Brien Char **av = blkspl(t->t_dcom, &pv[1]); 815c80476e4SDavid E. O'Brien xfree((ptr_t) t->t_dcom); 816c80476e4SDavid E. O'Brien t->t_dcom = av; 817c80476e4SDavid E. O'Brien } 818c80476e4SDavid E. O'Brien xfree((ptr_t) blk[0]); 819c80476e4SDavid E. O'Brien blk[0] = pv[0]; 820c80476e4SDavid E. O'Brien xfree((ptr_t) pv); 821c80476e4SDavid E. O'Brien } 822c80476e4SDavid E. O'Brien } 823c80476e4SDavid E. O'Brien else { 824c80476e4SDavid E. O'Brien Char buf[BUFSIZE]; 825c80476e4SDavid E. O'Brien 826c80476e4SDavid E. O'Brien (void) Strcpy(buf, blk[1] = Dfix1(cp)); 827c80476e4SDavid E. O'Brien xfree((ptr_t) blk[1]); 828c80476e4SDavid E. O'Brien blk[0] = globone(buf, G_ERROR); 829c80476e4SDavid E. O'Brien } 830c80476e4SDavid E. O'Brien return(blk[0]); 831c80476e4SDavid E. O'Brien } 832c80476e4SDavid E. O'Brien 833c80476e4SDavid E. O'Brien /* 834c80476e4SDavid E. O'Brien * Perform io redirection. 835c80476e4SDavid E. O'Brien * We may or maynot be forked here. 836c80476e4SDavid E. O'Brien */ 837c80476e4SDavid E. O'Brien static void 838c80476e4SDavid E. O'Brien doio(t, pipein, pipeout) 839c80476e4SDavid E. O'Brien register struct command *t; 840c80476e4SDavid E. O'Brien int *pipein, *pipeout; 841c80476e4SDavid E. O'Brien { 842c80476e4SDavid E. O'Brien register int fd; 843c80476e4SDavid E. O'Brien register Char *cp; 844c80476e4SDavid E. O'Brien register unsigned long flags = t->t_dflg; 845c80476e4SDavid E. O'Brien 846c80476e4SDavid E. O'Brien if (didfds || (flags & F_REPEAT)) 847c80476e4SDavid E. O'Brien return; 848c80476e4SDavid E. O'Brien if ((flags & F_READ) == 0) {/* F_READ already done */ 849c80476e4SDavid E. O'Brien if (t->t_dlef) { 850c80476e4SDavid E. O'Brien char tmp[MAXPATHLEN+1]; 851c80476e4SDavid E. O'Brien 852c80476e4SDavid E. O'Brien /* 853c80476e4SDavid E. O'Brien * so < /dev/std{in,out,err} work 854c80476e4SDavid E. O'Brien */ 855c80476e4SDavid E. O'Brien (void) dcopy(SHIN, 0); 856c80476e4SDavid E. O'Brien (void) dcopy(SHOUT, 1); 857c80476e4SDavid E. O'Brien (void) dcopy(SHDIAG, 2); 858c80476e4SDavid E. O'Brien cp = splicepipe(t, t->t_dlef); 859c80476e4SDavid E. O'Brien (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 860c80476e4SDavid E. O'Brien tmp[MAXPATHLEN] = '\0'; 861c80476e4SDavid E. O'Brien xfree((ptr_t) cp); 862c80476e4SDavid E. O'Brien if ((fd = open(tmp, O_RDONLY)) < 0) 863c80476e4SDavid E. O'Brien stderror(ERR_SYSTEM, tmp, strerror(errno)); 864c80476e4SDavid E. O'Brien #ifdef O_LARGEFILE 865c80476e4SDavid E. O'Brien /* allow input files larger than 2Gb */ 866c80476e4SDavid E. O'Brien (void) fcntl(fd, O_LARGEFILE, 0); 867c80476e4SDavid E. O'Brien #endif /* O_LARGEFILE */ 868c80476e4SDavid E. O'Brien (void) dmove(fd, 0); 869c80476e4SDavid E. O'Brien } 870c80476e4SDavid E. O'Brien else if (flags & F_PIPEIN) { 871c80476e4SDavid E. O'Brien (void) close(0); 872c80476e4SDavid E. O'Brien (void) dup(pipein[0]); 873c80476e4SDavid E. O'Brien (void) close(pipein[0]); 874c80476e4SDavid E. O'Brien (void) close(pipein[1]); 875c80476e4SDavid E. O'Brien } 876c80476e4SDavid E. O'Brien else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 877c80476e4SDavid E. O'Brien (void) close(0); 878c80476e4SDavid E. O'Brien (void) open(_PATH_DEVNULL, O_RDONLY); 879c80476e4SDavid E. O'Brien } 880c80476e4SDavid E. O'Brien else { 881c80476e4SDavid E. O'Brien (void) close(0); 882c80476e4SDavid E. O'Brien (void) dup(OLDSTD); 883c80476e4SDavid E. O'Brien #if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 884c80476e4SDavid E. O'Brien /* 885c80476e4SDavid E. O'Brien * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved 886c80476e4SDavid E. O'Brien * across dup()s, so we have to UNSET it here or else we get a 887c80476e4SDavid E. O'Brien * command with NO stdin, stdout, or stderr at all (a bad thing 888c80476e4SDavid E. O'Brien * indeed) 889c80476e4SDavid E. O'Brien */ 890c80476e4SDavid E. O'Brien (void) close_on_exec(0, 0); 891c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 892c80476e4SDavid E. O'Brien } 893c80476e4SDavid E. O'Brien } 894c80476e4SDavid E. O'Brien if (t->t_drit) { 895c80476e4SDavid E. O'Brien char tmp[MAXPATHLEN+1]; 896c80476e4SDavid E. O'Brien 897c80476e4SDavid E. O'Brien cp = splicepipe(t, t->t_drit); 898c80476e4SDavid E. O'Brien (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 899c80476e4SDavid E. O'Brien tmp[MAXPATHLEN] = '\0'; 900c80476e4SDavid E. O'Brien xfree((ptr_t) cp); 901c80476e4SDavid E. O'Brien /* 902c80476e4SDavid E. O'Brien * so > /dev/std{out,err} work 903c80476e4SDavid E. O'Brien */ 904c80476e4SDavid E. O'Brien (void) dcopy(SHOUT, 1); 905c80476e4SDavid E. O'Brien (void) dcopy(SHDIAG, 2); 906c80476e4SDavid E. O'Brien if ((flags & F_APPEND) != 0) { 907c80476e4SDavid E. O'Brien #ifdef O_APPEND 908c80476e4SDavid E. O'Brien fd = open(tmp, O_WRONLY | O_APPEND); 909c80476e4SDavid E. O'Brien #else /* !O_APPEND */ 910c80476e4SDavid E. O'Brien fd = open(tmp, O_WRONLY); 911c80476e4SDavid E. O'Brien (void) lseek(fd, (off_t) 0, L_XTND); 912c80476e4SDavid E. O'Brien #endif /* O_APPEND */ 913c80476e4SDavid E. O'Brien } 914c80476e4SDavid E. O'Brien else 915c80476e4SDavid E. O'Brien fd = 0; 916c80476e4SDavid E. O'Brien if ((flags & F_APPEND) == 0 || fd == -1) { 917c80476e4SDavid E. O'Brien if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 918c80476e4SDavid E. O'Brien if (flags & F_APPEND) 919c80476e4SDavid E. O'Brien stderror(ERR_SYSTEM, tmp, strerror(errno)); 920c80476e4SDavid E. O'Brien chkclob(tmp); 921c80476e4SDavid E. O'Brien } 922c80476e4SDavid E. O'Brien if ((fd = creat(tmp, 0666)) < 0) 923c80476e4SDavid E. O'Brien stderror(ERR_SYSTEM, tmp, strerror(errno)); 924c80476e4SDavid E. O'Brien #ifdef O_LARGEFILE 925c80476e4SDavid E. O'Brien /* allow input files larger than 2Gb */ 926c80476e4SDavid E. O'Brien (void) fcntl(fd, O_LARGEFILE, 0); 927c80476e4SDavid E. O'Brien #endif /* O_LARGEFILE */ 928c80476e4SDavid E. O'Brien } 929c80476e4SDavid E. O'Brien (void) dmove(fd, 1); 930c80476e4SDavid E. O'Brien is1atty = isatty(1); 931c80476e4SDavid E. O'Brien } 932c80476e4SDavid E. O'Brien else if (flags & F_PIPEOUT) { 933c80476e4SDavid E. O'Brien (void) close(1); 934c80476e4SDavid E. O'Brien (void) dup(pipeout[1]); 935c80476e4SDavid E. O'Brien is1atty = 0; 936c80476e4SDavid E. O'Brien } 937c80476e4SDavid E. O'Brien else { 938c80476e4SDavid E. O'Brien (void) close(1); 939c80476e4SDavid E. O'Brien (void) dup(SHOUT); 940c80476e4SDavid E. O'Brien is1atty = isoutatty; 941c80476e4SDavid E. O'Brien # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 942c80476e4SDavid E. O'Brien (void) close_on_exec(1, 0); 943c80476e4SDavid E. O'Brien # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 944c80476e4SDavid E. O'Brien } 945c80476e4SDavid E. O'Brien 946c80476e4SDavid E. O'Brien (void) close(2); 947c80476e4SDavid E. O'Brien if (flags & F_STDERR) { 948c80476e4SDavid E. O'Brien (void) dup(1); 949c80476e4SDavid E. O'Brien is2atty = is1atty; 950c80476e4SDavid E. O'Brien } 951c80476e4SDavid E. O'Brien else { 952c80476e4SDavid E. O'Brien (void) dup(SHDIAG); 953c80476e4SDavid E. O'Brien is2atty = isdiagatty; 954c80476e4SDavid E. O'Brien # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 955c80476e4SDavid E. O'Brien (void) close_on_exec(2, 0); 956c80476e4SDavid E. O'Brien # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 957c80476e4SDavid E. O'Brien } 958c80476e4SDavid E. O'Brien didfds = 1; 959c80476e4SDavid E. O'Brien } 960c80476e4SDavid E. O'Brien 961c80476e4SDavid E. O'Brien void 962c80476e4SDavid E. O'Brien mypipe(pv) 963c80476e4SDavid E. O'Brien register int *pv; 964c80476e4SDavid E. O'Brien { 965c80476e4SDavid E. O'Brien 966c80476e4SDavid E. O'Brien if (pipe(pv) < 0) 967c80476e4SDavid E. O'Brien goto oops; 968c80476e4SDavid E. O'Brien pv[0] = dmove(pv[0], -1); 969c80476e4SDavid E. O'Brien pv[1] = dmove(pv[1], -1); 970c80476e4SDavid E. O'Brien if (pv[0] >= 0 && pv[1] >= 0) 971c80476e4SDavid E. O'Brien return; 972c80476e4SDavid E. O'Brien oops: 973c80476e4SDavid E. O'Brien stderror(ERR_PIPE); 974c80476e4SDavid E. O'Brien } 975c80476e4SDavid E. O'Brien 976c80476e4SDavid E. O'Brien static void 977c80476e4SDavid E. O'Brien chkclob(cp) 978c80476e4SDavid E. O'Brien register char *cp; 979c80476e4SDavid E. O'Brien { 980c80476e4SDavid E. O'Brien struct stat stb; 981c80476e4SDavid E. O'Brien 982c80476e4SDavid E. O'Brien if (stat(cp, &stb) < 0) 983c80476e4SDavid E. O'Brien return; 984c80476e4SDavid E. O'Brien if (S_ISCHR(stb.st_mode)) 985c80476e4SDavid E. O'Brien return; 986c80476e4SDavid E. O'Brien stderror(ERR_EXISTS, cp); 987c80476e4SDavid E. O'Brien } 988