# 2.11BSD#431 - /usr/src/bin/tcsh/sh.sem.c

##### Functions

    execute           X
    mypipe            X

##### Macros

    CLEX_DUPS         X

       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

- in line 707

doio defined in line 626; used 1 times

- in line 499

execute defined in line 68; used 20 times

- in line 534, 540-545(2), 551, 562, 570, 578
- in /usr/src/bin/tcsh/sh.exp.c line 621
- in /usr/src/bin/tcsh/sh.func.c line 342
- in /usr/src/bin/tcsh/sh.glob.c line 707
- in /usr/src/bin/tcsh/sh.sem.c line 534, 540-545(2), 551, 562, 570, 578
- in /usr/src/bin/tcsh/tc.func.c line 250, 679
- in /usr/src/bin/tcsh/tc.sched.c line 253

mypipe defined in line 748; used 3 times

- in line 115
- in /usr/src/bin/tcsh/sh.glob.c line 670
- in /usr/src/bin/tcsh/sh.sem.c line 115

rcsid defined in line 40; never used
vffree defined in line 594; used 1 times

- in line 431

#### Defined macros

CLEX_DUPS defined in line 49; used 4 times

- in line 48, 670, 725, 740

Last modified: 1991-08-30 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1746 |