1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.sem.c,v 3.0 1991/07/04 23:34:26 christos Exp $ */ 2: /* 3: * sh.sem.c: I/O redirections and job forking. A touchy issue! 4: * Most stuff with builtins is incorrect 5: */ 6: /*- 7: * Copyright (c) 1980, 1991 The Regents of the University of California. 8: * All rights reserved. 9: * 10: * Redistribution and use in source and binary forms, with or without 11: * modification, are permitted provided that the following conditions 12: * are met: 13: * 1. Redistributions of source code must retain the above copyright 14: * notice, this list of conditions and the following disclaimer. 15: * 2. Redistributions in binary form must reproduce the above copyright 16: * notice, this list of conditions and the following disclaimer in the 17: * documentation and/or other materials provided with the distribution. 18: * 3. All advertising materials mentioning features or use of this software 19: * must display the following acknowledgement: 20: * This product includes software developed by the University of 21: * California, Berkeley and its contributors. 22: * 4. Neither the name of the University nor the names of its contributors 23: * may be used to endorse or promote products derived from this software 24: * without specific prior written permission. 25: * 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36: * SUCH DAMAGE. 37: */ 38: #include "config.h" 39: #if !defined(lint) && !defined(pdp11) 40: static char *rcsid() 41: { return "$Id: sh.sem.c,v 3.0 1991/07/04 23:34:26 christos Exp $"; } 42: #endif 43: 44: #include "sh.h" 45: 46: #ifdef FIOCLEX 47: #ifndef sun 48: #ifndef CLEX_DUPS 49: #define CLEX_DUPS 50: #endif /* CLEX_DUPS */ 51: #endif /* sun */ 52: #endif /* FIOCLEX */ 53: 54: #ifdef sparc 55: #include <vfork.h> 56: #endif /* sparc */ 57: 58: #ifdef VFORK 59: static sigret_t vffree __P((int)); 60: #endif 61: static void doio __P((struct command *t, int *, int *)); 62: static void chkclob __P((char *)); 63: 64: /* 65: * C shell 66: */ 67: /*VARARGS 1*/ 68: void 69: execute(t, wanttty, pipein, pipeout) 70: register struct command *t; 71: int wanttty, *pipein, *pipeout; 72: { 73: #if defined(convex) || defined(__convex__) 74: extern bool use_fork; /* use fork() instead of vfork()? */ 75: 76: #endif 77: 78: bool forked = 0; 79: struct biltins *bifunc; 80: int pid = 0; 81: int pv[2]; 82: 83: #ifdef BSDSIGS 84: static sigmask_t csigmask; 85: # ifdef VFORK 86: static sigmask_t ocsigmask; 87: # endif /* VFORK */ 88: #endif /* BSDSIGS */ 89: #ifdef VFORK 90: static int onosigchld = 0; 91: #endif /* VFORK */ 92: static int nosigchld = 0; 93: 94: if (t == 0) 95: return; 96: /* 97: * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 98: * Don't check for wantty > 0... 99: */ 100: if (t->t_dflg & F_AMPERSAND) 101: wanttty = 0; 102: switch (t->t_dtyp) { 103: 104: case NODE_COMMAND: 105: if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 106: (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 107: if ((t->t_dflg & F_REPEAT) == 0) 108: Dfix(t); /* $ " ' \ */ 109: if (t->t_dcom[0] == 0) 110: return; 111: /* fall into... */ 112: 113: case NODE_PAREN: 114: if (t->t_dflg & F_PIPEOUT) 115: mypipe(pipeout); 116: /* 117: * Must do << early so parent will know where input pointer should be. 118: * If noexec then this is all we do. 119: */ 120: if (t->t_dflg & F_READ) { 121: (void) close(0); 122: heredoc(t->t_dlef); 123: if (noexec) 124: (void) close(0); 125: } 126: if (noexec) 127: break; 128: 129: set(STRstatus, Strsave(STR0)); 130: 131: /* 132: * This mess is the necessary kludge to handle the prefix builtins: 133: * nice, nohup, time. These commands can also be used by themselves, 134: * and this is not handled here. This will also work when loops are 135: * parsed. 136: */ 137: while (t->t_dtyp == NODE_COMMAND) 138: if (eq(t->t_dcom[0], STRnice)) 139: if (t->t_dcom[1]) 140: if (strchr("+-", t->t_dcom[1][0])) 141: if (t->t_dcom[2]) { 142: setname("nice"); 143: t->t_nice = 144: getn(t->t_dcom[1]); 145: lshift(t->t_dcom, 2); 146: t->t_dflg |= F_NICE; 147: } 148: else 149: break; 150: else { 151: t->t_nice = 4; 152: lshift(t->t_dcom, 1); 153: t->t_dflg |= F_NICE; 154: } 155: else 156: break; 157: else if (eq(t->t_dcom[0], STRnohup)) 158: if (t->t_dcom[1]) { 159: t->t_dflg |= F_NOHUP; 160: lshift(t->t_dcom, 1); 161: } 162: else 163: break; 164: else if (eq(t->t_dcom[0], STRtime)) 165: if (t->t_dcom[1]) { 166: t->t_dflg |= F_TIME; 167: lshift(t->t_dcom, 1); 168: } 169: else 170: break; 171: #ifdef F_VER 172: else if (eq(t->t_dcom[0], STRver)) 173: if (t->t_dcom[1] && t->t_dcom[2]) { 174: setname("ver"); 175: t->t_systype = getv(t->t_dcom[1]); 176: lshift(t->t_dcom, 2); 177: t->t_dflg |= F_VER; 178: } 179: else 180: break; 181: #endif 182: else 183: break; 184: 185: /* is t a command */ 186: if (t->t_dtyp == NODE_COMMAND) { 187: /* 188: * Check if we have a builtin function and remember which one. 189: */ 190: bifunc = isbfunc(t); 191: } 192: else { /* not a command */ 193: bifunc = NULL; 194: } 195: 196: /* 197: * We fork only if we are timed, or are not the end of a parenthesized 198: * list and not a simple builtin function. Simple meaning one that is 199: * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 200: * fork in some of these cases. 201: */ 202: /* 203: * Prevent forking cd, pushd, popd, chdir cause this will cause the 204: * shell not to change dir! 205: */ 206: if (bifunc && (bifunc->bfunct == dochngd || 207: bifunc->bfunct == dopushd || 208: bifunc->bfunct == dopopd)) 209: t->t_dflg &= ~(F_NICE); 210: if (((t->t_dflg & F_TIME) || (t->t_dflg & F_NOFORK) == 0 && 211: (!bifunc || t->t_dflg & 212: (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP))) || 213: /* 214: * We have to fork for eval too. 215: */ 216: (bifunc && (t->t_dflg & F_PIPEIN) != 0 && 217: bifunc->bfunct == doeval)) 218: #ifdef VFORK 219: if (t->t_dtyp == NODE_PAREN || 220: t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) 221: #endif 222: { 223: forked++; 224: /* 225: * We need to block SIGCHLD here, so that if the process does 226: * not die before we can set the process group 227: */ 228: if (wanttty >= 0 && !nosigchld) { 229: #ifdef BSDSIGS 230: csigmask = sigblock(sigmask(SIGCHLD)); 231: #else 232: sighold(SIGCHLD); 233: #endif /* BSDSIGS */ 234: 235: nosigchld = 1; 236: } 237: 238: pid = pfork(t, wanttty); 239: if (pid == 0 && nosigchld) { 240: #ifdef BSDSIGS 241: (void) sigsetmask(csigmask); 242: #else 243: (void) sigrelse(SIGCHLD); 244: #endif /* BSDSIGS */ 245: nosigchld = 0; 246: } 247: } 248: 249: #ifdef VFORK 250: else { 251: int ochild, osetintr, ohaderr, odidfds; 252: int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; 253: int oisoutatty, oisdiagatty; 254: 255: #ifndef FIOCLEX 256: int odidcch; 257: 258: #endif 259: #ifdef BSDSIGS 260: sigmask_t omask; 261: #endif /* BSDSIGS */ 262: 263: /* 264: * Prepare for the vfork by saving everything that the child 265: * corrupts before it exec's. Note that in some signal 266: * implementations which keep the signal info in user space 267: * (e.g. Sun's) it will also be necessary to save and restore 268: * the current sigvec's for the signals the child touches 269: * before it exec's. 270: */ 271: #ifdef BSDSIGS 272: 273: /* 274: * Sooooo true... If this is a Sun, save the sigvec's. (Skip 275: * Gilbrech - 11/22/87) 276: */ 277: #ifdef SAVESIGVEC 278: sigvec_t savesv[NSIGSAVED]; 279: sigmask_t savesm; 280: 281: #endif /* SAVESIGVEC */ 282: if (wanttty >= 0 && !nosigchld && !noexec) { 283: #ifdef BSDSIGS 284: csigmask = sigblock(sigmask(SIGCHLD)); 285: #else 286: sighold(SIGCHLD); 287: #endif /* BSDSIGS */ 288: nosigchld = 1; 289: } 290: omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT)); 291: #else 292: (void) sighold(SIGCHLD); 293: (void) sighold(SIGINT); 294: #endif 295: ochild = child; 296: osetintr = setintr; 297: ohaderr = haderr; 298: odidfds = didfds; 299: #ifndef FIOCLEX 300: odidcch = didcch; 301: #endif 302: oSHIN = SHIN; 303: oSHOUT = SHOUT; 304: oSHDIAG = SHDIAG; 305: oOLDSTD = OLDSTD; 306: otpgrp = tpgrp; 307: oisoutatty = isoutatty; 308: oisdiagatty = isdiagatty; 309: #ifdef BSDSIGS 310: ocsigmask = csigmask; 311: #endif /* BSDSIGS */ 312: onosigchld = nosigchld; 313: Vsav = Vdp = 0; 314: Vexpath = 0; 315: Vt = 0; 316: #ifdef SAVESIGVEC 317: savesm = savesigvec(savesv); 318: #endif /* SAVESIGVEC */ 319: #if defined(convex) || defined(__convex__) 320: if (use_fork) 321: pid = fork(); 322: else 323: pid = vfork(); 324: #else 325: pid = vfork(); 326: #endif 327: 328: if (pid < 0) { 329: #ifdef BSDSIGS 330: #ifdef SAVESIGVEC 331: restoresigvec(savesv, savesm); 332: #endif /* SAVESIGVEC */ 333: (void) sigsetmask(omask); 334: #else 335: (void) sigrelse(SIGCHLD); 336: (void) sigrelse(SIGINT); 337: #endif 338: stderror(ERR_NOPROC); 339: } 340: forked++; 341: if (pid) { /* parent */ 342: #ifdef pdp11 343: register char **v; 344: #endif 345: #ifdef BSDSIGS 346: #ifdef SAVESIGVEC 347: restoresigvec(savesv, savesm); 348: #endif /* SAVESIGVEC */ 349: #endif /* BSDSIGS */ 350: child = ochild; 351: setintr = osetintr; 352: haderr = ohaderr; 353: didfds = odidfds; 354: SHIN = oSHIN; 355: #ifndef FIOCLEX 356: didcch = odidcch; 357: #endif 358: SHOUT = oSHOUT; 359: SHDIAG = oSHDIAG; 360: OLDSTD = oOLDSTD; 361: tpgrp = otpgrp; 362: isoutatty = oisoutatty; 363: isdiagatty = oisdiagatty; 364: #ifdef BSDSIGS 365: csigmask = ocsigmask; 366: #endif /* BSDSIGS */ 367: nosigchld = onosigchld; 368: 369: xfree((ptr_t) Vsav); 370: Vsav = 0; 371: xfree((ptr_t) Vdp); 372: Vdp = 0; 373: xfree((ptr_t) Vexpath); 374: Vexpath = 0; 375: blkfree((Char **) Vt); 376: Vt = 0; 377: #ifdef pdp11 378: if (v = gargv) 379: gargv = 0, blkfree(v); 380: if (v = pargv) 381: pargv = 0, blkfree(v); 382: #endif 383: /* this is from pfork() */ 384: palloc(pid, t); 385: #ifdef BSDSIGS 386: (void) sigsetmask(omask); 387: #else 388: (void) sigrelse(SIGCHLD); 389: (void) sigrelse(SIGINT); 390: #endif 391: } 392: else { /* child */ 393: /* this is from pfork() */ 394: int pgrp; 395: bool ignint = 0; 396: 397: if (nosigchld) { 398: #ifdef BSDSIGS 399: (void) sigsetmask(csigmask); 400: #else 401: (void) sigrelse(SIGCHLD); 402: #endif /* BSDSIGS */ 403: nosigchld = 0; 404: } 405: 406: if (setintr) 407: ignint = 408: (tpgrp == -1 && 409: (t->t_dflg & F_NOINTERRUPT)) 410: || gointr && eq(gointr, STRminus); 411: pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 412: child++; 413: if (setintr) { 414: setintr = 0; 415: #ifdef notdef 416: (void) signal(SIGCHLD, SIG_DFL); 417: #endif 418: /* 419: * casts made right for SunOS 4.0 by Douglas C. Schmidt 420: * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU> 421: * (thanks! -- PWP) 422: * 423: * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET> 424: * (thanks again) 425: */ 426: if (ignint) { 427: (void) signal(SIGINT, SIG_IGN); 428: (void) signal(SIGQUIT, SIG_IGN); 429: } 430: else { 431: (void) signal(SIGINT, vffree); 432: (void) signal(SIGQUIT, SIG_DFL); 433: } 434: 435: if (wanttty >= 0) { 436: (void) signal(SIGTSTP, SIG_DFL); 437: (void) signal(SIGTTIN, SIG_DFL); 438: (void) signal(SIGTTOU, SIG_DFL); 439: } 440: 441: (void) signal(SIGTERM, parterm); 442: } 443: else if (tpgrp == -1 && 444: (t->t_dflg & F_NOINTERRUPT)) { 445: (void) signal(SIGINT, SIG_IGN); 446: (void) signal(SIGQUIT, SIG_IGN); 447: } 448: 449: #ifdef _SEQUENT_ 450: pgetty(wanttty ? wanttty : 1, pgrp); 451: #else /* _SEQUENT_ */ 452: pgetty(wanttty, pgrp); 453: #endif /* _SEQUENT_ */ 454: 455: if (t->t_dflg & F_NOHUP) 456: (void) signal(SIGHUP, SIG_IGN); 457: if (t->t_dflg & F_NICE) 458: #ifdef BSDNICE 459: (void) setpriority(PRIO_PROCESS, 460: 0, t->t_nice); 461: #else /* BSDNICE */ 462: (void) nice(t->t_nice); 463: #endif /* BSDNICE */ 464: #ifdef F_VER 465: if (t->t_dflg & F_VER) { 466: Setenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53); 467: dohash(); 468: } 469: #endif 470: } 471: 472: } 473: #endif /* VFORK */ 474: if (pid != 0) { 475: /* 476: * It would be better if we could wait for the whole job when we 477: * knew the last process had been started. Pwait, in fact, does 478: * wait for the whole job anyway, but this test doesn't really 479: * express our intentions. 480: */ 481: if (didfds == 0 && t->t_dflg & F_PIPEIN) { 482: (void) close(pipein[0]); 483: (void) close(pipein[1]); 484: } 485: if ((t->t_dflg & F_PIPEOUT) == 0) { 486: if (nosigchld) { 487: #ifdef BSDSIGS 488: (void) sigsetmask(csigmask); 489: #else 490: (void) sigrelse(SIGCHLD); 491: #endif /* BSDSIGS */ 492: nosigchld = 0; 493: } 494: if ((t->t_dflg & F_AMPERSAND) == 0) 495: pwait(); 496: } 497: break; 498: } 499: doio(t, pipein, pipeout); 500: if (t->t_dflg & F_PIPEOUT) { 501: (void) close(pipeout[0]); 502: (void) close(pipeout[1]); 503: } 504: /* 505: * Perform a builtin function. If we are not forked, arrange for 506: * possible stopping 507: */ 508: if (bifunc) { 509: func(t, bifunc); 510: if (forked) 511: exitstat(); 512: break; 513: } 514: if (t->t_dtyp != NODE_PAREN) { 515: doexec(t); 516: /* NOTREACHED */ 517: } 518: /* 519: * For () commands must put new 0,1,2 in FSH* and recurse 520: */ 521: OLDSTD = dcopy(0, FOLDSTD); 522: SHOUT = dcopy(1, FSHOUT); 523: isoutatty = isatty(SHOUT); 524: SHDIAG = dcopy(2, FSHDIAG); 525: isdiagatty = isatty(SHDIAG); 526: (void) close(SHIN); 527: SHIN = -1; 528: #ifndef FIOCLEX 529: didcch = 0; 530: #endif 531: didfds = 0; 532: wanttty = -1; 533: t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; 534: execute(t->t_dspr, wanttty, NULL, NULL); 535: exitstat(); 536: 537: case NODE_PIPE: 538: t->t_dcar->t_dflg |= F_PIPEOUT | 539: (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); 540: execute(t->t_dcar, wanttty, pipein, pv); 541: t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 542: (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); 543: if (wanttty > 0) 544: wanttty = 0; /* got tty already */ 545: execute(t->t_dcdr, wanttty, pv, pipeout); 546: break; 547: 548: case NODE_LIST: 549: if (t->t_dcar) { 550: t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 551: execute(t->t_dcar, wanttty, NULL, NULL); 552: /* 553: * In strange case of A&B make a new job after A 554: */ 555: if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 556: (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 557: pendjob(); 558: } 559: if (t->t_dcdr) { 560: t->t_dcdr->t_dflg |= t->t_dflg & 561: (F_NOFORK | F_NOINTERRUPT); 562: execute(t->t_dcdr, wanttty, NULL, NULL); 563: } 564: break; 565: 566: case NODE_OR: 567: case NODE_AND: 568: if (t->t_dcar) { 569: t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; 570: execute(t->t_dcar, wanttty, NULL, NULL); 571: if ((getn(value(STRstatus)) == 0) != 572: (t->t_dtyp == NODE_AND)) 573: return; 574: } 575: if (t->t_dcdr) { 576: t->t_dcdr->t_dflg |= t->t_dflg & 577: (F_NOFORK | F_NOINTERRUPT); 578: execute(t->t_dcdr, wanttty, NULL, NULL); 579: } 580: break; 581: } 582: /* 583: * Fall through for all breaks from switch 584: * 585: * If there will be no more executions of this command, flush all file 586: * descriptors. Places that turn on the F_REPEAT bit are responsible for 587: * doing donefds after the last re-execution 588: */ 589: if (didfds && !(t->t_dflg & F_REPEAT)) 590: donefds(); 591: } 592: 593: #ifdef VFORK 594: static sigret_t 595: /*ARGSUSED*/ 596: vffree(snum) 597: int snum; 598: { 599: register Char **v; 600: 601: if (v = gargv) { 602: gargv = 0; 603: #ifdef pdp11 604: blkfree(v); 605: #else 606: xfree((ptr_t) v); 607: #endif 608: } 609: if (v = pargv) { 610: pargv = 0; 611: #ifdef pdp11 612: blkfree(v); 613: #else 614: xfree((ptr_t) v); 615: #endif 616: } 617: _exit(1); 618: } 619: 620: #endif 621: 622: /* 623: * Perform io redirection. 624: * We may or maynot be forked here. 625: */ 626: static void 627: doio(t, pipein, pipeout) 628: register struct command *t; 629: int *pipein, *pipeout; 630: { 631: register int fd; 632: register Char *cp, *dp; 633: register int flags = t->t_dflg; 634: 635: if (didfds || (flags & F_REPEAT)) 636: return; 637: if ((flags & F_READ) == 0) {/* F_READ already done */ 638: if (cp = t->t_dlef) { 639: char tmp[MAXPATHLEN+1]; 640: 641: /* 642: * so < /dev/std{in,out,err} work 643: */ 644: (void) dcopy(SHIN, 0); 645: (void) dcopy(SHOUT, 1); 646: (void) dcopy(SHDIAG, 2); 647: cp = globone(dp = Dfix1(cp), G_IGNORE); 648: (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 649: tmp[MAXPATHLEN] = '\0'; 650: xfree((ptr_t) cp); 651: xfree((ptr_t) dp); 652: if ((fd = open(tmp, O_RDONLY)) < 0) 653: stderror(ERR_SYSTEM, tmp, strerror(errno)); 654: (void) dmove(fd, 0); 655: } 656: else if (flags & F_PIPEIN) { 657: (void) close(0); 658: (void) dup(pipein[0]); 659: (void) close(pipein[0]); 660: (void) close(pipein[1]); 661: } 662: else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 663: (void) close(0); 664: (void) open(_PATH_DEVNULL, O_RDONLY); 665: } 666: else { 667: (void) close(0); 668: (void) dup(OLDSTD); 669: #ifdef FIOCLEX 670: #ifdef CLEX_DUPS 671: /* 672: * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved 673: * across dup()s, so we have to UNSET it here or else we get a 674: * command with NO stdin, stdout, or stderr at all (a bad thing 675: * indeed) 676: */ 677: 678: (void) ioctl(0, FIONCLEX, NULL); 679: #endif /* CLEX_DUPS */ 680: #endif /* FIONCLEX */ 681: } 682: } 683: if (cp = t->t_drit) { 684: char tmp[MAXPATHLEN+1]; 685: 686: cp = globone(dp = Dfix1(cp), G_IGNORE); 687: (void) strncpy(tmp, short2str(cp), MAXPATHLEN); 688: tmp[MAXPATHLEN] = '\0'; 689: xfree((ptr_t) dp); 690: xfree((ptr_t) cp); 691: /* 692: * so > /dev/std{out,err} work 693: */ 694: (void) dcopy(SHOUT, 1); 695: (void) dcopy(SHDIAG, 2); 696: if ((flags & F_APPEND) && 697: #ifdef O_APPEND 698: (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); 699: #else 700: (fd = open(tmp, O_WRONLY)) >= 0) 701: (void) lseek(1, (off_t) 0, L_XTND); 702: #endif 703: else { 704: if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { 705: if (flags & F_APPEND) 706: stderror(ERR_SYSTEM, tmp, strerror(errno)); 707: chkclob(tmp); 708: } 709: if ((fd = creat(tmp, 0666)) < 0) 710: stderror(ERR_SYSTEM, tmp, strerror(errno)); 711: } 712: (void) dmove(fd, 1); 713: is1atty = isatty(1); 714: } 715: else if (flags & F_PIPEOUT) { 716: (void) close(1); 717: (void) dup(pipeout[1]); 718: is1atty = 0; 719: } 720: else { 721: (void) close(1); 722: (void) dup(SHOUT); 723: is1atty = isoutatty; 724: #ifdef FIOCLEX 725: #ifdef CLEX_DUPS 726: (void) ioctl(1, FIONCLEX, NULL); 727: #endif /* CLEX_DUPS */ 728: #endif /* FIONCLEX */ 729: } 730: 731: (void) close(2); 732: if (flags & F_STDERR) { 733: (void) dup(1); 734: is2atty = is1atty; 735: } 736: else { 737: (void) dup(SHDIAG); 738: is2atty = isdiagatty; 739: #ifdef FIOCLEX 740: #ifdef CLEX_DUPS 741: (void) ioctl(2, FIONCLEX, NULL); 742: #endif /* CLEX_DUPS */ 743: #endif /* FIONCLEX */ 744: } 745: didfds = 1; 746: } 747: 748: void 749: mypipe(pv) 750: register int *pv; 751: { 752: 753: if (pipe(pv) < 0) 754: goto oops; 755: pv[0] = dmove(pv[0], -1); 756: pv[1] = dmove(pv[1], -1); 757: if (pv[0] >= 0 && pv[1] >= 0) 758: return; 759: oops: 760: stderror(ERR_PIPE); 761: } 762: 763: static void 764: chkclob(cp) 765: register char *cp; 766: { 767: struct stat stb; 768: 769: if (stat(cp, &stb) < 0) 770: return; 771: if ((stb.st_mode & S_IFMT) == S_IFCHR) 772: return; 773: stderror(ERR_EXISTS, cp); 774: }