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