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