1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley Software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: static char *sccsid = "@(#)sh.sem.c	5.4 (Berkeley) 5/13/86";
   9: #endif
  10: 
  11: #include "sh.h"
  12: #include "sh.proc.h"
  13: #include <sys/ioctl.h>
  14: 
  15: /*
  16:  * C shell
  17:  */
  18: 
  19: /*VARARGS 1*/
  20: execute(t, wanttty, pipein, pipeout)
  21:     register struct command *t;
  22:     int wanttty, *pipein, *pipeout;
  23: {
  24:     bool forked = 0;
  25:     struct biltins *bifunc;
  26:     int pid = 0;
  27:     int pv[2];
  28: 
  29:     if (t == 0)
  30:         return;
  31:     if ((t->t_dflg & FAND) && wanttty > 0)
  32:         wanttty = 0;
  33:     switch (t->t_dtyp) {
  34: 
  35:     case TCOM:
  36:         if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE)
  37:             (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
  38:         if ((t->t_dflg & FREDO) == 0)
  39:             Dfix(t);        /* $ " ' \ */
  40:         if (t->t_dcom[0] == 0)
  41:             return;
  42:         /* fall into... */
  43: 
  44:     case TPAR:
  45:         if (t->t_dflg & FPOU)
  46:             mypipe(pipeout);
  47:         /*
  48: 		 * Must do << early so parent will know
  49: 		 * where input pointer should be.
  50: 		 * If noexec then this is all we do.
  51: 		 */
  52:         if (t->t_dflg & FHERE) {
  53:             (void) close(0);
  54:             heredoc(t->t_dlef);
  55:             if (noexec)
  56:                 (void) close(0);
  57:         }
  58:         if (noexec)
  59:             break;
  60: 
  61:         set("status", "0");
  62: 
  63:         /*
  64: 		 * This mess is the necessary kludge to handle the prefix
  65: 		 * builtins: nice, nohup, time.  These commands can also
  66: 		 * be used by themselves, and this is not handled here.
  67: 		 * This will also work when loops are parsed.
  68: 		 */
  69:         while (t->t_dtyp == TCOM)
  70:             if (eq(t->t_dcom[0], "nice"))
  71:                 if (t->t_dcom[1])
  72:                     if (any(t->t_dcom[1][0], "+-"))
  73:                         if (t->t_dcom[2]) {
  74:                             setname("nice");
  75:                             t->t_nice = getn(t->t_dcom[1]);
  76:                             lshift(t->t_dcom, 2);
  77:                             t->t_dflg |= FNICE;
  78:                         } else
  79:                             break;
  80:                     else {
  81:                         t->t_nice = 4;
  82:                         lshift(t->t_dcom, 1);
  83:                         t->t_dflg |= FNICE;
  84:                     }
  85:                 else
  86:                     break;
  87:             else if (eq(t->t_dcom[0], "nohup"))
  88:                 if (t->t_dcom[1]) {
  89:                     t->t_dflg |= FNOHUP;
  90:                     lshift(t->t_dcom, 1);
  91:                 } else
  92:                     break;
  93:             else if (eq(t->t_dcom[0], "time"))
  94:                 if (t->t_dcom[1]) {
  95:                     t->t_dflg |= FTIME;
  96:                     lshift(t->t_dcom, 1);
  97:                 } else
  98:                     break;
  99:             else
 100:                 break;
 101:         /*
 102: 		 * Check if we have a builtin function and remember which one.
 103: 		 */
 104:         bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
 105: 
 106:         /*
 107: 		 * We fork only if we are timed, or are not the end of
 108: 		 * a parenthesized list and not a simple builtin function.
 109: 		 * Simple meaning one that is not pipedout, niced, nohupped,
 110: 		 * or &'d.
 111: 		 * It would be nice(?) to not fork in some of these cases.
 112: 		 */
 113:         if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
 114:              (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
 115: #ifdef VFORK
 116:             if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc)
 117: #endif
 118:             { forked++; pid = pfork(t, wanttty); }
 119: #ifdef VFORK
 120:             else {
 121:             int vffree();
 122:             int ochild, osetintr, ohaderr, odidfds;
 123:             int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
 124:             int omask;
 125: 
 126:             /*
 127: 			 * Prepare for the vfork by saving everything
 128: 			 * that the child corrupts before it exec's.
 129: 			 * Note that in some signal implementations
 130: 			 * which keep the signal info in user space
 131: 			 * (e.g. Sun's) it will also be necessary to
 132:  			 * save and restore the current sigvec's for
 133: 			 * the signals the child touches before it
 134: 			 * exec's.
 135: 			 */
 136:             omask = sigblock(sigmask(SIGCHLD));
 137:             ochild = child; osetintr = setintr;
 138:             ohaderr = haderr; odidfds = didfds;
 139:             oSHIN = SHIN; oSHOUT = SHOUT;
 140:             oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp;
 141:             Vsav = Vdp = 0; Vav = 0;
 142:             pid = vfork();
 143:             if (pid < 0) {
 144:                 (void) sigsetmask(omask);
 145:                 error("No more processes");
 146:             }
 147:             forked++;
 148:             if (pid) {  /* parent */
 149:                 child = ochild; setintr = osetintr;
 150:                 haderr = ohaderr; didfds = odidfds;
 151:                 SHIN = oSHIN;
 152:                 SHOUT = oSHOUT; SHDIAG = oSHDIAG;
 153:                 OLDSTD = oOLDSTD; tpgrp = otpgrp;
 154:                 xfree(Vsav); Vsav = 0;
 155:                 xfree(Vdp); Vdp = 0;
 156:                 xfree((char *)Vav); Vav = 0;
 157:                 /* this is from pfork() */
 158:                 palloc(pid, t);
 159:                 (void) sigsetmask(omask);
 160:             } else {    /* child */
 161:                 /* this is from pfork() */
 162:                 int pgrp;
 163:                 bool ignint = 0;
 164: 
 165:                 if (setintr)
 166:                     ignint =
 167:                         (tpgrp == -1 && (t->t_dflg&FINT))
 168:                         || gointr && eq(gointr, "-");
 169:                 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
 170:                 child++;
 171:                 if (setintr) {
 172:                     setintr = 0;
 173: #ifdef notdef
 174:                     (void) signal(SIGCHLD, SIG_DFL);
 175: #endif
 176:                     (void) signal(SIGINT, ignint ?
 177:                         SIG_IGN : vffree);
 178:                     (void) signal(SIGQUIT, ignint ?
 179:                         SIG_IGN : SIG_DFL);
 180:                     if (wanttty >= 0) {
 181:                         (void) signal(SIGTSTP, SIG_DFL);
 182:                         (void) signal(SIGTTIN, SIG_DFL);
 183:                         (void) signal(SIGTTOU, SIG_DFL);
 184:                     }
 185:                     (void) signal(SIGTERM, parterm);
 186:                 } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
 187:                     (void) signal(SIGINT, SIG_IGN);
 188:                     (void) signal(SIGQUIT, SIG_IGN);
 189:                 }
 190:                 if (wanttty > 0)
 191:                     (void) ioctl(FSHTTY, TIOCSPGRP,
 192:                         (char *)&pgrp);
 193:                 if (wanttty >= 0 && tpgrp >= 0)
 194:                     (void) setpgrp(0, pgrp);
 195:                 if (tpgrp > 0)
 196:                     tpgrp = 0;
 197:                 if (t->t_dflg & FNOHUP)
 198:                     (void) signal(SIGHUP, SIG_IGN);
 199:                 if (t->t_dflg & FNICE)
 200:                     (void) setpriority(PRIO_PROCESS,
 201:                         0, t->t_nice);
 202:             }
 203: 
 204:             }
 205: #endif
 206:         if (pid != 0) {
 207:             /*
 208: 			 * It would be better if we could wait for the
 209: 			 * whole job when we knew the last process
 210: 			 * had been started.  Pwait, in fact, does
 211: 			 * wait for the whole job anyway, but this test
 212: 			 * doesn't really express our intentions.
 213: 			 */
 214:             if (didfds==0 && t->t_dflg&FPIN) {
 215:                 (void) close(pipein[0]);
 216:                 (void) close(pipein[1]);
 217:             }
 218:             if ((t->t_dflg & (FPOU|FAND)) == 0)
 219:                 pwait();
 220:             break;
 221:         }
 222:         doio(t, pipein, pipeout);
 223:         if (t->t_dflg & FPOU) {
 224:             (void) close(pipeout[0]);
 225:             (void) close(pipeout[1]);
 226:         }
 227: 
 228:         /*
 229: 		 * Perform a builtin function.
 230: 		 * If we are not forked, arrange for possible stopping
 231: 		 */
 232:         if (bifunc) {
 233:             func(t, bifunc);
 234:             if (forked)
 235:                 exitstat();
 236:             break;
 237:         }
 238:         if (t->t_dtyp != TPAR) {
 239:             doexec(t);
 240:             /*NOTREACHED*/
 241:         }
 242:         /*
 243: 		 * For () commands must put new 0,1,2 in FSH* and recurse
 244: 		 */
 245:         OLDSTD = dcopy(0, FOLDSTD);
 246:         SHOUT = dcopy(1, FSHOUT);
 247:         SHDIAG = dcopy(2, FSHDIAG);
 248:         (void) close(SHIN);
 249:         SHIN = -1;
 250:         didfds = 0;
 251:         wanttty = -1;
 252:         t->t_dspr->t_dflg |= t->t_dflg & FINT;
 253:         execute(t->t_dspr, wanttty);
 254:         exitstat();
 255: 
 256:     case TFIL:
 257:         t->t_dcar->t_dflg |= FPOU |
 258:             (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
 259:         execute(t->t_dcar, wanttty, pipein, pv);
 260:         t->t_dcdr->t_dflg |= FPIN |
 261:             (t->t_dflg & (FPOU|FAND|FPAR|FINT));
 262:         if (wanttty > 0)
 263:             wanttty = 0;        /* got tty already */
 264:         execute(t->t_dcdr, wanttty, pv, pipeout);
 265:         break;
 266: 
 267:     case TLST:
 268:         if (t->t_dcar) {
 269:             t->t_dcar->t_dflg |= t->t_dflg & FINT;
 270:             execute(t->t_dcar, wanttty);
 271:             /*
 272: 			 * In strange case of A&B make a new job after A
 273: 			 */
 274:             if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
 275:                 (t->t_dcdr->t_dflg&FAND) == 0)
 276:                 pendjob();
 277:         }
 278:         if (t->t_dcdr) {
 279:             t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
 280:             execute(t->t_dcdr, wanttty);
 281:         }
 282:         break;
 283: 
 284:     case TOR:
 285:     case TAND:
 286:         if (t->t_dcar) {
 287:             t->t_dcar->t_dflg |= t->t_dflg & FINT;
 288:             execute(t->t_dcar, wanttty);
 289:             if ((getn(value("status")) == 0) != (t->t_dtyp == TAND))
 290:                 return;
 291:         }
 292:         if (t->t_dcdr) {
 293:             t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
 294:             execute(t->t_dcdr, wanttty);
 295:         }
 296:         break;
 297:     }
 298:     /*
 299: 	 * Fall through for all breaks from switch
 300: 	 *
 301: 	 * If there will be no more executions of this
 302: 	 * command, flush all file descriptors.
 303: 	 * Places that turn on the FREDO bit are responsible
 304: 	 * for doing donefds after the last re-execution
 305: 	 */
 306:     if (didfds && !(t->t_dflg & FREDO))
 307:         donefds();
 308: }
 309: 
 310: #ifdef VFORK
 311: vffree()
 312: {
 313:     register char **v;
 314: 
 315:     if (v = gargv)
 316:         gargv = 0, xfree((char *)v);
 317:     if (v = pargv)
 318:         pargv = 0, xfree((char *)v);
 319:     _exit(1);
 320: }
 321: #endif
 322: 
 323: /*
 324:  * Perform io redirection.
 325:  * We may or maynot be forked here.
 326:  */
 327: doio(t, pipein, pipeout)
 328:     register struct command *t;
 329:     int *pipein, *pipeout;
 330: {
 331:     register char *cp;
 332:     register int flags = t->t_dflg;
 333: 
 334:     if (didfds || (flags & FREDO))
 335:         return;
 336:     if ((flags & FHERE) == 0) { /* FHERE already done */
 337:         (void) close(0);
 338:         if (cp = t->t_dlef) {
 339:             cp = globone(Dfix1(cp));
 340:             xfree(cp);
 341:             if (open(cp, 0) < 0)
 342:                 Perror(cp);
 343:         } else if (flags & FPIN) {
 344:             (void) dup(pipein[0]);
 345:             (void) close(pipein[0]);
 346:             (void) close(pipein[1]);
 347:         } else if ((flags & FINT) && tpgrp == -1) {
 348:             (void) close(0);
 349:             (void) open("/dev/null", 0);
 350:         } else
 351:             (void) dup(OLDSTD);
 352:     }
 353:     (void) close(1);
 354:     if (cp = t->t_drit) {
 355:         cp = globone(Dfix1(cp));
 356:         xfree(cp);
 357:         if ((flags & FCAT) && open(cp, 1) >= 0)
 358:             (void) lseek(1, (off_t)0, 2);
 359:         else {
 360:             if (!(flags & FANY) && adrof("noclobber")) {
 361:                 if (flags & FCAT)
 362:                     Perror(cp);
 363:                 chkclob(cp);
 364:             }
 365:             if (creat(cp, 0666) < 0)
 366:                 Perror(cp);
 367:         }
 368:     } else if (flags & FPOU)
 369:         (void) dup(pipeout[1]);
 370:     else
 371:         (void) dup(SHOUT);
 372: 
 373:     (void) close(2);
 374:     if (flags & FDIAG)
 375:         (void) dup(1);
 376:     else
 377:         (void) dup(SHDIAG);
 378:     didfds = 1;
 379: }
 380: 
 381: mypipe(pv)
 382:     register int *pv;
 383: {
 384: 
 385:     if (pipe(pv) < 0)
 386:         goto oops;
 387:     pv[0] = dmove(pv[0], -1);
 388:     pv[1] = dmove(pv[1], -1);
 389:     if (pv[0] >= 0 && pv[1] >= 0)
 390:         return;
 391: oops:
 392:     error("Can't make pipe");
 393: }
 394: 
 395: chkclob(cp)
 396:     register char *cp;
 397: {
 398:     struct stat stb;
 399: 
 400:     if (stat(cp, &stb) < 0)
 401:         return;
 402:     if ((stb.st_mode & S_IFMT) == S_IFCHR)
 403:         return;
 404:     error("%s: File exists", cp);
 405: }

Defined functions

chkclob defined in line 395; used 1 times
doio defined in line 327; used 1 times
execute defined in line 20; used 11 times
mypipe defined in line 381; used 2 times
vffree defined in line 311; used 2 times

Defined variables

sccsid defined in line 8; never used
Last modified: 1986-05-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1626
Valid CSS Valid XHTML 1.0 Strict