|
|
1.1 ! root 1: static char *sccsid = "@(#)sh.sem.c 4.3 6/11/83"; ! 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: #ifdef notdef ! 155: sigsys(SIGCHLD, SIG_DFL); ! 156: #endif ! 157: sigsys(SIGINT, ! 158: ignint ? SIG_IGN : vffree); ! 159: sigsys(SIGQUIT, ! 160: ignint ? SIG_IGN : SIG_DFL); ! 161: if (wanttty >= 0) { ! 162: sigsys(SIGTSTP, SIG_DFL); ! 163: sigsys(SIGTTIN, SIG_DFL); ! 164: sigsys(SIGTTOU, SIG_DFL); ! 165: } ! 166: sigsys(SIGTERM, parterm); ! 167: } else if (tpgrp == -1 && (t->t_dflg&FINT)) { ! 168: sigsys(SIGINT, SIG_IGN); ! 169: sigsys(SIGQUIT, SIG_IGN); ! 170: } ! 171: if (wanttty > 0) ! 172: ioctl(FSHTTY, TIOCSPGRP, &pgrp); ! 173: if (wanttty >= 0 && tpgrp >= 0) ! 174: setpgrp(0, pgrp); ! 175: if (tpgrp > 0) ! 176: tpgrp = 0; ! 177: if (t->t_dflg & FNOHUP) ! 178: sigsys(SIGHUP, SIG_IGN); ! 179: if (t->t_dflg & FNICE) ! 180: nice(t->t_nice); ! 181: } ! 182: ! 183: } ! 184: #endif ! 185: if (pid != 0) { ! 186: /* ! 187: * It would be better if we could wait for the ! 188: * whole job when we knew the last process ! 189: * had been started. Pwait, in fact, does ! 190: * wait for the whole job anyway, but this test ! 191: * doesn't really express our intentions. ! 192: */ ! 193: if (didfds==0 && t->t_dflg&FPIN) ! 194: close(pipein[0]), close(pipein[1]); ! 195: if ((t->t_dflg & (FPOU|FAND)) == 0) ! 196: pwait(); ! 197: break; ! 198: } ! 199: doio(t, pipein, pipeout); ! 200: if (t->t_dflg & FPOU) ! 201: close(pipeout[0]), close(pipeout[1]); ! 202: ! 203: /* ! 204: * Perform a builtin function. ! 205: * If we are not forked, arrange for possible stopping ! 206: */ ! 207: if (bifunc) { ! 208: func(t, bifunc); ! 209: if (forked) ! 210: exitstat(); ! 211: break; ! 212: } ! 213: if (t->t_dtyp != TPAR) { ! 214: doexec(t); ! 215: /*NOTREACHED*/ ! 216: } ! 217: /* ! 218: * For () commands must put new 0,1,2 in FSH* and recurse ! 219: */ ! 220: OLDSTD = dcopy(0, FOLDSTD); ! 221: SHOUT = dcopy(1, FSHOUT); ! 222: SHDIAG = dcopy(2, FSHDIAG); ! 223: close(SHIN), SHIN = -1; ! 224: didcch = 0, didfds = 0; ! 225: wanttty = -1; ! 226: t->t_dspr->t_dflg |= t->t_dflg & FINT; ! 227: execute(t->t_dspr, wanttty); ! 228: exitstat(); ! 229: ! 230: case TFIL: ! 231: t->t_dcar->t_dflg |= FPOU | ! 232: (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); ! 233: execute(t->t_dcar, wanttty, pipein, pv); ! 234: t->t_dcdr->t_dflg |= FPIN | ! 235: (t->t_dflg & (FPOU|FAND|FPAR|FINT)); ! 236: if (wanttty > 0) ! 237: wanttty = 0; /* got tty already */ ! 238: execute(t->t_dcdr, wanttty, pv, pipeout); ! 239: break; ! 240: ! 241: case TLST: ! 242: if (t->t_dcar) { ! 243: t->t_dcar->t_dflg |= t->t_dflg & FINT; ! 244: execute(t->t_dcar, wanttty); ! 245: /* ! 246: * In strange case of A&B make a new job after A ! 247: */ ! 248: if (t->t_dcar->t_dflg&FAND && t->t_dcdr && ! 249: (t->t_dcdr->t_dflg&FAND) == 0) ! 250: pendjob(); ! 251: } ! 252: if (t->t_dcdr) { ! 253: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); ! 254: execute(t->t_dcdr, wanttty); ! 255: } ! 256: break; ! 257: ! 258: case TOR: ! 259: case TAND: ! 260: if (t->t_dcar) { ! 261: t->t_dcar->t_dflg |= t->t_dflg & FINT; ! 262: execute(t->t_dcar, wanttty); ! 263: if ((getn(value("status")) == 0) != (t->t_dtyp == TAND)) ! 264: return; ! 265: } ! 266: if (t->t_dcdr) { ! 267: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); ! 268: execute(t->t_dcdr, wanttty); ! 269: } ! 270: break; ! 271: } ! 272: /* ! 273: * Fall through for all breaks from switch ! 274: * ! 275: * If there will be no more executions of this ! 276: * command, flush all file descriptors. ! 277: * Places that turn on the FREDO bit are responsible ! 278: * for doing donefds after the last re-execution ! 279: */ ! 280: if (didfds && !(t->t_dflg & FREDO)) ! 281: donefds(); ! 282: } ! 283: ! 284: #ifdef VFORK ! 285: vffree() ! 286: { ! 287: register char **v; ! 288: ! 289: if (v = gargv) ! 290: gargv = 0, xfree(gargv); ! 291: if (v = pargv) ! 292: pargv = 0, xfree(pargv); ! 293: _exit(1); ! 294: } ! 295: #endif ! 296: ! 297: /* ! 298: * Perform io redirection. ! 299: * We may or maynot be forked here. ! 300: */ ! 301: doio(t, pipein, pipeout) ! 302: register struct command *t; ! 303: int *pipein, *pipeout; ! 304: { ! 305: register char *cp; ! 306: register int flags = t->t_dflg; ! 307: ! 308: if (didfds || (flags & FREDO)) ! 309: return; ! 310: if ((flags & FHERE) == 0) { /* FHERE already done */ ! 311: close(0); ! 312: if (cp = t->t_dlef) { ! 313: cp = globone(Dfix1(cp)); ! 314: xfree(cp); ! 315: if (open(cp, 0) < 0) ! 316: Perror(cp); ! 317: } else if (flags & FPIN) ! 318: dup(pipein[0]), close(pipein[0]), close(pipein[1]); ! 319: else if ((flags & FINT) && 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.