1a15e6f9aSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/sh.sem.c,v 3.80 2009/06/25 21:27:38 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 36a15e6f9aSMark Peek RCSID("$tcsh: sh.sem.c,v 3.80 2009/06/25 21:27:38 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) 5323338178SMark Peek # if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(linux) && !defined(__GNU__) && !defined(__GLIBC__) 54c80476e4SDavid E. O'Brien # include <vfork.h> 5523338178SMark Peek # endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 && !glibc */ 56c80476e4SDavid E. O'Brien #endif /* __sparc__ || sparc */ 57c80476e4SDavid E. O'Brien 58c80476e4SDavid E. O'Brien #ifdef VFORK 5945e5710bSMark Peek static void vffree (int); 60c80476e4SDavid E. O'Brien #endif 6145e5710bSMark Peek static Char *splicepipe (struct command *, Char *); 6245e5710bSMark Peek static void doio (struct command *, int *, int *); 6345e5710bSMark Peek static void chkclob (const 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 8745e5710bSMark Peek execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, 8845e5710bSMark Peek int do_glob) 89c80476e4SDavid E. O'Brien { 9023338178SMark Peek int forked = 0; 9145e5710bSMark Peek const struct biltins * volatile bifunc; 9245e5710bSMark Peek pid_t pid = 0; 93c80476e4SDavid E. O'Brien int pv[2]; 9445e5710bSMark Peek sigset_t set; 9545e5710bSMark Peek static sigset_t csigset; 96c80476e4SDavid E. O'Brien #ifdef VFORK 97c80476e4SDavid E. O'Brien static int onosigchld = 0; 98c80476e4SDavid E. O'Brien #endif /* VFORK */ 99c80476e4SDavid E. O'Brien static int nosigchld = 0; 100c80476e4SDavid E. O'Brien 101c80476e4SDavid E. O'Brien (void) &wanttty; 102c80476e4SDavid E. O'Brien (void) &forked; 103c80476e4SDavid E. O'Brien (void) &bifunc; 104c80476e4SDavid E. O'Brien 105c80476e4SDavid E. O'Brien if (t == 0) 106c80476e4SDavid E. O'Brien return; 107c80476e4SDavid E. O'Brien 1083b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 109c80476e4SDavid E. O'Brien { 110c80476e4SDavid E. O'Brien if ((varval(STRNTslowexec) == STRNULL) && 111c80476e4SDavid E. O'Brien !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds && 112c80476e4SDavid E. O'Brien (intty || intact) && (t->t_dtyp == NODE_COMMAND) && 113c80476e4SDavid E. O'Brien !isbfunc(t)) { 114c80476e4SDavid E. O'Brien if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 115c80476e4SDavid E. O'Brien (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 116c80476e4SDavid E. O'Brien Dfix(t); 117c80476e4SDavid E. O'Brien if (nt_try_fast_exec(t) == 0) 118c80476e4SDavid E. O'Brien return; 119c80476e4SDavid E. O'Brien } 120c80476e4SDavid E. O'Brien } 1213b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 122c80476e4SDavid E. O'Brien 123c80476e4SDavid E. O'Brien /* 124c80476e4SDavid E. O'Brien * Ed hutchins@sgi.com & Dominic dbg@sgi.com 125c80476e4SDavid E. O'Brien * Sat Feb 25 03:13:11 PST 1995 126c80476e4SDavid E. O'Brien * try implicit cd if we have a 1 word command 127c80476e4SDavid E. O'Brien */ 128c80476e4SDavid E. O'Brien if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] && 129c80476e4SDavid E. O'Brien t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) { 13045e5710bSMark Peek Char *sCName; 131c80476e4SDavid E. O'Brien struct stat stbuf; 132c80476e4SDavid E. O'Brien char *pathname; 133c80476e4SDavid E. O'Brien 13445e5710bSMark Peek sCName = dollar(t->t_dcom[0]); 13545e5710bSMark Peek if (sCName != NULL && sCName[0] == '~') { 13645e5710bSMark Peek struct Strbuf buf = Strbuf_INIT; 13745e5710bSMark Peek const Char *name_end; 138c80476e4SDavid E. O'Brien 13945e5710bSMark Peek for (name_end = sCName + 1; *name_end != '\0' && *name_end != '/'; 14045e5710bSMark Peek name_end++) 14145e5710bSMark Peek continue; 14245e5710bSMark Peek if (name_end != sCName + 1) { 14345e5710bSMark Peek Char *name, *home; 14445e5710bSMark Peek 14545e5710bSMark Peek name = Strnsave(sCName + 1, name_end - (sCName + 1)); 14645e5710bSMark Peek home = gethdir(name); 14745e5710bSMark Peek if (home != NULL) { 14845e5710bSMark Peek Strbuf_append(&buf, home); 14945e5710bSMark Peek xfree(home); 15045e5710bSMark Peek } else 15145e5710bSMark Peek Strbuf_append(&buf, name); 15245e5710bSMark Peek xfree(name); 15345e5710bSMark Peek } else 15445e5710bSMark Peek Strbuf_append(&buf, varval(STRhome)); 15545e5710bSMark Peek Strbuf_append(&buf, name_end); 15645e5710bSMark Peek xfree(sCName); 15745e5710bSMark Peek sCName = Strbuf_finish(&buf); 158c80476e4SDavid E. O'Brien } 159c80476e4SDavid E. O'Brien 160c80476e4SDavid E. O'Brien pathname = short2str(sCName); 16145e5710bSMark Peek xfree(sCName); 162c80476e4SDavid E. O'Brien /* if this is a dir, tack a "cd" on as the first arg */ 16345e5710bSMark Peek if (pathname != NULL && 16445e5710bSMark Peek ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode)) 1653b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE 166c80476e4SDavid E. O'Brien || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0') 1673b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */ 16845e5710bSMark Peek )) { 169c80476e4SDavid E. O'Brien Char *vCD[2]; 170c80476e4SDavid E. O'Brien Char **ot_dcom = t->t_dcom; 171c80476e4SDavid E. O'Brien 172c80476e4SDavid E. O'Brien vCD[0] = Strsave(STRcd); 173c80476e4SDavid E. O'Brien vCD[1] = NULL; 174c80476e4SDavid E. O'Brien t->t_dcom = blkspl(vCD, ot_dcom); 17545e5710bSMark Peek xfree(ot_dcom); 176c80476e4SDavid E. O'Brien if (implicit_cd > 1) { 177c80476e4SDavid E. O'Brien blkpr(t->t_dcom); 178c80476e4SDavid E. O'Brien xputchar( '\n' ); 179c80476e4SDavid E. O'Brien } 180c80476e4SDavid E. O'Brien } 181c80476e4SDavid E. O'Brien } 182c80476e4SDavid E. O'Brien 183c80476e4SDavid E. O'Brien /* 184c80476e4SDavid E. O'Brien * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 185c80476e4SDavid E. O'Brien * Don't check for wantty > 0... 186c80476e4SDavid E. O'Brien */ 187c80476e4SDavid E. O'Brien if (t->t_dflg & F_AMPERSAND) 188c80476e4SDavid E. O'Brien wanttty = 0; 189c80476e4SDavid E. O'Brien switch (t->t_dtyp) { 190c80476e4SDavid E. O'Brien 191c80476e4SDavid E. O'Brien case NODE_COMMAND: 192c80476e4SDavid E. O'Brien if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 19345e5710bSMark Peek memmove(t->t_dcom[0], t->t_dcom[0] + 1, 19445e5710bSMark Peek (Strlen(t->t_dcom[0] + 1) + 1) * sizeof (*t->t_dcom[0])); 195c80476e4SDavid E. O'Brien if ((t->t_dflg & F_REPEAT) == 0) 196c80476e4SDavid E. O'Brien Dfix(t); /* $ " ' \ */ 197c80476e4SDavid E. O'Brien if (t->t_dcom[0] == 0) { 198c80476e4SDavid E. O'Brien return; 199c80476e4SDavid E. O'Brien } 200c80476e4SDavid E. O'Brien /*FALLTHROUGH*/ 201c80476e4SDavid E. O'Brien 202c80476e4SDavid E. O'Brien case NODE_PAREN: 203c80476e4SDavid E. O'Brien #ifdef BACKPIPE 204c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEIN) 205c80476e4SDavid E. O'Brien mypipe(pipein); 206c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 207c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEOUT) 208c80476e4SDavid E. O'Brien mypipe(pipeout); 209c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 210c80476e4SDavid E. O'Brien /* 211c80476e4SDavid E. O'Brien * Must do << early so parent will know where input pointer should be. 212c80476e4SDavid E. O'Brien * If noexec then this is all we do. 213c80476e4SDavid E. O'Brien */ 214c80476e4SDavid E. O'Brien if (t->t_dflg & F_READ) { 21545e5710bSMark Peek xclose(0); 216c80476e4SDavid E. O'Brien heredoc(t->t_dlef); 217c80476e4SDavid E. O'Brien if (noexec) 21845e5710bSMark Peek xclose(0); 219c80476e4SDavid E. O'Brien } 220c80476e4SDavid E. O'Brien 22145e5710bSMark Peek setcopy(STRstatus, STR0, VAR_READWRITE); 222c80476e4SDavid E. O'Brien 223c80476e4SDavid E. O'Brien /* 224c80476e4SDavid E. O'Brien * This mess is the necessary kludge to handle the prefix builtins: 225c80476e4SDavid E. O'Brien * nice, nohup, time. These commands can also be used by themselves, 226c80476e4SDavid E. O'Brien * and this is not handled here. This will also work when loops are 227c80476e4SDavid E. O'Brien * parsed. 228c80476e4SDavid E. O'Brien */ 229c80476e4SDavid E. O'Brien while (t->t_dtyp == NODE_COMMAND) 230c80476e4SDavid E. O'Brien if (eq(t->t_dcom[0], STRnice)) { 231c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 232c80476e4SDavid E. O'Brien if (strchr("+-", t->t_dcom[1][0])) { 233c80476e4SDavid E. O'Brien if (t->t_dcom[2]) { 234c80476e4SDavid E. O'Brien setname("nice"); 235c80476e4SDavid E. O'Brien t->t_nice = 236c80476e4SDavid E. O'Brien getn(t->t_dcom[1]); 237c80476e4SDavid E. O'Brien lshift(t->t_dcom, 2); 238c80476e4SDavid E. O'Brien t->t_dflg |= F_NICE; 239c80476e4SDavid E. O'Brien } 240c80476e4SDavid E. O'Brien else 241c80476e4SDavid E. O'Brien break; 242c80476e4SDavid E. O'Brien } 243c80476e4SDavid E. O'Brien else { 244c80476e4SDavid E. O'Brien t->t_nice = 4; 245c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 246c80476e4SDavid E. O'Brien t->t_dflg |= F_NICE; 247c80476e4SDavid E. O'Brien } 248c80476e4SDavid E. O'Brien } 249c80476e4SDavid E. O'Brien else 250c80476e4SDavid E. O'Brien break; 251c80476e4SDavid E. O'Brien } 252c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRnohup)) { 253c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 254c80476e4SDavid E. O'Brien t->t_dflg |= F_NOHUP; 255c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 256c80476e4SDavid E. O'Brien } 257c80476e4SDavid E. O'Brien else 258c80476e4SDavid E. O'Brien break; 259c80476e4SDavid E. O'Brien } 260c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRhup)) { 261c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 262c80476e4SDavid E. O'Brien t->t_dflg |= F_HUP; 263c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 264c80476e4SDavid E. O'Brien } 265c80476e4SDavid E. O'Brien else 266c80476e4SDavid E. O'Brien break; 267c80476e4SDavid E. O'Brien } 268c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRtime)) { 269c80476e4SDavid E. O'Brien if (t->t_dcom[1]) { 270c80476e4SDavid E. O'Brien t->t_dflg |= F_TIME; 271c80476e4SDavid E. O'Brien lshift(t->t_dcom, 1); 272c80476e4SDavid E. O'Brien } 273c80476e4SDavid E. O'Brien else 274c80476e4SDavid E. O'Brien break; 275c80476e4SDavid E. O'Brien } 276c80476e4SDavid E. O'Brien #ifdef F_VER 277c80476e4SDavid E. O'Brien else if (eq(t->t_dcom[0], STRver)) 278c80476e4SDavid E. O'Brien if (t->t_dcom[1] && t->t_dcom[2]) { 279c80476e4SDavid E. O'Brien setname("ver"); 280c80476e4SDavid E. O'Brien t->t_systype = getv(t->t_dcom[1]); 281c80476e4SDavid E. O'Brien lshift(t->t_dcom, 2); 282c80476e4SDavid E. O'Brien t->t_dflg |= F_VER; 283c80476e4SDavid E. O'Brien } 284c80476e4SDavid E. O'Brien else 285c80476e4SDavid E. O'Brien break; 286c80476e4SDavid E. O'Brien #endif /* F_VER */ 287c80476e4SDavid E. O'Brien else 288c80476e4SDavid E. O'Brien break; 289c80476e4SDavid E. O'Brien 290c80476e4SDavid E. O'Brien /* is it a command */ 291c80476e4SDavid E. O'Brien if (t->t_dtyp == NODE_COMMAND) { 292c80476e4SDavid E. O'Brien /* 293c80476e4SDavid E. O'Brien * Check if we have a builtin function and remember which one. 294c80476e4SDavid E. O'Brien */ 295c80476e4SDavid E. O'Brien bifunc = isbfunc(t); 29645e5710bSMark Peek if (noexec) { 297c80476e4SDavid E. O'Brien /* 298c80476e4SDavid E. O'Brien * Continue for builtins that are part of the scripting language 299c80476e4SDavid E. O'Brien */ 30045e5710bSMark Peek if (bifunc == NULL) 30145e5710bSMark Peek break; 302c80476e4SDavid E. O'Brien if (bifunc->bfunct != (bfunc_t)dobreak && 303c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)docontin && 304c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doelse && 305c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doend && 306c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doforeach&& 307c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dogoto && 308c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doif && 309c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dorepeat && 310c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doswbrk && 311c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)doswitch && 312c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dowhile && 313c80476e4SDavid E. O'Brien bifunc->bfunct != (bfunc_t)dozip) 314c80476e4SDavid E. O'Brien break; 315c80476e4SDavid E. O'Brien } 316c80476e4SDavid E. O'Brien } 317c80476e4SDavid E. O'Brien else { /* not a command */ 318c80476e4SDavid E. O'Brien bifunc = NULL; 319c80476e4SDavid E. O'Brien if (noexec) 320c80476e4SDavid E. O'Brien break; 321c80476e4SDavid E. O'Brien } 322c80476e4SDavid E. O'Brien 323c80476e4SDavid E. O'Brien /* 3246767bd61SMark Peek * GrP Executing a command - run jobcmd hook 3256767bd61SMark Peek * Don't run for builtins 3266767bd61SMark Peek * Don't run if we're not in a tty 3276767bd61SMark Peek * Don't run if we're not really executing 3286767bd61SMark Peek */ 329a15e6f9aSMark Peek /* 330a15e6f9aSMark Peek * CR - Charles Ross Aug 2005 331a15e6f9aSMark Peek * added "isoutatty". 332a15e6f9aSMark Peek * The new behavior is that the jobcmd won't be executed 333a15e6f9aSMark Peek * if stdout (SHOUT) isnt attached to a tty.. IE when 334a15e6f9aSMark Peek * redirecting, or using backquotes etc.. 335a15e6f9aSMark Peek */ 336a15e6f9aSMark Peek if (t->t_dtyp == NODE_COMMAND && !bifunc && !noexec && intty && isoutatty) { 3376767bd61SMark Peek Char *cmd = unparse(t); 33845e5710bSMark Peek 33945e5710bSMark Peek cleanup_push(cmd, xfree); 3406767bd61SMark Peek job_cmd(cmd); 34145e5710bSMark Peek cleanup_until(cmd); 3426767bd61SMark Peek } 3436767bd61SMark Peek 3446767bd61SMark Peek /* 345c80476e4SDavid E. O'Brien * We fork only if we are timed, or are not the end of a parenthesized 346c80476e4SDavid E. O'Brien * list and not a simple builtin function. Simple meaning one that is 347c80476e4SDavid E. O'Brien * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 348c80476e4SDavid E. O'Brien * fork in some of these cases. 349c80476e4SDavid E. O'Brien */ 350c80476e4SDavid E. O'Brien /* 351c80476e4SDavid E. O'Brien * Prevent forking cd, pushd, popd, chdir cause this will cause the 352c80476e4SDavid E. O'Brien * shell not to change dir! 353c80476e4SDavid E. O'Brien */ 354c80476e4SDavid E. O'Brien #ifdef BACKPIPE 355c80476e4SDavid E. O'Brien /* 356c80476e4SDavid E. O'Brien * Can't have NOFORK for the tail of a pipe - because it is not the 357c80476e4SDavid E. O'Brien * last command spawned (even if it is at the end of a parenthesised 358c80476e4SDavid E. O'Brien * list). 359c80476e4SDavid E. O'Brien */ 360c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEIN) 361c80476e4SDavid E. O'Brien t->t_dflg &= ~(F_NOFORK); 362c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 363c80476e4SDavid E. O'Brien if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd || 364c80476e4SDavid E. O'Brien bifunc->bfunct == (bfunc_t)dopushd || 365c80476e4SDavid E. O'Brien bifunc->bfunct == (bfunc_t)dopopd)) 366c80476e4SDavid E. O'Brien t->t_dflg &= ~(F_NICE); 367c80476e4SDavid E. O'Brien if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && 368c80476e4SDavid E. O'Brien (!bifunc || t->t_dflg & 369c80476e4SDavid E. O'Brien (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) || 370c80476e4SDavid E. O'Brien /* 371c80476e4SDavid E. O'Brien * We have to fork for eval too. 372c80476e4SDavid E. O'Brien */ 373c80476e4SDavid E. O'Brien (bifunc && (t->t_dflg & F_PIPEIN) != 0 && 3743b6eaa7bSAndrey A. Chernov bifunc->bfunct == (bfunc_t)doeval)) { 375c80476e4SDavid E. O'Brien #ifdef VFORK 376c80476e4SDavid E. O'Brien if (t->t_dtyp == NODE_PAREN || 377c80476e4SDavid E. O'Brien t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) 378c80476e4SDavid E. O'Brien #endif /* VFORK */ 379c80476e4SDavid E. O'Brien { 380c80476e4SDavid E. O'Brien forked++; 381c80476e4SDavid E. O'Brien /* 382c80476e4SDavid E. O'Brien * We need to block SIGCHLD here, so that if the process does 383c80476e4SDavid E. O'Brien * not die before we can set the process group 384c80476e4SDavid E. O'Brien */ 385c80476e4SDavid E. O'Brien if (wanttty >= 0 && !nosigchld) { 38645e5710bSMark Peek sigemptyset(&set); 38745e5710bSMark Peek sigaddset(&set, SIGCHLD); 38845e5710bSMark Peek (void)sigprocmask(SIG_BLOCK, &set, &csigset); 389c80476e4SDavid E. O'Brien 390c80476e4SDavid E. O'Brien nosigchld = 1; 391c80476e4SDavid E. O'Brien } 392c80476e4SDavid E. O'Brien 393c80476e4SDavid E. O'Brien pid = pfork(t, wanttty); 394c80476e4SDavid E. O'Brien if (pid == 0 && nosigchld) { 39545e5710bSMark Peek sigprocmask(SIG_SETMASK, &csigset, NULL); 396c80476e4SDavid E. O'Brien nosigchld = 0; 397c80476e4SDavid E. O'Brien } 398c80476e4SDavid E. O'Brien else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) 399c80476e4SDavid E. O'Brien backpid = pid; 400c80476e4SDavid E. O'Brien } 401c80476e4SDavid E. O'Brien 402c80476e4SDavid E. O'Brien #ifdef VFORK 403c80476e4SDavid E. O'Brien else { 404c80476e4SDavid E. O'Brien int ochild, osetintr, ohaderr, odidfds; 405c80476e4SDavid E. O'Brien int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; 406c80476e4SDavid E. O'Brien int oisoutatty, oisdiagatty; 40745e5710bSMark Peek sigset_t oset, ocsigset; 408c80476e4SDavid E. O'Brien # ifndef CLOSE_ON_EXEC 409c80476e4SDavid E. O'Brien int odidcch; 410c80476e4SDavid E. O'Brien # endif /* !CLOSE_ON_EXEC */ 411c80476e4SDavid E. O'Brien 412c80476e4SDavid E. O'Brien /* 413c80476e4SDavid E. O'Brien * Prepare for the vfork by saving everything that the child 414c80476e4SDavid E. O'Brien * corrupts before it exec's. Note that in some signal 415c80476e4SDavid E. O'Brien * implementations which keep the signal info in user space 416c80476e4SDavid E. O'Brien * (e.g. Sun's) it will also be necessary to save and restore 417c80476e4SDavid E. O'Brien * the current sigvec's for the signals the child touches 418c80476e4SDavid E. O'Brien * before it exec's. 419c80476e4SDavid E. O'Brien */ 420c80476e4SDavid E. O'Brien 421c80476e4SDavid E. O'Brien /* 422c80476e4SDavid E. O'Brien * Sooooo true... If this is a Sun, save the sigvec's. (Skip 423c80476e4SDavid E. O'Brien * Gilbrech - 11/22/87) 424c80476e4SDavid E. O'Brien */ 425c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 42645e5710bSMark Peek struct sigaction savesv[NSIGSAVED]; 42745e5710bSMark Peek sigset_t savesm; 428c80476e4SDavid E. O'Brien 429c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 430c80476e4SDavid E. O'Brien if (wanttty >= 0 && !nosigchld && !noexec) { 43145e5710bSMark Peek sigemptyset(&set); 43245e5710bSMark Peek sigaddset(&set, SIGCHLD); 43345e5710bSMark Peek (void)sigprocmask(SIG_BLOCK, &set, &csigset); 434c80476e4SDavid E. O'Brien nosigchld = 1; 435c80476e4SDavid E. O'Brien } 43645e5710bSMark Peek sigemptyset(&set); 43745e5710bSMark Peek sigaddset(&set, SIGCHLD); 43845e5710bSMark Peek sigaddset(&set, SIGINT); 43945e5710bSMark Peek (void)sigprocmask(SIG_BLOCK, &set, &oset); 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; 45445e5710bSMark Peek ocsigset = csigset; 455c80476e4SDavid E. O'Brien onosigchld = nosigchld; 456c80476e4SDavid E. O'Brien Vsav = Vdp = 0; 457c80476e4SDavid E. O'Brien Vexpath = 0; 458c80476e4SDavid E. O'Brien Vt = 0; 459c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 46045e5710bSMark Peek savesigvec(savesv, savesm); 461c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 462c80476e4SDavid E. O'Brien if (use_fork) 463c80476e4SDavid E. O'Brien pid = fork(); 464c80476e4SDavid E. O'Brien else 465c80476e4SDavid E. O'Brien pid = vfork(); 466c80476e4SDavid E. O'Brien 467c80476e4SDavid E. O'Brien if (pid < 0) { 468c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 469c80476e4SDavid E. O'Brien restoresigvec(savesv, savesm); 470c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 47145e5710bSMark Peek sigprocmask(SIG_SETMASK, &oset, NULL); 472c80476e4SDavid E. O'Brien stderror(ERR_NOPROC); 473c80476e4SDavid E. O'Brien } 474c80476e4SDavid E. O'Brien forked++; 475c80476e4SDavid E. O'Brien if (pid) { /* parent */ 476c80476e4SDavid E. O'Brien # ifdef SAVESIGVEC 477c80476e4SDavid E. O'Brien restoresigvec(savesv, savesm); 478c80476e4SDavid E. O'Brien # endif /* SAVESIGVEC */ 479c80476e4SDavid E. O'Brien child = ochild; 480c80476e4SDavid E. O'Brien setintr = osetintr; 481c80476e4SDavid E. O'Brien haderr = ohaderr; 482c80476e4SDavid E. O'Brien didfds = odidfds; 483c80476e4SDavid E. O'Brien SHIN = oSHIN; 484c80476e4SDavid E. O'Brien # ifndef CLOSE_ON_EXEC 485c80476e4SDavid E. O'Brien didcch = odidcch; 486c80476e4SDavid E. O'Brien # endif /* !CLOSE_ON_EXEC */ 487c80476e4SDavid E. O'Brien SHOUT = oSHOUT; 488c80476e4SDavid E. O'Brien SHDIAG = oSHDIAG; 489c80476e4SDavid E. O'Brien OLDSTD = oOLDSTD; 490c80476e4SDavid E. O'Brien tpgrp = otpgrp; 491c80476e4SDavid E. O'Brien isoutatty = oisoutatty; 492c80476e4SDavid E. O'Brien isdiagatty = oisdiagatty; 49345e5710bSMark Peek csigset = ocsigset; 494c80476e4SDavid E. O'Brien nosigchld = onosigchld; 495c80476e4SDavid E. O'Brien 49645e5710bSMark Peek xfree(Vsav); 497c80476e4SDavid E. O'Brien Vsav = 0; 49845e5710bSMark Peek xfree(Vdp); 499c80476e4SDavid E. O'Brien Vdp = 0; 50045e5710bSMark Peek xfree(Vexpath); 501c80476e4SDavid E. O'Brien Vexpath = 0; 50245e5710bSMark Peek blk_cleanup(Vt); 503c80476e4SDavid E. O'Brien Vt = 0; 504c80476e4SDavid E. O'Brien /* this is from pfork() */ 505c80476e4SDavid E. O'Brien palloc(pid, t); 50645e5710bSMark Peek sigprocmask(SIG_SETMASK, &oset, NULL); 507c80476e4SDavid E. O'Brien } 508c80476e4SDavid E. O'Brien else { /* child */ 509c80476e4SDavid E. O'Brien /* this is from pfork() */ 51045e5710bSMark Peek pid_t pgrp; 51123338178SMark Peek int ignint = 0; 512c80476e4SDavid E. O'Brien if (nosigchld) { 51345e5710bSMark Peek sigprocmask(SIG_SETMASK, &csigset, NULL); 514c80476e4SDavid E. O'Brien nosigchld = 0; 515c80476e4SDavid E. O'Brien } 516c80476e4SDavid E. O'Brien 517c80476e4SDavid E. O'Brien if (setintr) 518c80476e4SDavid E. O'Brien ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 519c80476e4SDavid E. O'Brien || (gointr && eq(gointr, STRminus)); 520c80476e4SDavid E. O'Brien pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 521c80476e4SDavid E. O'Brien child++; 522c80476e4SDavid E. O'Brien if (setintr) { 523c80476e4SDavid E. O'Brien setintr = 0; 524c80476e4SDavid E. O'Brien /* 525c80476e4SDavid E. O'Brien * casts made right for SunOS 4.0 by Douglas C. Schmidt 526c80476e4SDavid E. O'Brien * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU> 527c80476e4SDavid E. O'Brien * (thanks! -- PWP) 528c80476e4SDavid E. O'Brien * 529c80476e4SDavid E. O'Brien * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET> 530c80476e4SDavid E. O'Brien * (thanks again) 531c80476e4SDavid E. O'Brien */ 532c80476e4SDavid E. O'Brien if (ignint) { 533c80476e4SDavid E. O'Brien (void) signal(SIGINT, SIG_IGN); 534c80476e4SDavid E. O'Brien (void) signal(SIGQUIT, SIG_IGN); 535c80476e4SDavid E. O'Brien } 536c80476e4SDavid E. O'Brien else { 537c80476e4SDavid E. O'Brien (void) signal(SIGINT, vffree); 538c80476e4SDavid E. O'Brien (void) signal(SIGQUIT, SIG_DFL); 539c80476e4SDavid E. O'Brien } 540c80476e4SDavid E. O'Brien # ifdef BSDJOBS 541c80476e4SDavid E. O'Brien if (wanttty >= 0) { 542c80476e4SDavid E. O'Brien (void) signal(SIGTSTP, SIG_DFL); 543c80476e4SDavid E. O'Brien (void) signal(SIGTTIN, SIG_DFL); 544c80476e4SDavid E. O'Brien (void) signal(SIGTTOU, SIG_DFL); 545c80476e4SDavid E. O'Brien } 546c80476e4SDavid E. O'Brien # endif /* BSDJOBS */ 547c80476e4SDavid E. O'Brien 54845e5710bSMark Peek sigaction(SIGTERM, &parterm, NULL); 549c80476e4SDavid E. O'Brien } 550c80476e4SDavid E. O'Brien else if (tpgrp == -1 && 551c80476e4SDavid E. O'Brien (t->t_dflg & F_NOINTERRUPT)) { 552c80476e4SDavid E. O'Brien (void) signal(SIGINT, SIG_IGN); 553c80476e4SDavid E. O'Brien (void) signal(SIGQUIT, SIG_IGN); 554c80476e4SDavid E. O'Brien } 555c80476e4SDavid E. O'Brien 556c80476e4SDavid E. O'Brien pgetty(wanttty, pgrp); 557c80476e4SDavid E. O'Brien 558c80476e4SDavid E. O'Brien if (t->t_dflg & F_NOHUP) 559c80476e4SDavid E. O'Brien (void) signal(SIGHUP, SIG_IGN); 560c80476e4SDavid E. O'Brien if (t->t_dflg & F_HUP) 561c80476e4SDavid E. O'Brien (void) signal(SIGHUP, SIG_DFL); 562c80476e4SDavid E. O'Brien if (t->t_dflg & F_NICE) { 563c80476e4SDavid E. O'Brien int nval = SIGN_EXTEND_CHAR(t->t_nice); 56423338178SMark Peek # ifdef HAVE_SETPRIORITY 5656767bd61SMark Peek if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno) 5666767bd61SMark Peek stderror(ERR_SYSTEM, "setpriority", 5676767bd61SMark Peek strerror(errno)); 56823338178SMark Peek # else /* !HAVE_SETPRIORITY */ 569c80476e4SDavid E. O'Brien (void) nice(nval); 57023338178SMark Peek # endif /* HAVE_SETPRIORITY */ 571c80476e4SDavid E. O'Brien } 572c80476e4SDavid E. O'Brien # ifdef F_VER 573c80476e4SDavid E. O'Brien if (t->t_dflg & F_VER) { 574c80476e4SDavid E. O'Brien tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53); 575c80476e4SDavid E. O'Brien dohash(NULL, NULL); 576c80476e4SDavid E. O'Brien } 577c80476e4SDavid E. O'Brien # endif /* F_VER */ 578c80476e4SDavid E. O'Brien } 579c80476e4SDavid E. O'Brien 580c80476e4SDavid E. O'Brien } 581c80476e4SDavid E. O'Brien #endif /* VFORK */ 5823b6eaa7bSAndrey A. Chernov } 583c80476e4SDavid E. O'Brien if (pid != 0) { 584c80476e4SDavid E. O'Brien /* 585c80476e4SDavid E. O'Brien * It would be better if we could wait for the whole job when we 586c80476e4SDavid E. O'Brien * knew the last process had been started. Pwait, in fact, does 587c80476e4SDavid E. O'Brien * wait for the whole job anyway, but this test doesn't really 588c80476e4SDavid E. O'Brien * express our intentions. 589c80476e4SDavid E. O'Brien */ 590c80476e4SDavid E. O'Brien #ifdef BACKPIPE 591c80476e4SDavid E. O'Brien if (didfds == 0 && t->t_dflg & F_PIPEOUT) { 59245e5710bSMark Peek xclose(pipeout[0]); 59345e5710bSMark Peek xclose(pipeout[1]); 594c80476e4SDavid E. O'Brien } 595c80476e4SDavid E. O'Brien if ((t->t_dflg & F_PIPEIN) != 0) 596c80476e4SDavid E. O'Brien break; 597c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 598c80476e4SDavid E. O'Brien if (didfds == 0 && t->t_dflg & F_PIPEIN) { 59945e5710bSMark Peek xclose(pipein[0]); 60045e5710bSMark Peek xclose(pipein[1]); 601c80476e4SDavid E. O'Brien } 602c80476e4SDavid E. O'Brien if ((t->t_dflg & F_PIPEOUT) != 0) 603c80476e4SDavid E. O'Brien break; 604c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 605c80476e4SDavid E. O'Brien 606c80476e4SDavid E. O'Brien if (nosigchld) { 60745e5710bSMark Peek sigprocmask(SIG_SETMASK, &csigset, NULL); 608c80476e4SDavid E. O'Brien nosigchld = 0; 609c80476e4SDavid E. O'Brien } 610c80476e4SDavid E. O'Brien if ((t->t_dflg & F_AMPERSAND) == 0) 611c80476e4SDavid E. O'Brien pwait(); 612c80476e4SDavid E. O'Brien break; 613c80476e4SDavid E. O'Brien } 614c80476e4SDavid E. O'Brien 615c80476e4SDavid E. O'Brien doio(t, pipein, pipeout); 616c80476e4SDavid E. O'Brien #ifdef BACKPIPE 617c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEIN) { 61845e5710bSMark Peek xclose(pipein[0]); 61945e5710bSMark Peek xclose(pipein[1]); 620c80476e4SDavid E. O'Brien } 621c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 622c80476e4SDavid E. O'Brien if (t->t_dflg & F_PIPEOUT) { 62345e5710bSMark Peek xclose(pipeout[0]); 62445e5710bSMark Peek xclose(pipeout[1]); 625c80476e4SDavid E. O'Brien } 626c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 627c80476e4SDavid E. O'Brien /* 628c80476e4SDavid E. O'Brien * Perform a builtin function. If we are not forked, arrange for 629c80476e4SDavid E. O'Brien * possible stopping 630c80476e4SDavid E. O'Brien */ 631c80476e4SDavid E. O'Brien if (bifunc) { 632c80476e4SDavid E. O'Brien func(t, bifunc); 633c80476e4SDavid E. O'Brien if (forked) 634c80476e4SDavid E. O'Brien exitstat(); 63523338178SMark Peek else { 63623338178SMark Peek if (adrof(STRprintexitvalue)) { 63723338178SMark Peek int rv = getn(varval(STRstatus)); 63823338178SMark Peek if (rv != 0) 63923338178SMark Peek xprintf(CGETS(17, 2, "Exit %d\n"), rv); 64023338178SMark Peek } 64123338178SMark Peek } 642c80476e4SDavid E. O'Brien break; 643c80476e4SDavid E. O'Brien } 644c80476e4SDavid E. O'Brien if (t->t_dtyp != NODE_PAREN) { 64529301572SMark Peek doexec(t, do_glob); 646c80476e4SDavid E. O'Brien /* NOTREACHED */ 647c80476e4SDavid E. O'Brien } 648c80476e4SDavid E. O'Brien /* 649c80476e4SDavid E. O'Brien * For () commands must put new 0,1,2 in FSH* and recurse 650c80476e4SDavid E. O'Brien */ 65123338178SMark Peek (void)close_on_exec(OLDSTD = dcopy(0, FOLDSTD), 1); 65223338178SMark Peek (void)close_on_exec(SHOUT = dcopy(1, FSHOUT), 1); 653c80476e4SDavid E. O'Brien isoutatty = isatty(SHOUT); 65423338178SMark Peek (void)close_on_exec(SHDIAG = dcopy(2, FSHDIAG), 1); 655c80476e4SDavid E. O'Brien isdiagatty = isatty(SHDIAG); 65645e5710bSMark Peek xclose(SHIN); 657c80476e4SDavid E. O'Brien SHIN = -1; 658c80476e4SDavid E. O'Brien #ifndef CLOSE_ON_EXEC 659c80476e4SDavid E. O'Brien didcch = 0; 66023338178SMark Peek #else 66123338178SMark Peek (void) close_on_exec(FSHOUT, 1); 66223338178SMark Peek (void) close_on_exec(FSHDIAG, 1); 66323338178SMark Peek (void) close_on_exec(FOLDSTD, 1); 664c80476e4SDavid E. O'Brien #endif /* !CLOSE_ON_EXEC */ 665c80476e4SDavid E. O'Brien didfds = 0; 666c80476e4SDavid E. O'Brien wanttty = -1; 667c80476e4SDavid E. O'Brien t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 66829301572SMark Peek execute(t->t_dspr, wanttty, NULL, NULL, do_glob); 669c80476e4SDavid E. O'Brien exitstat(); 670c80476e4SDavid E. O'Brien 671c80476e4SDavid E. O'Brien case NODE_PIPE: 672c80476e4SDavid E. O'Brien #ifdef BACKPIPE 673c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 674c80476e4SDavid E. O'Brien (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 67529301572SMark Peek execute(t->t_dcdr, wanttty, pv, pipeout, do_glob); 676c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= F_PIPEOUT | 677c80476e4SDavid E. O'Brien (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 67829301572SMark Peek execute(t->t_dcar, wanttty, pipein, pv, do_glob); 679c80476e4SDavid E. O'Brien #else /* !BACKPIPE */ 680c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= F_PIPEOUT | 681c80476e4SDavid E. O'Brien (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 68229301572SMark Peek execute(t->t_dcar, wanttty, pipein, pv, do_glob); 683c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 684c80476e4SDavid E. O'Brien (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 68529301572SMark Peek execute(t->t_dcdr, wanttty, pv, pipeout, do_glob); 686c80476e4SDavid E. O'Brien #endif /* BACKPIPE */ 687c80476e4SDavid E. O'Brien break; 688c80476e4SDavid E. O'Brien 689c80476e4SDavid E. O'Brien case NODE_LIST: 690c80476e4SDavid E. O'Brien if (t->t_dcar) { 691c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 69229301572SMark Peek execute(t->t_dcar, wanttty, NULL, NULL, do_glob); 693c80476e4SDavid E. O'Brien /* 694c80476e4SDavid E. O'Brien * In strange case of A&B make a new job after A 695c80476e4SDavid E. O'Brien */ 696c80476e4SDavid E. O'Brien if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 697c80476e4SDavid E. O'Brien (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 698c80476e4SDavid E. O'Brien pendjob(); 699c80476e4SDavid E. O'Brien } 700c80476e4SDavid E. O'Brien if (t->t_dcdr) { 701c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= t->t_dflg & 702c80476e4SDavid E. O'Brien (F_NOFORK | F_NOINTERRUPT); 70329301572SMark Peek execute(t->t_dcdr, wanttty, NULL, NULL, do_glob); 704c80476e4SDavid E. O'Brien } 705c80476e4SDavid E. O'Brien break; 706c80476e4SDavid E. O'Brien 707c80476e4SDavid E. O'Brien case NODE_OR: 708c80476e4SDavid E. O'Brien case NODE_AND: 709c80476e4SDavid E. O'Brien if (t->t_dcar) { 710c80476e4SDavid E. O'Brien t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 71129301572SMark Peek execute(t->t_dcar, wanttty, NULL, NULL, do_glob); 712c80476e4SDavid E. O'Brien if ((getn(varval(STRstatus)) == 0) != 713c80476e4SDavid E. O'Brien (t->t_dtyp == NODE_AND)) { 714c80476e4SDavid E. O'Brien return; 715c80476e4SDavid E. O'Brien } 716c80476e4SDavid E. O'Brien } 717c80476e4SDavid E. O'Brien if (t->t_dcdr) { 718c80476e4SDavid E. O'Brien t->t_dcdr->t_dflg |= t->t_dflg & 719c80476e4SDavid E. O'Brien (F_NOFORK | F_NOINTERRUPT); 72029301572SMark Peek execute(t->t_dcdr, wanttty, NULL, NULL, do_glob); 721c80476e4SDavid E. O'Brien } 722c80476e4SDavid E. O'Brien break; 723c80476e4SDavid E. O'Brien 724c80476e4SDavid E. O'Brien default: 725c80476e4SDavid E. O'Brien break; 726c80476e4SDavid E. O'Brien } 727c80476e4SDavid E. O'Brien /* 728c80476e4SDavid E. O'Brien * Fall through for all breaks from switch 729c80476e4SDavid E. O'Brien * 730c80476e4SDavid E. O'Brien * If there will be no more executions of this command, flush all file 731c80476e4SDavid E. O'Brien * descriptors. Places that turn on the F_REPEAT bit are responsible for 732c80476e4SDavid E. O'Brien * doing donefds after the last re-execution 733c80476e4SDavid E. O'Brien */ 734c80476e4SDavid E. O'Brien if (didfds && !(t->t_dflg & F_REPEAT)) 735c80476e4SDavid E. O'Brien donefds(); 736c80476e4SDavid E. O'Brien } 737c80476e4SDavid E. O'Brien 738c80476e4SDavid E. O'Brien #ifdef VFORK 73945e5710bSMark Peek static void 740c80476e4SDavid E. O'Brien /*ARGSUSED*/ 74145e5710bSMark Peek vffree(int snum) 742c80476e4SDavid E. O'Brien { 743c80476e4SDavid E. O'Brien USE(snum); 744c80476e4SDavid E. O'Brien 745c80476e4SDavid E. O'Brien _exit(1); 746c80476e4SDavid E. O'Brien } 747c80476e4SDavid E. O'Brien #endif /* VFORK */ 748c80476e4SDavid E. O'Brien 749c80476e4SDavid E. O'Brien /* 750c80476e4SDavid E. O'Brien * Expand and glob the words after an i/o redirection. 751c80476e4SDavid E. O'Brien * If more than one word is generated, then update the command vector. 752c80476e4SDavid E. O'Brien * 753c80476e4SDavid E. O'Brien * This is done differently in all the shells: 754c80476e4SDavid E. O'Brien * 1. in the bourne shell and ksh globbing is not performed 755c80476e4SDavid E. O'Brien * 2. Bash/csh say ambiguous 756c80476e4SDavid E. O'Brien * 3. zsh does i/o to/from all the files 757c80476e4SDavid E. O'Brien * 4. itcsh concatenates the words. 758c80476e4SDavid E. O'Brien * 759c80476e4SDavid E. O'Brien * I don't know what is best to do. I think that Ambiguous is better 760c80476e4SDavid E. O'Brien * than restructuring the command vector, because the user can get 761c80476e4SDavid E. O'Brien * unexpected results. In any case, the command vector restructuring 762c80476e4SDavid E. O'Brien * code is present and the user can choose it by setting noambiguous 763c80476e4SDavid E. O'Brien */ 764c80476e4SDavid E. O'Brien static Char * 76545e5710bSMark Peek splicepipe(struct command *t, Char *cp) 766c80476e4SDavid E. O'Brien { 767c80476e4SDavid E. O'Brien Char *blk[2]; 768c80476e4SDavid E. O'Brien 769c80476e4SDavid E. O'Brien if (adrof(STRnoambiguous)) { 770c80476e4SDavid E. O'Brien Char **pv; 77145e5710bSMark Peek int gflag; 772c80476e4SDavid E. O'Brien 773c80476e4SDavid E. O'Brien blk[0] = Dfix1(cp); /* expand $ */ 774c80476e4SDavid E. O'Brien blk[1] = NULL; 775c80476e4SDavid E. O'Brien 77645e5710bSMark Peek gflag = tglob(blk); 777c80476e4SDavid E. O'Brien if (gflag) { 77845e5710bSMark Peek pv = globall(blk, gflag); 779c80476e4SDavid E. O'Brien if (pv == NULL) { 780c80476e4SDavid E. O'Brien setname(short2str(blk[0])); 78145e5710bSMark Peek xfree(blk[0]); 782c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_NOMATCH); 783c80476e4SDavid E. O'Brien } 784c80476e4SDavid E. O'Brien if (pv[1] != NULL) { /* we need to fix the command vector */ 785c80476e4SDavid E. O'Brien Char **av = blkspl(t->t_dcom, &pv[1]); 78645e5710bSMark Peek xfree(t->t_dcom); 787c80476e4SDavid E. O'Brien t->t_dcom = av; 788c80476e4SDavid E. O'Brien } 78945e5710bSMark Peek xfree(blk[0]); 790c80476e4SDavid E. O'Brien blk[0] = pv[0]; 79145e5710bSMark Peek xfree(pv); 792c80476e4SDavid E. O'Brien } 793c80476e4SDavid E. O'Brien } 794c80476e4SDavid E. O'Brien else { 79545e5710bSMark Peek Char *buf; 796c80476e4SDavid E. O'Brien 79745e5710bSMark Peek buf = Dfix1(cp); 79845e5710bSMark Peek cleanup_push(buf, xfree); 799c80476e4SDavid E. O'Brien blk[0] = globone(buf, G_ERROR); 80045e5710bSMark Peek cleanup_until(buf); 801c80476e4SDavid E. O'Brien } 802c80476e4SDavid E. O'Brien return(blk[0]); 803c80476e4SDavid E. O'Brien } 804c80476e4SDavid E. O'Brien 805c80476e4SDavid E. O'Brien /* 806c80476e4SDavid E. O'Brien * Perform io redirection. 807c80476e4SDavid E. O'Brien * We may or maynot be forked here. 808c80476e4SDavid E. O'Brien */ 809c80476e4SDavid E. O'Brien static void 81045e5710bSMark Peek doio(struct command *t, int *pipein, int *pipeout) 811c80476e4SDavid E. O'Brien { 81223338178SMark Peek int fd; 81323338178SMark Peek Char *cp; 81423338178SMark Peek unsigned long flags = t->t_dflg; 815c80476e4SDavid E. O'Brien 816c80476e4SDavid E. O'Brien if (didfds || (flags & F_REPEAT)) 817c80476e4SDavid E. O'Brien return; 818c80476e4SDavid E. O'Brien if ((flags & F_READ) == 0) {/* F_READ already done */ 819c80476e4SDavid E. O'Brien if (t->t_dlef) { 82045e5710bSMark Peek char *tmp; 821c80476e4SDavid E. O'Brien 822c80476e4SDavid E. O'Brien /* 823c80476e4SDavid E. O'Brien * so < /dev/std{in,out,err} work 824c80476e4SDavid E. O'Brien */ 825c80476e4SDavid E. O'Brien (void) dcopy(SHIN, 0); 826c80476e4SDavid E. O'Brien (void) dcopy(SHOUT, 1); 827c80476e4SDavid E. O'Brien (void) dcopy(SHDIAG, 2); 828c80476e4SDavid E. O'Brien cp = splicepipe(t, t->t_dlef); 82945e5710bSMark Peek tmp = strsave(short2str(cp)); 83045e5710bSMark Peek xfree(cp); 83145e5710bSMark Peek cleanup_push(tmp, xfree); 83245e5710bSMark Peek if ((fd = xopen(tmp, O_RDONLY|O_LARGEFILE)) < 0) 833c80476e4SDavid E. O'Brien stderror(ERR_SYSTEM, tmp, strerror(errno)); 83445e5710bSMark Peek cleanup_until(tmp); 835c80476e4SDavid E. O'Brien /* allow input files larger than 2Gb */ 836b2d5d167SMark Peek #ifndef WINNT_NATIVE 83723338178SMark Peek (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); 838b2d5d167SMark Peek #endif /*!WINNT_NATIVE*/ 839c80476e4SDavid E. O'Brien (void) dmove(fd, 0); 840c80476e4SDavid E. O'Brien } 841c80476e4SDavid E. O'Brien else if (flags & F_PIPEIN) { 84245e5710bSMark Peek xclose(0); 843a15e6f9aSMark Peek IGNORE(dup(pipein[0])); 84445e5710bSMark Peek xclose(pipein[0]); 84545e5710bSMark Peek xclose(pipein[1]); 846c80476e4SDavid E. O'Brien } 847c80476e4SDavid E. O'Brien else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 84845e5710bSMark Peek xclose(0); 84945e5710bSMark Peek (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 850c80476e4SDavid E. O'Brien } 851c80476e4SDavid E. O'Brien else { 85245e5710bSMark Peek xclose(0); 853a15e6f9aSMark Peek IGNORE(dup(OLDSTD)); 854c80476e4SDavid E. O'Brien #if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 855c80476e4SDavid E. O'Brien /* 856c80476e4SDavid E. O'Brien * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved 857c80476e4SDavid E. O'Brien * across dup()s, so we have to UNSET it here or else we get a 858c80476e4SDavid E. O'Brien * command with NO stdin, stdout, or stderr at all (a bad thing 859c80476e4SDavid E. O'Brien * indeed) 860c80476e4SDavid E. O'Brien */ 861c80476e4SDavid E. O'Brien (void) close_on_exec(0, 0); 862c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 863c80476e4SDavid E. O'Brien } 864c80476e4SDavid E. O'Brien } 865c80476e4SDavid E. O'Brien if (t->t_drit) { 86645e5710bSMark Peek char *tmp; 867c80476e4SDavid E. O'Brien 868c80476e4SDavid E. O'Brien cp = splicepipe(t, t->t_drit); 86945e5710bSMark Peek tmp = strsave(short2str(cp)); 87045e5710bSMark Peek xfree(cp); 87145e5710bSMark Peek cleanup_push(tmp, xfree); 872c80476e4SDavid E. O'Brien /* 873c80476e4SDavid E. O'Brien * so > /dev/std{out,err} work 874c80476e4SDavid E. O'Brien */ 875c80476e4SDavid E. O'Brien (void) dcopy(SHOUT, 1); 876c80476e4SDavid E. O'Brien (void) dcopy(SHDIAG, 2); 877c80476e4SDavid E. O'Brien if ((flags & F_APPEND) != 0) { 878c80476e4SDavid E. O'Brien #ifdef O_APPEND 87945e5710bSMark Peek fd = xopen(tmp, O_WRONLY|O_APPEND|O_LARGEFILE); 880c80476e4SDavid E. O'Brien #else /* !O_APPEND */ 88145e5710bSMark Peek fd = xopen(tmp, O_WRONLY|O_LARGEFILE); 882c80476e4SDavid E. O'Brien (void) lseek(fd, (off_t) 0, L_XTND); 883c80476e4SDavid E. O'Brien #endif /* O_APPEND */ 884c80476e4SDavid E. O'Brien } 885c80476e4SDavid E. O'Brien else 886c80476e4SDavid E. O'Brien fd = 0; 887c80476e4SDavid E. O'Brien if ((flags & F_APPEND) == 0 || fd == -1) { 888c80476e4SDavid E. O'Brien if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 889c80476e4SDavid E. O'Brien if (flags & F_APPEND) 890c80476e4SDavid E. O'Brien stderror(ERR_SYSTEM, tmp, strerror(errno)); 891c80476e4SDavid E. O'Brien chkclob(tmp); 892c80476e4SDavid E. O'Brien } 89345e5710bSMark Peek if ((fd = xcreat(tmp, 0666)) < 0) 894c80476e4SDavid E. O'Brien stderror(ERR_SYSTEM, tmp, strerror(errno)); 895c80476e4SDavid E. O'Brien /* allow input files larger than 2Gb */ 896b2d5d167SMark Peek #ifndef WINNT_NATIVE 89723338178SMark Peek (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); 898b2d5d167SMark Peek #endif /*!WINNT_NATIVE*/ 899c80476e4SDavid E. O'Brien } 90045e5710bSMark Peek cleanup_until(tmp); 901c80476e4SDavid E. O'Brien (void) dmove(fd, 1); 902c80476e4SDavid E. O'Brien is1atty = isatty(1); 903c80476e4SDavid E. O'Brien } 904c80476e4SDavid E. O'Brien else if (flags & F_PIPEOUT) { 90545e5710bSMark Peek xclose(1); 906a15e6f9aSMark Peek IGNORE(dup(pipeout[1])); 907c80476e4SDavid E. O'Brien is1atty = 0; 908c80476e4SDavid E. O'Brien } 909c80476e4SDavid E. O'Brien else { 91045e5710bSMark Peek xclose(1); 911a15e6f9aSMark Peek IGNORE(dup(SHOUT)); 912c80476e4SDavid E. O'Brien is1atty = isoutatty; 913c80476e4SDavid E. O'Brien # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 914c80476e4SDavid E. O'Brien (void) close_on_exec(1, 0); 915c80476e4SDavid E. O'Brien # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 916c80476e4SDavid E. O'Brien } 917c80476e4SDavid E. O'Brien 91845e5710bSMark Peek xclose(2); 919c80476e4SDavid E. O'Brien if (flags & F_STDERR) { 920a15e6f9aSMark Peek IGNORE(dup(1)); 921c80476e4SDavid E. O'Brien is2atty = is1atty; 922c80476e4SDavid E. O'Brien } 923c80476e4SDavid E. O'Brien else { 924a15e6f9aSMark Peek IGNORE(dup(SHDIAG)); 925c80476e4SDavid E. O'Brien is2atty = isdiagatty; 926c80476e4SDavid E. O'Brien # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 927c80476e4SDavid E. O'Brien (void) close_on_exec(2, 0); 928c80476e4SDavid E. O'Brien # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 929c80476e4SDavid E. O'Brien } 930c80476e4SDavid E. O'Brien didfds = 1; 931c80476e4SDavid E. O'Brien } 932c80476e4SDavid E. O'Brien 933c80476e4SDavid E. O'Brien void 93445e5710bSMark Peek mypipe(int *pv) 935c80476e4SDavid E. O'Brien { 936c80476e4SDavid E. O'Brien 937c80476e4SDavid E. O'Brien if (pipe(pv) < 0) 938c80476e4SDavid E. O'Brien goto oops; 93923338178SMark Peek (void)close_on_exec(pv[0] = dmove(pv[0], -1), 1); 94023338178SMark Peek (void)close_on_exec(pv[1] = dmove(pv[1], -1), 1); 941c80476e4SDavid E. O'Brien if (pv[0] >= 0 && pv[1] >= 0) 942c80476e4SDavid E. O'Brien return; 94345e5710bSMark Peek if (pv[0] >= 0) 94445e5710bSMark Peek xclose(pv[0]); 94545e5710bSMark Peek if (pv[1] >= 0) 94645e5710bSMark Peek xclose(pv[1]); 947c80476e4SDavid E. O'Brien oops: 948c80476e4SDavid E. O'Brien stderror(ERR_PIPE); 949c80476e4SDavid E. O'Brien } 950c80476e4SDavid E. O'Brien 951c80476e4SDavid E. O'Brien static void 95245e5710bSMark Peek chkclob(const char *cp) 953c80476e4SDavid E. O'Brien { 954c80476e4SDavid E. O'Brien struct stat stb; 955c80476e4SDavid E. O'Brien 956c80476e4SDavid E. O'Brien if (stat(cp, &stb) < 0) 957c80476e4SDavid E. O'Brien return; 958c80476e4SDavid E. O'Brien if (S_ISCHR(stb.st_mode)) 959c80476e4SDavid E. O'Brien return; 960c80476e4SDavid E. O'Brien stderror(ERR_EXISTS, cp); 961c80476e4SDavid E. O'Brien } 962