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