|
|
1.1 ! root 1: /* ! 2: * sh/exec2.c ! 3: * Bourne shell. ! 4: * System part of execution. ! 5: */ ! 6: ! 7: #include "sh.h" ! 8: #include <errno.h> ! 9: #include <sys/param.h> ! 10: #include <signal.h> ! 11: #include <sys/stat.h> ! 12: #include <fcntl.h> ! 13: ! 14: /* ! 15: * Wait for the given process to complete. ! 16: */ ! 17: waitc(pid) ! 18: int pid; ! 19: { ! 20: register int f; ! 21: unsigned s; ! 22: register int w, n; ! 23: int (*ssig)(); ! 24: ! 25: if (pid < 0) ! 26: f = -pid; ! 27: else ! 28: f = pid; ! 29: if ((ssig=signal(SIGINT, SIG_IGN)) != SIG_IGN) ! 30: signal(SIGINT, sigintr); ! 31: for (;;) { ! 32: if ((w=wait(&s)) >= 0) { ! 33: if (n = (s&0177)) { ! 34: if (n==SIGINT) ! 35: sigintr(n); ! 36: else if (n==SIGPIPE && spipe ! 37: && (w >= spipe && w <= f)) ! 38: ; ! 39: else { ! 40: if (w != f) ! 41: prints("%d: ", w); ! 42: if (n==SIGSYS && (s&0200)==0) ! 43: prints("exec failed"); ! 44: else if (n>0 && n<=NSIG) ! 45: prints("%s", signame[n]); ! 46: else ! 47: prints("status %d", n); ! 48: if (s & 0200) ! 49: prints(" -- core dumped"); ! 50: prints("\n"); ! 51: } ! 52: s = 200 + n; ! 53: } else ! 54: s >>= 8; ! 55: if (w == f) { ! 56: slret = s; ! 57: break; ! 58: } ! 59: } else if (errno==EINTR) { ! 60: if (pid > 0) ! 61: continue; ! 62: else { ! 63: slret = 0; ! 64: break; ! 65: } ! 66: } else if (errno==ECHILD) { ! 67: if (pid == 0) ! 68: slret = 0; ! 69: else ! 70: slret = ECHILD; ! 71: break; ! 72: } else { ! 73: panic(6); ! 74: NOTREACHED; ! 75: } ! 76: } ! 77: signal(SIGINT, ssig); ! 78: return (slret); ! 79: } ! 80: ! 81: /* ! 82: * Make an imperfect copy of ourself. ! 83: */ ! 84: clone() ! 85: { ! 86: register int f; ! 87: register SES *sp; ! 88: ! 89: if ((f=fork()) < 0) { ! 90: prints("Try again\n"); ! 91: reset(RSYSER); ! 92: NOTREACHED; ! 93: } else if (f == 0) { ! 94: nllflag = 1; ! 95: sflag = iflag = cflag = no1flag = lgnflag = 0; ! 96: slret = spipe = 0; ! 97: sp = sesp; ! 98: sp->s_con->c_next = NULL; ! 99: ! 100: /* ! 101: * Originally this function suppressed function definitions ! 102: * in child processes. This is wrong. Note that we have to ! 103: * detach the temporary-file stuff from the child functions, ! 104: * however, so that functions with here-documents work (as ! 105: * long as the top-level shell is alive, that is). ! 106: */ ! 107: #if 1 ! 108: subshell_shell_fns (); ! 109: #else ! 110: sh_fnp = NULL; ! 111: #endif ! 112: ! 113: while (sp) { ! 114: if (sp->s_type == SFILE) ! 115: fclose(sp->s_ifp); ! 116: sp = sp->s_next; ! 117: } ! 118: dflttrp(IFORK); ! 119: } ! 120: return (f); ! 121: } ! 122: ! 123: /* ! 124: * Open a pipe, panic on failure. ! 125: * Otherwise return as a clone. ! 126: */ ! 127: pipeline(pv) ! 128: int *pv; ! 129: { ! 130: if (pipe(pv) < 0) { ! 131: prints("Pipe failed\n"); ! 132: reset(RSYSER); ! 133: NOTREACHED; ! 134: } ! 135: return (clone()); ! 136: } ! 137: ! 138: /* ! 139: * Try to execute a file in several ways. ! 140: * A return is always an error. ! 141: * Used by exec in inline. ! 142: */ ! 143: flexec() ! 144: { ! 145: ffind(NULL); ! 146: while (ffind(vpath, *nargv, 1)) { ! 147: execve(strt, nargv, nenvp); ! 148: if (errno==ENOEXEC) { ! 149: scmdp = duplstr(strt, 0); ! 150: nargc += 1; ! 151: nargv -= 1; ! 152: nargv = vdupl(nargv); ! 153: nenvp = vdupl(nenvp); ! 154: while (sesp) { ! 155: freebuf(sesp->s_bpp); ! 156: sesp = sesp->s_next; ! 157: } ! 158: longjmp(restart, 1); ! 159: } ! 160: if (errno==E2BIG) { ! 161: e2big(nargv[0]); ! 162: return(-1); ! 163: } ! 164: } ! 165: ecantfind(nargv[0]); ! 166: return (-1); ! 167: } ! 168: ! 169: ALLOC_COUNT (undo) ! 170: ! 171: /* ! 172: * Process a redirection vector. ! 173: * Abort and return -1 at the first failure, return 0 for success. ! 174: * ! 175: * NB: In ordr to support redirection of builtins, an extra argument to this ! 176: * function has been addded. If undo is NULL, things remain as before, but if ! 177: * non-NULL it is taken to be the head of a list of undo items. As the list of ! 178: * redirections is processed, undo entries will be added to the head of the ! 179: * list, so that the caller will see the list in the appropriate order for ! 180: * undoing the redirections. ! 181: */ ! 182: redirect(iovp, undo) ! 183: char **iovp; ! 184: REDIR_UNDO ** undo; ! 185: { ! 186: register char **iopp; ! 187: register char *io; ! 188: register int op; ! 189: int u1, u2; ! 190: REDIR_UNDO * undo_node; ! 191: ! 192: for (iopp = iovp;(io = *iopp++)!=NULL; ) { ! 193: if (class(*io, MDIGI)) ! 194: u1 = *io++ - '0'; ! 195: else ! 196: u1 = *io=='<' ? 0 : 1; ! 197: ! 198: if (undo) { ! 199: /* ! 200: * Create and link in the undo node now. Stash away a ! 201: * spare copy of the original fd as well. Note that ! 202: * this may cause semantic changes in attempts to ! 203: * redirect from fds that would otherwise be closed, ! 204: * but that error was never diagnosed before anyway... ! 205: */ ! 206: ! 207: ALLOC_ALLOC (undo); ! 208: undo_node = (REDIR_UNDO *) salloc (sizeof (REDIR_UNDO)); ! 209: undo_node->ru_next = * undo; ! 210: undo_node->ru_oldfd = u1; ! 211: if ((undo_node->ru_newfd = dup (u1)) == -1) { ! 212: if (errno != EBADF) ! 213: eredirundo (); ! 214: } else { ! 215: fcntl (undo_node->ru_newfd, F_SETFD, ! 216: fcntl (undo_node->ru_newfd, F_GETFD, ! 217: 0) | FD_CLOEXEC); ! 218: } ! 219: * undo = undo_node; ! 220: } else ! 221: undo_node = NULL; ! 222: for (op=0; ; io+=1) ! 223: if (*io=='>') ! 224: op += 1; ! 225: else if (*io=='<') ! 226: op -= 1; ! 227: else ! 228: break; ! 229: if (*io++ == '&') { ! 230: if (op != 1 && op != -1) { ! 231: panic(7); ! 232: NOTREACHED; ! 233: } ! 234: u2 = *io++; ! 235: if (u2 == '-') { ! 236: close(u1); ! 237: continue; ! 238: } else if (!class(u2, MDIGI)) { ! 239: eredir(); ! 240: return (-1); ! 241: } else { ! 242: u2 -= '0'; ! 243: dup2(u2, u1); ! 244: continue; ! 245: } ! 246: } ! 247: for (io-=1; *io==' '||*io=='\t'; io+=1); ! 248: switch (op) { ! 249: case -2: /* Unquoted here */ ! 250: /* Fall through */ ! 251: case -1: /* Input file, quoted here */ ! 252: if ((u2 = open(io, 0)) < 0) { ! 253: ecantopen(io); ! 254: return (-1); ! 255: } ! 256: if (op == -2 && (u2 = evalhere(u2)) < 0) ! 257: return (-1); ! 258: dup2(u2, u1); ! 259: close(u2); ! 260: continue; ! 261: case 2: /* Append to output */ ! 262: if ((u2 = open(io, 1)) >= 0) { ! 263: lseek(u2, 0L, 2); ! 264: dup2(u2, u1); ! 265: close(u2); ! 266: continue; ! 267: } /* else fall through */ ! 268: case 1: /* Output file */ ! 269: if ((u2 = creat(io, 0666)) < 0) { ! 270: ecantmake(io); ! 271: return (-1); ! 272: } ! 273: dup2(u2, u1); ! 274: close(u2); ! 275: continue; ! 276: default: ! 277: panic(8); ! 278: NOTREACHED; ! 279: } ! 280: } ! 281: return (0); ! 282: } ! 283: ! 284: /* ! 285: * Undo a redirection sequence, reclaiming all the space for the undo nodes. ! 286: */ ! 287: redirundo (undo) ! 288: REDIR_UNDO ** undo; ! 289: { ! 290: REDIR_UNDO * undo_node; ! 291: ! 292: while ((undo_node = * undo) != NULL) { ! 293: * undo = undo_node->ru_next; ! 294: if (undo_node->ru_newfd == -1) ! 295: close (undo_node->ru_oldfd); ! 296: else { ! 297: dup2 (undo_node->ru_newfd, undo_node->ru_oldfd); ! 298: close (undo_node->ru_newfd); ! 299: } ! 300: ALLOC_FREE (undo); ! 301: sfree (undo_node); ! 302: } ! 303: return 0; ! 304: } ! 305: ! 306: ! 307: #ifdef NAMEPIPE ! 308: /* ! 309: * Create a named pipe. ! 310: */ ! 311: npipe(np) ! 312: register NODE *np; ! 313: { ! 314: register char *tmp; ! 315: register int f; ! 316: char *tvec[2]; ! 317: ! 318: tmp = shtmp(); ! 319: mknod(tmp, S_IFPIP, 0); ! 320: if ((f = clone()) == 0) { ! 321: if (np->n_type==NRPIPE) ! 322: strt[0] = '<'; ! 323: else ! 324: strt[0] = '>'; ! 325: strt[1] = '\0'; ! 326: tvec[0] = strcat(strt, tmp); ! 327: tvec[1] = NULL; ! 328: redirect(tvec, NULL); ! 329: command(np->n_auxp); ! 330: exit(slret); ! 331: NOTREACHED; ! 332: } ! 333: remember_temp (tmp); ! 334: strcpy(strt, tmp); ! 335: return; ! 336: } ! 337: #endif ! 338: ! 339: /* ! 340: * Search a path, perhaps repeatedly, for a file with access mode. ! 341: * Is called with paths == NULL to reset pointers. ! 342: * UGLY, but it works. ! 343: */ ! 344: ffind(paths, file, mode) ! 345: char *paths, *file; ! 346: { ! 347: register char c, *cp1, *cp2; ! 348: static char *fp, *ff, *fcp; ! 349: ! 350: if (paths==NULL) { ! 351: fp = ff = fcp = NULL; ! 352: return (0); ! 353: } ! 354: if (ff!=file) { ! 355: fp = fcp = paths; ! 356: ff = file; ! 357: if (index(ff, '/')!=NULL) ! 358: fcp = ""; ! 359: } ! 360: for (c=':'; c==':'; ) { ! 361: cp1 = fcp; ! 362: cp2 = strt; ! 363: while (*cp1 && *cp1!=':') ! 364: *cp2++ = *cp1++; ! 365: if (cp2 != strt) ! 366: *cp2++ = '/'; ! 367: c = *cp1++; ! 368: fcp = cp1; ! 369: cp1 = ff; ! 370: while (*cp2++ = *cp1++); ! 371: if (access(strt, mode)>=0) ! 372: return (1); ! 373: } ! 374: return (0); ! 375: } ! 376: ! 377: /* ! 378: * execute a non standard shell. ! 379: */ ! 380: exshell(vp) VAR *vp; ! 381: { ! 382: char *vshell; ! 383: register char *p; ! 384: ! 385: vshell = vp->v_strp; ! 386: while (*vshell && *vshell++ != '='); ! 387: /* Construct -name argv[0] */ ! 388: if ((p = rindex(vshell, '/')) != NULL) ! 389: p += 1; ! 390: else ! 391: p = vshell; ! 392: strcpy(strt, "-"); ! 393: strcat(strt, p); ! 394: /* Construct argv */ ! 395: nargv = makargl(); ! 396: nargv = addargl(nargv, "sh"); ! 397: nargv = addargl(nargv, duplstr(strt, 0)); ! 398: nargc = 2; ! 399: /* Construct envp */ ! 400: nenvp = makargl(); ! 401: nenvp = envlvar(nenvp); ! 402: /* Try exec */ ! 403: execve(vshell, nargv+1, nenvp); ! 404: ! 405: if (errno==ENOEXEC) { ! 406: fakearg(1, nargc, nargv, nenvp); ! 407: sargc = 0; ! 408: sargp = nargv+2; ! 409: sarg0 = nargv[1]; ! 410: nllflag = 0; ! 411: return session(SFILE, vshell); ! 412: } ! 413: fprintf(stderr, "No shell: %s\n", vshell); ! 414: exit(1); ! 415: } ! 416: ! 417: /* ! 418: * Check to see if we have mail. ! 419: */ ! 420: checkmail() ! 421: { ! 422: static long mailsize = -1; ! 423: struct stat sbuf; ! 424: ! 425: if (*vmail == '\0') ! 426: return; ! 427: if (stat(vmail, &sbuf)<0) { ! 428: mailsize = 0; ! 429: } else { ! 430: if (sbuf.st_size != 0 ! 431: && sbuf.st_size > mailsize) { ! 432: if (mailsize == -1) ! 433: prints("You have mail.\n"); ! 434: else ! 435: prints("You have new mail.\n"); ! 436: } ! 437: mailsize = sbuf.st_size; ! 438: } ! 439: } ! 440: ! 441: /* end of sh/exec2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.