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