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