|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley Software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char *sccsid = "@(#)sh.sem.c 5.5 (Berkeley) 6/25/87"; ! 9: #endif ! 10: ! 11: #include "sh.h" ! 12: #include "sh.proc.h" ! 13: #include <sys/ioctl.h> ! 14: ! 15: /* ! 16: * C shell ! 17: */ ! 18: ! 19: /*VARARGS 1*/ ! 20: execute(t, wanttty, pipein, pipeout) ! 21: register struct command *t; ! 22: int wanttty, *pipein, *pipeout; ! 23: { ! 24: bool forked = 0; ! 25: struct biltins *bifunc; ! 26: int pid = 0; ! 27: int pv[2]; ! 28: ! 29: if (t == 0) ! 30: return; ! 31: if ((t->t_dflg & FAND) && wanttty > 0) ! 32: wanttty = 0; ! 33: switch (t->t_dtyp) { ! 34: ! 35: case TCOM: ! 36: if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE) ! 37: (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1); ! 38: if ((t->t_dflg & FREDO) == 0) ! 39: Dfix(t); /* $ " ' \ */ ! 40: if (t->t_dcom[0] == 0) ! 41: return; ! 42: /* fall into... */ ! 43: ! 44: case TPAR: ! 45: if (t->t_dflg & FPOU) ! 46: mypipe(pipeout); ! 47: /* ! 48: * Must do << early so parent will know ! 49: * where input pointer should be. ! 50: * If noexec then this is all we do. ! 51: */ ! 52: if (t->t_dflg & FHERE) { ! 53: (void) close(0); ! 54: heredoc(t->t_dlef); ! 55: if (noexec) ! 56: (void) close(0); ! 57: } ! 58: if (noexec) ! 59: break; ! 60: ! 61: set("status", "0"); ! 62: ! 63: /* ! 64: * This mess is the necessary kludge to handle the prefix ! 65: * builtins: nice, nohup, time. These commands can also ! 66: * be used by themselves, and this is not handled here. ! 67: * This will also work when loops are parsed. ! 68: */ ! 69: while (t->t_dtyp == TCOM) ! 70: if (eq(t->t_dcom[0], "nice")) ! 71: if (t->t_dcom[1]) ! 72: if (any(t->t_dcom[1][0], "+-")) ! 73: if (t->t_dcom[2]) { ! 74: setname("nice"); ! 75: t->t_nice = getn(t->t_dcom[1]); ! 76: lshift(t->t_dcom, 2); ! 77: t->t_dflg |= FNICE; ! 78: } else ! 79: break; ! 80: else { ! 81: t->t_nice = 4; ! 82: lshift(t->t_dcom, 1); ! 83: t->t_dflg |= FNICE; ! 84: } ! 85: else ! 86: break; ! 87: else if (eq(t->t_dcom[0], "nohup")) ! 88: if (t->t_dcom[1]) { ! 89: t->t_dflg |= FNOHUP; ! 90: lshift(t->t_dcom, 1); ! 91: } else ! 92: break; ! 93: else if (eq(t->t_dcom[0], "time")) ! 94: if (t->t_dcom[1]) { ! 95: t->t_dflg |= FTIME; ! 96: lshift(t->t_dcom, 1); ! 97: } else ! 98: break; ! 99: else ! 100: break; ! 101: /* ! 102: * Check if we have a builtin function and remember which one. ! 103: */ ! 104: bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0; ! 105: ! 106: /* ! 107: * We fork only if we are timed, or are not the end of ! 108: * a parenthesized list and not a simple builtin function. ! 109: * Simple meaning one that is not pipedout, niced, nohupped, ! 110: * or &'d. ! 111: * It would be nice(?) to not fork in some of these cases. ! 112: */ ! 113: if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 && ! 114: (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP)))) ! 115: #ifdef VFORK ! 116: if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc) ! 117: #endif ! 118: { forked++; pid = pfork(t, wanttty); } ! 119: #ifdef VFORK ! 120: else { ! 121: int vffree(); ! 122: int ochild, osetintr, ohaderr, odidfds; ! 123: int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; ! 124: long omask; ! 125: ! 126: /* ! 127: * Prepare for the vfork by saving everything ! 128: * that the child corrupts before it exec's. ! 129: * Note that in some signal implementations ! 130: * which keep the signal info in user space ! 131: * (e.g. Sun's) it will also be necessary to ! 132: * save and restore the current sigvec's for ! 133: * the signals the child touches before it ! 134: * exec's. ! 135: */ ! 136: omask = sigblock(sigmask(SIGCHLD)); ! 137: ochild = child; osetintr = setintr; ! 138: ohaderr = haderr; odidfds = didfds; ! 139: oSHIN = SHIN; oSHOUT = SHOUT; ! 140: oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp; ! 141: Vsav = Vdp = 0; Vav = 0; ! 142: pid = vfork(); ! 143: if (pid < 0) { ! 144: (void) sigsetmask(omask); ! 145: error("No more processes"); ! 146: } ! 147: forked++; ! 148: if (pid) { /* parent */ ! 149: child = ochild; setintr = osetintr; ! 150: haderr = ohaderr; didfds = odidfds; ! 151: SHIN = oSHIN; ! 152: SHOUT = oSHOUT; SHDIAG = oSHDIAG; ! 153: OLDSTD = oOLDSTD; tpgrp = otpgrp; ! 154: xfree(Vsav); Vsav = 0; ! 155: xfree(Vdp); Vdp = 0; ! 156: xfree((char *)Vav); Vav = 0; ! 157: /* this is from pfork() */ ! 158: palloc(pid, t); ! 159: (void) sigsetmask(omask); ! 160: } else { /* child */ ! 161: /* this is from pfork() */ ! 162: int pgrp; ! 163: bool ignint = 0; ! 164: ! 165: if (setintr) ! 166: ignint = ! 167: (tpgrp == -1 && (t->t_dflg&FINT)) ! 168: || gointr && eq(gointr, "-"); ! 169: pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); ! 170: child++; ! 171: if (setintr) { ! 172: setintr = 0; ! 173: #ifdef notdef ! 174: (void) signal(SIGCHLD, SIG_DFL); ! 175: #endif ! 176: (void) signal(SIGINT, ignint ? ! 177: SIG_IGN : vffree); ! 178: (void) signal(SIGQUIT, ignint ? ! 179: SIG_IGN : SIG_DFL); ! 180: if (wanttty >= 0) { ! 181: (void) signal(SIGTSTP, SIG_DFL); ! 182: (void) signal(SIGTTIN, SIG_DFL); ! 183: (void) signal(SIGTTOU, SIG_DFL); ! 184: } ! 185: (void) signal(SIGTERM, parterm); ! 186: } else if (tpgrp == -1 && (t->t_dflg&FINT)) { ! 187: (void) signal(SIGINT, SIG_IGN); ! 188: (void) signal(SIGQUIT, SIG_IGN); ! 189: } ! 190: if (wanttty > 0) ! 191: (void) ioctl(FSHTTY, TIOCSPGRP, ! 192: (char *)&pgrp); ! 193: if (wanttty >= 0 && tpgrp >= 0) ! 194: (void) setpgrp(0, pgrp); ! 195: if (tpgrp > 0) ! 196: tpgrp = 0; ! 197: if (t->t_dflg & FNOHUP) ! 198: (void) signal(SIGHUP, SIG_IGN); ! 199: if (t->t_dflg & FNICE) ! 200: (void) setpriority(PRIO_PROCESS, ! 201: 0, t->t_nice); ! 202: } ! 203: ! 204: } ! 205: #endif ! 206: if (pid != 0) { ! 207: /* ! 208: * It would be better if we could wait for the ! 209: * whole job when we knew the last process ! 210: * had been started. Pwait, in fact, does ! 211: * wait for the whole job anyway, but this test ! 212: * doesn't really express our intentions. ! 213: */ ! 214: if (didfds==0 && t->t_dflg&FPIN) { ! 215: (void) close(pipein[0]); ! 216: (void) close(pipein[1]); ! 217: } ! 218: if ((t->t_dflg & (FPOU|FAND)) == 0) ! 219: pwait(); ! 220: break; ! 221: } ! 222: doio(t, pipein, pipeout); ! 223: if (t->t_dflg & FPOU) { ! 224: (void) close(pipeout[0]); ! 225: (void) close(pipeout[1]); ! 226: } ! 227: ! 228: /* ! 229: * Perform a builtin function. ! 230: * If we are not forked, arrange for possible stopping ! 231: */ ! 232: if (bifunc) { ! 233: func(t, bifunc); ! 234: if (forked) ! 235: exitstat(); ! 236: break; ! 237: } ! 238: if (t->t_dtyp != TPAR) { ! 239: doexec(t); ! 240: /*NOTREACHED*/ ! 241: } ! 242: /* ! 243: * For () commands must put new 0,1,2 in FSH* and recurse ! 244: */ ! 245: OLDSTD = dcopy(0, FOLDSTD); ! 246: SHOUT = dcopy(1, FSHOUT); ! 247: SHDIAG = dcopy(2, FSHDIAG); ! 248: (void) close(SHIN); ! 249: SHIN = -1; ! 250: didfds = 0; ! 251: wanttty = -1; ! 252: t->t_dspr->t_dflg |= t->t_dflg & FINT; ! 253: execute(t->t_dspr, wanttty); ! 254: exitstat(); ! 255: ! 256: case TFIL: ! 257: t->t_dcar->t_dflg |= FPOU | ! 258: (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); ! 259: execute(t->t_dcar, wanttty, pipein, pv); ! 260: t->t_dcdr->t_dflg |= FPIN | ! 261: (t->t_dflg & (FPOU|FAND|FPAR|FINT)); ! 262: if (wanttty > 0) ! 263: wanttty = 0; /* got tty already */ ! 264: execute(t->t_dcdr, wanttty, pv, pipeout); ! 265: break; ! 266: ! 267: case TLST: ! 268: if (t->t_dcar) { ! 269: t->t_dcar->t_dflg |= t->t_dflg & FINT; ! 270: execute(t->t_dcar, wanttty); ! 271: /* ! 272: * In strange case of A&B make a new job after A ! 273: */ ! 274: if (t->t_dcar->t_dflg&FAND && t->t_dcdr && ! 275: (t->t_dcdr->t_dflg&FAND) == 0) ! 276: pendjob(); ! 277: } ! 278: if (t->t_dcdr) { ! 279: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); ! 280: execute(t->t_dcdr, wanttty); ! 281: } ! 282: break; ! 283: ! 284: case TOR: ! 285: case TAND: ! 286: if (t->t_dcar) { ! 287: t->t_dcar->t_dflg |= t->t_dflg & FINT; ! 288: execute(t->t_dcar, wanttty); ! 289: if ((getn(value("status")) == 0) != (t->t_dtyp == TAND)) ! 290: return; ! 291: } ! 292: if (t->t_dcdr) { ! 293: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); ! 294: execute(t->t_dcdr, wanttty); ! 295: } ! 296: break; ! 297: } ! 298: /* ! 299: * Fall through for all breaks from switch ! 300: * ! 301: * If there will be no more executions of this ! 302: * command, flush all file descriptors. ! 303: * Places that turn on the FREDO bit are responsible ! 304: * for doing donefds after the last re-execution ! 305: */ ! 306: if (didfds && !(t->t_dflg & FREDO)) ! 307: donefds(); ! 308: } ! 309: ! 310: #ifdef VFORK ! 311: vffree() ! 312: { ! 313: register char **v; ! 314: ! 315: if (v = gargv) ! 316: gargv = 0, xfree((char *)v); ! 317: if (v = pargv) ! 318: pargv = 0, xfree((char *)v); ! 319: _exit(1); ! 320: } ! 321: #endif ! 322: ! 323: /* ! 324: * Perform io redirection. ! 325: * We may or maynot be forked here. ! 326: */ ! 327: doio(t, pipein, pipeout) ! 328: register struct command *t; ! 329: int *pipein, *pipeout; ! 330: { ! 331: register char *cp; ! 332: register int flags = t->t_dflg; ! 333: ! 334: if (didfds || (flags & FREDO)) ! 335: return; ! 336: if ((flags & FHERE) == 0) { /* FHERE already done */ ! 337: (void) close(0); ! 338: if (cp = t->t_dlef) { ! 339: cp = globone(Dfix1(cp)); ! 340: xfree(cp); ! 341: if (open(cp, 0) < 0) ! 342: Perror(cp); ! 343: } else if (flags & FPIN) { ! 344: (void) dup(pipein[0]); ! 345: (void) close(pipein[0]); ! 346: (void) close(pipein[1]); ! 347: } else if ((flags & FINT) && tpgrp == -1) { ! 348: (void) close(0); ! 349: (void) open("/dev/null", 0); ! 350: } else ! 351: (void) dup(OLDSTD); ! 352: } ! 353: (void) close(1); ! 354: if (cp = t->t_drit) { ! 355: cp = globone(Dfix1(cp)); ! 356: xfree(cp); ! 357: if ((flags & FCAT) && open(cp, 1) >= 0) ! 358: (void) lseek(1, (off_t)0, 2); ! 359: else { ! 360: if (!(flags & FANY) && adrof("noclobber")) { ! 361: if (flags & FCAT) ! 362: Perror(cp); ! 363: chkclob(cp); ! 364: } ! 365: if (creat(cp, 0666) < 0) ! 366: Perror(cp); ! 367: } ! 368: } else if (flags & FPOU) ! 369: (void) dup(pipeout[1]); ! 370: else ! 371: (void) dup(SHOUT); ! 372: ! 373: (void) close(2); ! 374: if (flags & FDIAG) ! 375: (void) dup(1); ! 376: else ! 377: (void) dup(SHDIAG); ! 378: didfds = 1; ! 379: } ! 380: ! 381: mypipe(pv) ! 382: register int *pv; ! 383: { ! 384: ! 385: if (pipe(pv) < 0) ! 386: goto oops; ! 387: pv[0] = dmove(pv[0], -1); ! 388: pv[1] = dmove(pv[1], -1); ! 389: if (pv[0] >= 0 && pv[1] >= 0) ! 390: return; ! 391: oops: ! 392: error("Can't make pipe"); ! 393: } ! 394: ! 395: chkclob(cp) ! 396: register char *cp; ! 397: { ! 398: struct stat stb; ! 399: ! 400: if (stat(cp, &stb) < 0) ! 401: return; ! 402: if ((stb.st_mode & S_IFMT) == S_IFCHR) ! 403: return; ! 404: error("%s: File exists", cp); ! 405: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.