|
|
1.1 ! root 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) { ! 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) ! 316: /* ! 317: * until stop on background read is implemented ... ! 318: */ ! 319: /* && tpgrp == -1 */ ) ! 320: close(0), open("/dev/null", 0); ! 321: else ! 322: dup(OLDSTD); ! 323: } ! 324: close(1); ! 325: if (cp = t->t_drit) { ! 326: cp = globone(Dfix1(cp)); ! 327: xfree(cp); ! 328: if ((flags & FCAT) && open(cp, 1) >= 0) ! 329: lseek(1, 0l, 2); ! 330: else { ! 331: if (!(flags & FANY) && adrof("noclobber")) { ! 332: if (flags & FCAT) ! 333: Perror(cp); ! 334: chkclob(cp); ! 335: } ! 336: if (creat(cp, 0666) < 0) ! 337: Perror(cp); ! 338: } ! 339: } else if (flags & FPOU) ! 340: dup(pipeout[1]); ! 341: else ! 342: dup(SHOUT); ! 343: ! 344: close(2); ! 345: dup((flags & FDIAG) ? 1 : SHDIAG); ! 346: didfds = 1; ! 347: } ! 348: ! 349: mypipe(pv) ! 350: register int *pv; ! 351: { ! 352: ! 353: if (pipe(pv) < 0) ! 354: goto oops; ! 355: pv[0] = dmove(pv[0], -1); ! 356: pv[1] = dmove(pv[1], -1); ! 357: if (pv[0] >= 0 && pv[1] >= 0) ! 358: return; ! 359: oops: ! 360: error("Can't make pipe"); ! 361: } ! 362: ! 363: chkclob(cp) ! 364: register char *cp; ! 365: { ! 366: struct stat stb; ! 367: ! 368: if (stat(cp, &stb) < 0) ! 369: return; ! 370: if ((stb.st_mode & S_IFMT) == S_IFCHR) ! 371: return; ! 372: error("%s: File exists", cp); ! 373: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.