|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: #include "sh.h" ! 3: ! 4: /* ! 5: * C shell ! 6: */ ! 7: ! 8: execute(t, pipein, pipeout) ! 9: register struct command *t; ! 10: int *pipein, *pipeout; ! 11: { ! 12: int pid, flags, pv[2]; ! 13: register struct command *t1; ! 14: register char *cp; ! 15: bool forked = 0; ! 16: bool shudint, shudhup; ! 17: #ifdef VFORK ! 18: int (*savint)(), vffree(); ! 19: int ochild, osetintr, ohaderr, otimflg, odidfds, odidcch; ! 20: int oSHIN, oSHOUT, oSHDIAG, oOLDSTD; ! 21: int isvfork = 0; ! 22: #endif ! 23: ! 24: if (t == 0) ! 25: return; ! 26: switch (t->t_dtyp) { ! 27: ! 28: case TCOM: ! 29: cp = t->t_dcom[0]; ! 30: if ((cp[0] & (QUOTE|TRIM)) == QUOTE) ! 31: strcpy(cp, cp + 1); ! 32: if ((t->t_dflg & FREDO) == 0) ! 33: Dfix(t); /* $ " ' \ */ ! 34: /* fall into... */ ! 35: ! 36: case TPAR: ! 37: flags = t->t_dflg; ! 38: if (flags & FPOU) ! 39: mypipe(pipeout); ! 40: /* ! 41: * A child will be interruptible only under very ! 42: * certain conditions: ! 43: * we must be monkeying with interrupts ! 44: * the child must not be &'ed ! 45: * we must not have had an "onintr -" ! 46: */ ! 47: shudint = setintr && (flags & FINT) == 0 && (!gointr || !eq(gointr, "-")); ! 48: shudhup = (flags & FAND) == 0; ! 49: ! 50: /* ! 51: * Must do << early so parent will know ! 52: * where input pointer should be ! 53: */ ! 54: if (flags & FHERE) ! 55: close(0), heredoc(t->t_dlef); ! 56: ! 57: /* ! 58: * If not executing commands then ! 59: * all we must do is read forward in the input to ! 60: * account for << redirection if present. ! 61: */ ! 62: if (noexec) { ! 63: if (flags & FHERE) ! 64: close(0); ! 65: return; ! 66: } ! 67: ! 68: set("status", "0"); ! 69: pid = 0; ! 70: ! 71: /* ! 72: * Built-in functions ! 73: */ ! 74: if (t->t_dtyp == TCOM && isbfunc(t->t_dcom[0])) { ! 75: /* ! 76: * If output is piped, or running & and we would ! 77: * eventually fork for non-builtin commands, ! 78: * then do it now, so we won't block. ! 79: */ ! 80: if ((flags & (FPOU|FAND)) && (flags & FPAR) == 0) ! 81: pid = dofork(shudint, shudhup), forked++; ! 82: ! 83: /* ! 84: * If the builtin is actually executed (some, e.g. ! 85: * time and nice may refuse to execute here) ! 86: * then either exit (if we forked) or close i/o ! 87: * and continue execution (if we didn't). ! 88: */ ! 89: if (pid == 0) { ! 90: doio(t, pipein, pipeout); ! 91: if (flags & FPOU) { ! 92: close(pipeout[0]), close(pipeout[1]); ! 93: pipeout[0] = pipeout[1] = -1; ! 94: } ! 95: if (setintr && forked) { ! 96: if (shudint) ! 97: signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL); ! 98: signal(SIGTERM, parterm); ! 99: if (flags & FINT) ! 100: setintr = 0; ! 101: } ! 102: if (func(t, pipein, pipeout)) { ! 103: if (forked) ! 104: exitstat(); ! 105: if (didfds && !(t->t_dflg & FREDO)) ! 106: donefds(); ! 107: return; ! 108: } ! 109: } ! 110: } ! 111: ! 112: /* ! 113: * Now, we must make a new process since either the ! 114: * command is non-builtin, a parenthesized list, ! 115: * or builtin such as time or nice which really ! 116: * requires a child. ! 117: */ ! 118: if (!forked && (flags & FPAR) == 0) ! 119: #ifdef VFORK ! 120: if (t->t_dtyp == TPAR || (flags&FREDO) || ! 121: eq(t->t_dcom[0], "nice") || eq(t->t_dcom[0], "nohup")) ! 122: #endif ! 123: pid = dofork(shudint, shudhup); ! 124: #ifdef VFORK ! 125: else { ! 126: savint = signal(SIGINT, SIG_IGN); ! 127: ochild = child; osetintr = setintr; ! 128: ohaderr = haderr; otimflg = timflg; ! 129: odidfds = didfds; odidcch = didcch; ! 130: oSHIN = SHIN; oSHOUT = SHOUT; ! 131: oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; ! 132: Vsav = Vdp = 0; Vav = 0; ! 133: isvfork++; ! 134: pid = vfork(); ! 135: if (pid < 0) { ! 136: signal(SIGINT, savint); ! 137: error("No more processes"); ! 138: } ! 139: if (pid == 0) { ! 140: child++; ! 141: signal(SIGINT, shudint ? SIG_DFL : savint); ! 142: if (!shudhup) ! 143: signal(SIGHUP, SIG_IGN); ! 144: } else { ! 145: child = ochild; setintr = osetintr; ! 146: haderr = ohaderr; timflg = otimflg; ! 147: didfds = odidfds; didcch = odidcch; ! 148: SHIN = oSHIN; SHOUT = oSHOUT; ! 149: SHDIAG = oSHDIAG; OLDSTD = oOLDSTD; ! 150: xfree(Vsav), Vsav = 0; ! 151: xfree(Vdp), Vdp = 0; ! 152: xfree(Vav), Vav = 0; ! 153: signal(SIGINT, savint); ! 154: } ! 155: } ! 156: #endif ! 157: if (pid != 0) { ! 158: /* ! 159: * The parent path (or nobody does this if ! 160: * (flags & FPAR), i.e. date in (set;date)) ! 161: */ ! 162: if (didfds == 0 && (flags & FPIN)) ! 163: close(pipein[0]), close(pipein[1]); ! 164: if (didfds && !(t->t_dflg & FREDO)) ! 165: donefds(); ! 166: if (flags & FPRS) ! 167: printf("%d\n", pid), set("child", putn(pid)); ! 168: /* ! 169: * Unless output is piped or command is & ! 170: * wait for it. ! 171: */ ! 172: if (t->t_dtyp == TCOM) ! 173: cadd(pid, t->t_dcom[0]); ! 174: else ! 175: cadd(pid, "()"); ! 176: if ((flags & (FPOU|FAND)) == 0) ! 177: pwait(pid); ! 178: return; ! 179: } ! 180: ! 181: /* ! 182: * Insure that this (child) shell doesn't muck on ! 183: */ ! 184: child++; ! 185: ! 186: /* ! 187: * If havent yet, finally set up the file descriptors. ! 188: */ ! 189: doio(t, pipein, pipeout); ! 190: if (flags & FPOU) ! 191: close(pipeout[0]), close(pipeout[1]); ! 192: ! 193: /* ! 194: * If mucking with interrupts fix interrupt, quit, ! 195: * and terminate handling ... in any case set setintr ! 196: * to 0 if we are not interruptible so that no further ! 197: * interrupt mucking occurs. ! 198: */ ! 199: if (setintr) { ! 200: if (shudint) { ! 201: signal(SIGQUIT, SIG_DFL); ! 202: #ifdef VFORK ! 203: if (isvfork) ! 204: signal(SIGINT, vffree); ! 205: else ! 206: #endif ! 207: signal(SIGINT, SIG_DFL); ! 208: } ! 209: signal(SIGTERM, parterm); ! 210: if (flags & FINT) ! 211: setintr = 0; ! 212: } ! 213: ! 214: /* ! 215: * For () commands must put new 0,1,2 in FSH* and recurse ! 216: */ ! 217: if (t->t_dtyp == TPAR) { ! 218: t1 = t->t_dspr; ! 219: t1->t_dflg |= flags & FINT; ! 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: execute(t1); ! 226: exitstat(); ! 227: } ! 228: if (eq(t->t_dcom[0], "nice")) { ! 229: /* sigh... ! 230: nice(20); ! 231: nice(-10); ! 232: */ ! 233: cp = t->t_dcom[1]; ! 234: if (any(cp[0], "+-")) ! 235: nice(getn(cp)), lshift(t->t_dcom, 2); ! 236: else ! 237: nice(4), lshift(t->t_dcom, 1); ! 238: t->t_dflg = FPAR | FREDO; ! 239: execute(t); ! 240: exitstat(); ! 241: } ! 242: if (eq(t->t_dcom[0], "nohup")) { ! 243: if (setintr == 0) ! 244: signal(SIGHUP, SIG_IGN); ! 245: signal(SIGTERM, SIG_IGN); ! 246: lshift(t->t_dcom, 1); ! 247: t->t_dflg = FPAR | FREDO; ! 248: execute(t); ! 249: exitstat(); ! 250: } ! 251: doexec(t); ! 252: /* no return */ ! 253: ! 254: case TFIL: ! 255: flags = t->t_dflg; ! 256: t1 = t->t_dcar; ! 257: t1->t_dflg |= FPOU | (flags & (FPIN|FINT|FPRS|FDIAG)); ! 258: execute(t1, pipein, pv); ! 259: t1 = t->t_dcdr; ! 260: t1->t_dflg |= FPIN | (flags & (FPOU|FINT|FAND|FPRS|FPAR)); ! 261: execute(t1, pv, pipeout); ! 262: return; ! 263: ! 264: case TLST: ! 265: flags = t->t_dflg & FINT; ! 266: if (t1 = t->t_dcar) ! 267: t1->t_dflg |= flags, execute(t1); ! 268: if (t1 = t->t_dcdr) ! 269: t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1); ! 270: return; ! 271: ! 272: case TOR: ! 273: case TAND: ! 274: flags = t->t_dflg & FINT; ! 275: if (t1 = t->t_dcar) { ! 276: t1->t_dflg |= flags, execute(t1); ! 277: if ((getn(value("status")) == 0) == (t->t_dtyp == TAND)) ! 278: return; ! 279: } ! 280: if (t1 = t->t_dcdr) ! 281: t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1); ! 282: return; ! 283: } ! 284: } ! 285: ! 286: #ifdef VFORK ! 287: vffree() ! 288: { ! 289: register char **v; ! 290: ! 291: if (v = gargv) ! 292: gargv = 0, xfree(gargv); ! 293: if (v = pargv) ! 294: pargv = 0, xfree(pargv); ! 295: _exit(1); ! 296: } ! 297: #endif ! 298: ! 299: doio(t, pipein, pipeout) ! 300: register struct command *t; ! 301: int *pipein, *pipeout; ! 302: { ! 303: register char *cp; ! 304: register int flags = t->t_dflg; ! 305: char *dp; ! 306: ! 307: if (didfds || (flags & FREDO)) ! 308: return; ! 309: if (flags & FHERE) ! 310: goto skipin; ! 311: close(0); ! 312: if (cp = t->t_dlef) { ! 313: cp = globone(dp = Dfix1(cp)); ! 314: xfree(dp); ! 315: xfree(cp); ! 316: if (open(cp, 0) < 0) ! 317: Perror(cp); ! 318: } else if (flags & FPIN) ! 319: dup(pipein[0]), close(pipein[0]), close(pipein[1]); ! 320: else if (flags & FINT) ! 321: close(0), open("/dev/null", 0); ! 322: else ! 323: dup(OLDSTD); ! 324: ! 325: skipin: ! 326: close(1); ! 327: if (cp = t->t_drit) { ! 328: cp = globone(dp = Dfix1(cp)); ! 329: xfree(dp); ! 330: xfree(cp); ! 331: if ((flags & FCAT) && open(cp, 1) >= 0) ! 332: lseek(1, 0l, 2); ! 333: else { ! 334: if (!(flags & FANY) && adrof("noclobber")) { ! 335: if (flags & FCAT) ! 336: Perror(cp); ! 337: chkclob(cp); ! 338: } ! 339: #ifdef V6 ! 340: if (creat(cp, 0644) < 0) ! 341: Perror(cp); ! 342: #else ! 343: if (creat(cp, 0666) < 0) ! 344: Perror(cp); ! 345: #endif ! 346: } ! 347: } else ! 348: dup((flags & FPOU) ? pipeout[1] : SHOUT); ! 349: ! 350: close(2); ! 351: dup((flags & FDIAG) ? 1 : SHDIAG); ! 352: didfds = 1; ! 353: } ! 354: ! 355: dofork(shudint, shudhup) ! 356: bool shudint, shudhup; ! 357: { ! 358: register int pid, (*savint)(); ! 359: ! 360: savint = signal(SIGINT, SIG_IGN); ! 361: pid = fork(); ! 362: if (pid < 0) { ! 363: signal(SIGINT, savint); ! 364: error("No more processes"); ! 365: } ! 366: if (pid == 0) { ! 367: child++; ! 368: signal(SIGINT, shudint ? SIG_DFL : savint); ! 369: if (!shudhup) ! 370: signal(SIGHUP, SIG_IGN); ! 371: } else ! 372: signal(SIGINT, savint); ! 373: return (pid); ! 374: } ! 375: ! 376: mypipe(pv) ! 377: register int *pv; ! 378: { ! 379: ! 380: if (pipe(pv) < 0) ! 381: goto oops; ! 382: pv[0] = dmove(pv[0], -1); ! 383: pv[1] = dmove(pv[1], -1); ! 384: if (pv[0] >= 0 && pv[1] >= 0) ! 385: return; ! 386: oops: ! 387: error("Can't make pipe"); ! 388: } ! 389: ! 390: chkclob(cp) ! 391: register char *cp; ! 392: { ! 393: struct stat stb; ! 394: ! 395: if (stat(cp, &stb) < 0) ! 396: return; ! 397: if ((stb.st_mode & S_IFMT) == S_IFCHR) ! 398: return; ! 399: error("%s: File exists", cp); ! 400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.