|
|
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: ! 16: #define DEAD 1 /* Dead but haven't informed user yet */ ! 17: #define STOPPED 2 /* Job stopped */ ! 18: #define RUNNING 3 /* Just running */ ! 19: #define NEW 4 /* This process is brand new */ ! 20: ! 21: /* If process is dead, flags says how. */ ! 22: #define EXITED 1 ! 23: #define KILLED 2 ! 24: ! 25: #define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1) ! 26: #define makedead(p) (proc_state(p) = DEAD) ! 27: ! 28: #define proc_buf(p) (p->p_buffer->b_name) ! 29: #define proc_cmd(p) (p->p_name) ! 30: #define proc_state(p) (p->p_state) ! 31: ! 32: private Process *procs = 0; ! 33: ! 34: int ProcInput, ! 35: ProcOutput, ! 36: NumProcs = 0; ! 37: ! 38: char * ! 39: pstate(p) ! 40: Process *p; ! 41: { ! 42: switch (proc_state(p)) { ! 43: case NEW: ! 44: return "Pre-birth"; ! 45: ! 46: case STOPPED: ! 47: return "Stopped"; ! 48: ! 49: case RUNNING: ! 50: return "Running"; ! 51: ! 52: case DEAD: ! 53: if (p->p_howdied == EXITED) { ! 54: if (p->p_reason == 0) ! 55: return "Done"; ! 56: return sprint("Exit %d", p->p_reason); ! 57: } ! 58: return sprint("Killed %d", p->p_reason); ! 59: ! 60: default: ! 61: return "Unknown state"; ! 62: } ! 63: } ! 64: ! 65: static Process * ! 66: proc_pid(pid) ! 67: { ! 68: register Process *p; ! 69: ! 70: for (p = procs; p != 0; p = p->p_next) ! 71: if (p->p_portpid == pid) ! 72: break; ! 73: ! 74: return p; ! 75: } ! 76: ! 77: procs_read() ! 78: { ! 79: struct header { ! 80: int pid; ! 81: int nbytes; ! 82: } header; ! 83: int n; ! 84: long nbytes; ! 85: static int here = NO; ! 86: ! 87: if (here) ! 88: return; ! 89: sighold(SIGCHLD); /* block any other children */ ! 90: here = YES; ! 91: for (;;) { ! 92: (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes); ! 93: if (nbytes < sizeof header) ! 94: break; ! 95: n = read(ProcInput, (char *) &header, sizeof header); ! 96: if (n != sizeof header) ! 97: finish(1); ! 98: read_proc(header.pid, header.nbytes); ! 99: } ! 100: here = NO; ! 101: sigrelse(SIGCHLD); ! 102: } ! 103: ! 104: read_proc(pid, nbytes) ! 105: int pid; ! 106: register int nbytes; ! 107: { ! 108: register Process *p; ! 109: int n; ! 110: char ibuf[512]; ! 111: ! 112: if ((p = proc_pid(pid)) == 0) { ! 113: printf("\riproc: unknown pid (%d)", pid); ! 114: return; ! 115: } ! 116: if (proc_state(p) == NEW) { ! 117: int rpid; ! 118: /* pid of real child, not of portsrv */ ! 119: ! 120: doread(ProcInput, (char *) &rpid, nbytes); ! 121: nbytes -= sizeof rpid; ! 122: p->p_pid = rpid; ! 123: p->p_state = RUNNING; ! 124: } ! 125: ! 126: if (nbytes == EOF) { /* okay to clean up this process */ ! 127: proc_close(p); ! 128: makedead(p); ! 129: return; ! 130: } ! 131: ! 132: while (nbytes > 0) { ! 133: n = min((sizeof ibuf) - 1, nbytes); ! 134: doread(ProcInput, ibuf, n); ! 135: ibuf[n] = 0; /* Null terminate for convenience */ ! 136: nbytes -= n; ! 137: proc_rec(p, ibuf); ! 138: } ! 139: } ! 140: ! 141: ProcKill() ! 142: { ! 143: proc_kill(curbuf->b_process, SIGKILL); ! 144: } ! 145: ! 146: ProcInt() ! 147: { ! 148: proc_kill(curbuf->b_process, SIGINT); ! 149: } ! 150: ! 151: ProcQuit() ! 152: { ! 153: proc_kill(curbuf->b_process, SIGQUIT); ! 154: } ! 155: ! 156: private ! 157: proc_close(p) ! 158: Process *p; ! 159: { ! 160: sighold(SIGCHLD); ! 161: ! 162: if (p->p_toproc >= 0) { ! 163: (void) close(p->p_toproc); ! 164: p->p_toproc = -1; /* writes will fail */ ! 165: NumProcs -= 1; ! 166: } ! 167: ! 168: sigrelse(SIGCHLD); ! 169: } ! 170: ! 171: do_rtp(mp) ! 172: register Mark *mp; ! 173: { ! 174: register Process *p = curbuf->b_process; ! 175: Line *line1 = curline, ! 176: *line2 = mp->m_line; ! 177: int char1 = curchar, ! 178: char2 = mp->m_char; ! 179: char *gp; ! 180: ! 181: if (isdead(p) || p->p_buffer != curbuf) ! 182: return; ! 183: ! 184: (void) fixorder(&line1, &char1, &line2, &char2); ! 185: while (line1 != line2->l_next) { ! 186: gp = ltobuf(line1, genbuf) + char1; ! 187: if (line1 == line2) ! 188: gp[char2] = '\0'; ! 189: else ! 190: strcat(gp, "\n"); ! 191: (void) write(p->p_toproc, gp, strlen(gp)); ! 192: line1 = line1->l_next; ! 193: char1 = 0; ! 194: } ! 195: } ! 196: ! 197: /* VARARGS3 */ ! 198: ! 199: private ! 200: proc_strt(bufname, clobber, va_alist) ! 201: char *bufname; ! 202: va_dcl ! 203: { ! 204: Window *owind = curwind; ! 205: int toproc[2], ! 206: pid; ! 207: Process *newp; ! 208: Buffer *newbuf; ! 209: char *argv[32], ! 210: *cp, ! 211: foo[10], ! 212: cmdbuf[128]; ! 213: int i; ! 214: va_list ap; ! 215: ! 216: isprocbuf(bufname); /* make sure BUFNAME is either nonexistant ! 217: or is of type B_PROCESS */ ! 218: dopipe(toproc); ! 219: ! 220: sighold(SIGCHLD); ! 221: #ifdef SIGWINCH ! 222: sighold(SIGWINCH); ! 223: #endif ! 224: switch (pid = fork()) { ! 225: case -1: ! 226: pclose(toproc); ! 227: complain("[Fork failed.]"); ! 228: ! 229: case 0: ! 230: sigrelse(SIGCHLD); ! 231: #ifdef SIGWINCH ! 232: sigrelse(SIGWINCH); ! 233: #endif ! 234: argv[0] = "portsrv"; ! 235: argv[1] = foo; ! 236: sprintf(foo, "%d", ProcInput); ! 237: va_start(ap); ! 238: make_argv(&argv[2], ap); ! 239: va_end(ap); ! 240: (void) dup2(toproc[0], 0); ! 241: (void) dup2(ProcOutput, 1); ! 242: (void) dup2(ProcOutput, 2); ! 243: pclose(toproc); ! 244: execv(Portsrv, argv); ! 245: printf("execl failed\n"); ! 246: _exit(1); ! 247: } ! 248: ! 249: newp = (Process *) malloc(sizeof *newp); ! 250: newp->p_next = procs; ! 251: newp->p_state = NEW; ! 252: newp->p_cmd = 0; ! 253: ! 254: cmdbuf[0] = '\0'; ! 255: va_start(ap); ! 256: while (cp = va_arg(ap, char *)) ! 257: sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp); ! 258: va_end(ap); ! 259: newp->p_name = copystr(cmdbuf); ! 260: procs = newp; ! 261: newp->p_portpid = pid; ! 262: newp->p_pid = -1; ! 263: ! 264: newbuf = do_select((Window *) 0, bufname); ! 265: newbuf->b_type = B_PROCESS; ! 266: newp->p_buffer = newbuf; ! 267: newbuf->b_process = newp; /* sorta circular, eh? */ ! 268: pop_wind(bufname, clobber, B_PROCESS); ! 269: ToLast(); ! 270: if (!bolp()) ! 271: LineInsert(1); ! 272: /* Pop_wind() after everything is set up; important! ! 273: Bindings won't work right unless newbuf->b_process is already ! 274: set up BEFORE NEWBUF is first SetBuf()'d. */ ! 275: newp->p_mark = MakeMark(curline, curchar, M_FLOATER); ! 276: ! 277: newp->p_toproc = toproc[1]; ! 278: newp->p_reason = 0; ! 279: NumProcs += 1; ! 280: (void) close(toproc[0]); ! 281: SetWind(owind); ! 282: sigrelse(SIGCHLD); ! 283: #ifdef SIGWINCH ! 284: sigrelse(SIGWINCH); ! 285: #endif ! 286: } ! 287: ! 288: pinit() ! 289: { ! 290: int p[2]; ! 291: ! 292: (void) signal(SIGCHLD, proc_child); ! 293: (void) pipe(p); ! 294: ProcInput = p[0]; ! 295: ProcOutput = p[1]; ! 296: (void) signal(INPUT_SIG, procs_read); ! 297: sighold(INPUT_SIG); /* Released during terminal read */ ! 298: } ! 299: ! 300: doread(fd, buf, n) ! 301: char *buf; ! 302: { ! 303: int nread; ! 304: ! 305: if ((nread = read(fd, buf, n)) != n) ! 306: complain("Cannot read %d (got %d) bytes.", n, nread); ! 307: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.