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: }

Defined functions

chkclob defined in line 763; used 1 times
doio defined in line 626; used 1 times
mypipe defined in line 748; used 3 times
rcsid defined in line 40; never used
vffree defined in line 594; used 1 times

Defined macros

CLEX_DUPS defined in line 49; used 4 times
Last modified: 1991-08-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5164
Valid CSS Valid XHTML 1.0 Strict