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: }