|
|
1.1 ! root 1: /*************************************************************************** ! 2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * ! 3: * is provided to you without charge, and with no warranty. You may give * ! 4: * away copies of JOVE, including sources, provided that this notice is * ! 5: * included in all the files. * ! 6: ***************************************************************************/ ! 7: ! 8: #ifdef BSD4_2 ! 9: # include <sys/wait.h> ! 10: #else ! 11: # include <wait.h> ! 12: #endif ! 13: #include <signal.h> ! 14: #include <sgtty.h> ! 15: #include <errno.h> ! 16: ! 17: #define DEAD 1 /* dead but haven't informed user yet */ ! 18: #define STOPPED 2 /* job stopped */ ! 19: #define RUNNING 3 /* just running */ ! 20: #define NEW 4 /* brand new, never been ... received no input */ ! 21: ! 22: /* If process is dead, flags says how. */ ! 23: #define EXITED 1 ! 24: #define KILLED 2 ! 25: ! 26: #define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_fd == -1) ! 27: #define makedead(p) (proc_state(p) = DEAD) ! 28: ! 29: #define proc_buf(p) (p->p_buffer->b_name) ! 30: #define proc_cmd(p) (p->p_name) ! 31: #define proc_state(p) (p->p_state) ! 32: ! 33: private Process *procs = 0; ! 34: ! 35: long global_fd = 1; ! 36: int NumProcs = 0; ! 37: ! 38: #ifdef BRLUNIX ! 39: extern struct sg_brl sg1; ! 40: #else ! 41: extern struct sgttyb sg1; ! 42: #endif ! 43: ! 44: extern struct tchars tc1; ! 45: ! 46: #ifdef TIOCSLTC ! 47: extern struct ltchars ls1; ! 48: #endif ! 49: ! 50: char * ! 51: pstate(p) ! 52: Process *p; ! 53: { ! 54: switch (proc_state(p)) { ! 55: case STOPPED: ! 56: return "Stopped"; ! 57: ! 58: case RUNNING: ! 59: return "Running"; ! 60: ! 61: case DEAD: ! 62: if (p->p_howdied == EXITED) { ! 63: if (p->p_reason == 0) ! 64: return "Done"; ! 65: return sprint("Exit %d", p->p_reason); ! 66: } ! 67: return sprint("Killed %d", p->p_reason); ! 68: ! 69: case NEW: ! 70: return "New"; ! 71: ! 72: default: ! 73: return "Unknown state"; ! 74: } ! 75: } ! 76: ! 77: static Process * ! 78: proc_pid(pid) ! 79: { ! 80: register Process *p; ! 81: ! 82: for (p = procs; p != 0; p = p->p_next) ! 83: if (p->p_pid == pid) ! 84: break; ! 85: ! 86: return p; ! 87: } ! 88: ! 89: read_proc(fd) ! 90: register int fd; ! 91: { ! 92: register Process *p; ! 93: unsigned int n; ! 94: char ibuf[1024]; ! 95: ! 96: for (p = procs; p != 0; p = p->p_next) ! 97: if (p->p_fd == fd) ! 98: break; ! 99: ! 100: if (p == 0) { ! 101: printf("\riproc: unknown fd %d", fd); ! 102: return; ! 103: } ! 104: ! 105: n = read(fd, ibuf, sizeof(ibuf) - 1); ! 106: if (n == -1 && errno == EIO) { ! 107: if (proc_state(p) == NEW) ! 108: return; ! 109: proc_close(p); ! 110: makedead(p); ! 111: return; ! 112: } else { ! 113: if (proc_state(p) != RUNNING) { ! 114: proc_state(p) = RUNNING; ! 115: UpdModLine = YES; ! 116: } ! 117: } ! 118: if (n <= 0) { ! 119: if (n == 0) ! 120: strcpy(ibuf, "[Process EOF]"); ! 121: else ! 122: sprintf(ibuf, "\n[pty read error: %d]\n", errno); ! 123: } else ! 124: ibuf[n] = '\0'; ! 125: proc_rec(p, ibuf); ! 126: } ! 127: ! 128: ProcKill() ! 129: { ! 130: register Buffer *b; ! 131: Process *buf_to_proc(); ! 132: char *bname; ! 133: ! 134: bname = ask_buf(curbuf); ! 135: ! 136: if ((b = buf_exists(bname)) == 0) ! 137: complain("[No such buffer]"); ! 138: if (b->b_process == 0) ! 139: complain("%s not tied to a process.", bname); ! 140: proc_kill(b->b_process, SIGKILL); ! 141: } ! 142: ! 143: ProcCont() ! 144: { ! 145: Process *p; ! 146: ! 147: if ((p = curbuf->b_process) == 0) ! 148: complain("[No process]"); ! 149: if (p->p_state != DEAD) { ! 150: proc_kill(p, SIGCONT); ! 151: p->p_state = RUNNING; ! 152: } ! 153: } ! 154: ! 155: ProcEof() ! 156: { ! 157: send_p(tc1.t_eofc); ! 158: } ! 159: ! 160: ProcInt() ! 161: { ! 162: send_p(tc1.t_intrc); ! 163: } ! 164: ! 165: ProcQuit() ! 166: { ! 167: send_p(tc1.t_quitc); ! 168: } ! 169: ! 170: ProcStop() ! 171: { ! 172: send_p(ls1.t_suspc); ! 173: } ! 174: ! 175: ProcDStop() ! 176: { ! 177: send_p(ls1.t_dsuspc); ! 178: } ! 179: ! 180: send_p(c) ! 181: char c; ! 182: { ! 183: Process *p; ! 184: char buf[2]; ! 185: ! 186: if ((p = curbuf->b_process) == 0) ! 187: complain("[No process]"); ! 188: ToLast(); ! 189: buf[0] = c; ! 190: buf[1] = '\0'; ! 191: proc_rec(p, buf); ! 192: (void) write(p->p_fd, &c, 1); ! 193: } ! 194: ! 195: private ! 196: proc_close(p) ! 197: Process *p; ! 198: { ! 199: sighold(SIGCHLD); /* be mutually exclusive */ ! 200: ! 201: if (p->p_fd >= 0) { ! 202: (void) close(p->p_fd); ! 203: global_fd &= ~(1L << p->p_fd); ! 204: NumProcs -= 1; ! 205: p->p_fd = -1; ! 206: } ! 207: ! 208: sigrelse(SIGCHLD); ! 209: } ! 210: ! 211: do_rtp(mp) ! 212: register Mark *mp; ! 213: { ! 214: register Process *p = curbuf->b_process; ! 215: Line *line1 = curline, ! 216: *line2 = mp->m_line; ! 217: int char1 = curchar, ! 218: char2 = mp->m_char; ! 219: char *gp; ! 220: int nbytes; ! 221: ! 222: if (isdead(p) || p->p_buffer != curbuf) ! 223: return; ! 224: ! 225: (void) fixorder(&line1, &char1, &line2, &char2); ! 226: while (line1 != line2->l_next) { ! 227: gp = ltobuf(line1, genbuf) + char1; ! 228: if (line1 == line2) ! 229: gp[char2] = '\0'; ! 230: else ! 231: strcat(gp, "\n"); ! 232: if (nbytes = strlen(gp)) ! 233: (void) write(p->p_fd, gp, nbytes); ! 234: line1 = line1->l_next; ! 235: char1 = 0; ! 236: } ! 237: } ! 238: ! 239: /* VARARGS2 */ ! 240: ! 241: private ! 242: proc_strt(bufname, clobber, va_alist) ! 243: char *bufname; ! 244: va_dcl ! 245: { ! 246: va_list ap; ! 247: char *argv[32], ! 248: *cp; ! 249: Window *owind = curwind; ! 250: int pid; ! 251: Process *newp; ! 252: Buffer *newbuf; ! 253: int i, ! 254: ptyfd, ! 255: ttyfd, ! 256: ldisc, ! 257: lmode; ! 258: register char *s, ! 259: *t; ! 260: extern int errno; ! 261: static char ttybuf[11], ! 262: ptybuf[11]; ! 263: char cmdbuf[128]; ! 264: #ifdef BRLUNIX ! 265: struct sg_brl sg; ! 266: #else ! 267: struct sgttyb sg; ! 268: #endif ! 269: ! 270: #ifdef TIOCGWINSZ ! 271: struct winsize win; ! 272: #else ! 273: # ifdef BTL_BLIT ! 274: # include <sys/jioctl.h> ! 275: struct jwinsize jwin; ! 276: # endif ! 277: #endif ! 278: ! 279: isprocbuf(bufname); /* make sure BUFNAME is either nonexistant ! 280: or is of type B_PROCESS */ ! 281: for (s = "pqrs"; *s; s++) { ! 282: for (t = "0123456789abcdef"; *t; t++) { ! 283: sprintf(ptybuf, "/dev/pty%c%c", *s, *t); ! 284: if ((ptyfd = open(ptybuf, 2)) >= 0) { ! 285: strcpy(ttybuf, ptybuf); ! 286: ttybuf[5] = 't'; ! 287: /* make sure both ends are available */ ! 288: if ((i = open(ttybuf, 2)) < 0) ! 289: continue; ! 290: (void) close(i); ! 291: goto out; ! 292: } ! 293: } ! 294: } ! 295: ! 296: out: if (s == 0 && t == 0) ! 297: complain("[Out of ptys!]"); ! 298: ! 299: #ifdef TIOCGETD ! 300: (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc); ! 301: #endif ! 302: #ifdef TIOCLGET ! 303: (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode); ! 304: #endif ! 305: #ifdef TIOCGWINSZ ! 306: (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win); ! 307: #else ! 308: # ifdef BTL_BLIT ! 309: (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin); ! 310: # endif /* BTL_BLIT */ ! 311: #endif ! 312: ! 313: sighold(SIGCHLD); ! 314: #ifdef SIGWINCH ! 315: sighold(SIGWINCH); ! 316: #endif ! 317: switch (pid = fork()) { ! 318: case -1: ! 319: (void) close(ptyfd); ! 320: message("[Fork failed!]"); ! 321: goto fail; ! 322: ! 323: case 0: ! 324: sigrelse(SIGCHLD); ! 325: #ifdef SIGWINCH ! 326: sigrelse(SIGWINCH); ! 327: #endif ! 328: for (i = 0; i < 32; i++) ! 329: (void) close(i); ! 330: ! 331: #ifdef TIOCNOTTY ! 332: if ((i = open("/dev/tty", 2)) >= 0) { ! 333: (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0); ! 334: (void) close(i); ! 335: } ! 336: #endif ! 337: if ((ttyfd = open(ttybuf, 2)) < 0) ! 338: exit(-1); ! 339: (void) dup2(ttyfd, 1); ! 340: (void) dup2(ttyfd, 2); ! 341: ! 342: #ifdef TIOCSETD ! 343: (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc); ! 344: #endif ! 345: #ifdef TIOCLSET ! 346: (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode); ! 347: #endif ! 348: #ifdef TIOCSETC ! 349: (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1); ! 350: #endif ! 351: #ifdef TIOCSLTC ! 352: (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1); ! 353: #endif ! 354: ! 355: #ifdef TIOCGWINSZ ! 356: # ifdef SIGWINCH ! 357: (void) signal(SIGWINCH, SIG_IGN); ! 358: # endif ! 359: win.ws_row = curwind->w_height; ! 360: (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win); ! 361: #else ! 362: # ifdef BTL_BLIT ! 363: jwin.bytesy = curwind->w_height; ! 364: (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin); ! 365: # endif ! 366: #endif ! 367: ! 368: sg = sg1; ! 369: sg.sg_flags &= ~(ECHO | CRMOD); ! 370: (void) stty(0, &sg); ! 371: ! 372: i = getpid(); ! 373: (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i); ! 374: (void) setpgrp(0, i); ! 375: va_start(ap); ! 376: make_argv(argv, ap); ! 377: va_end(ap); ! 378: execv(argv[0], &argv[1]); ! 379: (void) write(1, "execve failed!\n", 15); ! 380: _exit(errno + 1); ! 381: } ! 382: ! 383: newp = (Process *) emalloc(sizeof *newp); ! 384: ! 385: newp->p_fd = ptyfd; ! 386: newp->p_pid = pid; ! 387: ! 388: newbuf = do_select((Window *) 0, bufname); ! 389: newbuf->b_type = B_PROCESS; ! 390: newp->p_buffer = newbuf; ! 391: newbuf->b_process = newp; /* sorta circular, eh? */ ! 392: pop_wind(bufname, clobber, B_PROCESS); ! 393: /* Pop_wind() after everything is set up; important! ! 394: Bindings won't work right unless newbuf->b_process is already ! 395: set up BEFORE NEWBUF is first SetBuf()'d. */ ! 396: ToLast(); ! 397: if (!bolp()) ! 398: LineInsert(1); ! 399: ! 400: cmdbuf[0] = '\0'; ! 401: va_start(ap); ! 402: while (cp = va_arg(ap, char *)) ! 403: sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++); ! 404: va_end(ap); ! 405: ! 406: newp->p_name = copystr(cmdbuf); ! 407: newp->p_state = NEW; ! 408: newp->p_reason = 0; ! 409: newp->p_mark = MakeMark(curline, curchar, M_FLOATER); ! 410: ! 411: newp->p_next = procs; ! 412: procs = newp; ! 413: NumProcs += 1; ! 414: global_fd |= 1L << newp->p_fd; ! 415: SetWind(owind); ! 416: ! 417: fail: sigrelse(SIGCHLD); ! 418: #ifdef SIGWINCH ! 419: sigrelse(SIGWINCH); ! 420: #endif ! 421: } ! 422: ! 423: pinit() ! 424: { ! 425: (void) signal(SIGCHLD, proc_child); ! 426: } ! 427:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.