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.4 (Berkeley) 5/13/86"; 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: int 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: }