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