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

Defined functions

chkclob defined in line 359; used 1 times
doio defined in line 297; used 1 times
execute defined in line 12; used 11 times
mypipe defined in line 345; used 2 times
vffree defined in line 281; used 2 times

Defined variables

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