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

Defined functions

chkclob defined in line 402; used 1 times
doio defined in line 334; used 1 times
execute defined in line 21; used 11 times
mypipe defined in line 388; used 2 times
vffree defined in line 318; used 2 times

Defined variables

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