|
|
1.1 ! root 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_toproc == -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_toproc, /* read p_fromproc and write p_toproc */ ! 38: p_portpid, /* Pid of child (the portsrv) */ ! 39: p_pid; /* Pid of real child i.e. not portsrv */ ! 40: Buffer *p_buffer; /* Add output to end of this buffer */ ! 41: char *p_name; /* ... */ ! 42: char p_state, /* State */ ! 43: p_howdied, /* Killed? or Exited? */ ! 44: p_reason, /* If signaled, p_reason is the signal; else ! 45: it is the the exit code */ ! 46: p_eof; /* Received EOF, so can be free'd up */ ! 47: Mark *p_mark; /* Where output left us. */ ! 48: data_obj ! 49: *p_cmd; /* Command to call when process dies */ ! 50: } *procs = 0, ! 51: *cur_proc = 0; ! 52: ! 53: char proc_prompt[80] = "% "; ! 54: ! 55: int ProcInput, ! 56: ProcOutput, ! 57: NumProcs = 0; ! 58: ! 59: static char * ! 60: pstate(p) ! 61: Process *p; ! 62: { ! 63: switch (proc_state(p)) { ! 64: case NEW: ! 65: return "Pre-birth"; ! 66: ! 67: case STOPPED: ! 68: return "Stopped"; ! 69: ! 70: case RUNNING: ! 71: return "Running"; ! 72: ! 73: case DEAD: ! 74: if (p->p_howdied == EXITED) { ! 75: if (p->p_reason == 0) ! 76: return "Done"; ! 77: return sprint("[Exit %d]", p->p_reason); ! 78: } ! 79: return sprint("[Killed %d]", p->p_reason); ! 80: ! 81: default: ! 82: return "Unknown state."; ! 83: } ! 84: } ! 85: ! 86: static Process * ! 87: proc_pid(pid) ! 88: { ! 89: register Process *p; ! 90: ! 91: for (p = procs; p != 0; p = p->p_next) ! 92: if (p->p_portpid == pid) ! 93: break; ! 94: ! 95: return p; ! 96: } ! 97: ! 98: procs_read() ! 99: { ! 100: struct header { ! 101: int pid; ! 102: int nbytes; ! 103: } header; ! 104: int n; ! 105: long nbytes; ! 106: static int here = 0; ! 107: ! 108: if (here) ! 109: return; ! 110: sighold(SIGCHLD); /* Block any other children. */ ! 111: here++; ! 112: for (;;) { ! 113: (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes); ! 114: if (nbytes < sizeof header) ! 115: break; ! 116: n = read(ProcInput, (char *) &header, sizeof header); ! 117: if (n != sizeof header) ! 118: finish(1); ! 119: read_proc(header.pid, header.nbytes); ! 120: } ! 121: redisplay(); ! 122: here = 0; ! 123: sigrelse(SIGCHLD); ! 124: } ! 125: ! 126: read_proc(pid, nbytes) ! 127: int pid; ! 128: register int nbytes; ! 129: { ! 130: register Process *p; ! 131: int n; ! 132: char ibuf[512]; ! 133: ! 134: if ((p = proc_pid(pid)) == 0) { ! 135: printf("\riproc: unknown pid (%d)", pid); ! 136: return; ! 137: } ! 138: if (proc_state(p) == NEW) { ! 139: int rpid; ! 140: /* Pid of real child, not of portsrv. */ ! 141: ! 142: doread(ProcInput, (char *) &rpid, nbytes); ! 143: nbytes -= sizeof rpid; ! 144: p->p_pid = rpid; ! 145: p->p_state = RUNNING; ! 146: } ! 147: ! 148: if (nbytes == EOF) { /* Okay to clean up this process */ ! 149: p->p_eof = 1; ! 150: NumProcs--; /* As far as getch() in main is concerned */ ! 151: return; ! 152: } ! 153: ! 154: while (nbytes > 0) { ! 155: n = min((sizeof ibuf) - 1, nbytes); ! 156: doread(ProcInput, ibuf, n); ! 157: ibuf[n] = 0; /* Null terminate for convenience */ ! 158: nbytes -= n; ! 159: proc_rec(p, ibuf); ! 160: } ! 161: } ! 162: ! 163: ProcKill() ! 164: { ! 165: proc_kill(cur_proc, SIGKILL); ! 166: } ! 167: ! 168: ProcInt() ! 169: { ! 170: proc_kill(cur_proc, SIGINT); ! 171: } ! 172: ! 173: ProcQuit() ! 174: { ! 175: proc_kill(cur_proc, SIGQUIT); ! 176: } ! 177: ! 178: static ! 179: proc_close(p) ! 180: Process *p; ! 181: { ! 182: (void) close(p->p_toproc); ! 183: p->p_toproc = -1; /* Writes will fail. */ ! 184: } ! 185: ! 186: do_rtp(mp) ! 187: register Mark *mp; ! 188: { ! 189: register Process *p = cur_proc; ! 190: Line *line1 = curline, ! 191: *line2 = mp->m_line; ! 192: int char1 = curchar, ! 193: char2 = mp->m_char; ! 194: char *gp; ! 195: ! 196: if (isdead(p) || p->p_buffer != curbuf) ! 197: return; ! 198: ! 199: (void) fixorder(&line1, &char1, &line2, &char2); ! 200: while (line1 != line2->l_next) { ! 201: gp = ltobuf(line1, genbuf) + char1; ! 202: if (line1 == line2) ! 203: gp[char2] = '\0'; ! 204: else ! 205: strcat(gp, "\n"); ! 206: (void) write(p->p_toproc, gp, strlen(gp)); ! 207: line1 = line1->l_next; ! 208: char1 = 0; ! 209: } ! 210: } ! 211: ! 212: /* VARARGS2 */ ! 213: ! 214: static ! 215: proc_strt(bufname, procname, cmd) ! 216: char *bufname, ! 217: *procname, ! 218: *cmd; ! 219: { ! 220: Window *owind = curwind; ! 221: int toproc[2], ! 222: pid; ! 223: Process *newp; ! 224: Buffer *bp; ! 225: char *args[25], ! 226: **cp, ! 227: foo[10], ! 228: cmdbuf[128]; ! 229: int i; ! 230: ! 231: bp = buf_exists(bufname); ! 232: if (bp != 0 && IsModified(bp) && bp->b_type != B_IPROCESS && bp->b_type != B_PROCESS) ! 233: complain("Command would over-write buffer %s.", procname, bufname); ! 234: pop_wind(bufname, 1, B_IPROCESS); ! 235: ! 236: dopipe(toproc); ! 237: ! 238: switch (pid = fork()) { ! 239: case -1: ! 240: pclose(toproc); ! 241: complain("[Fork failed.]"); ! 242: ! 243: case 0: ! 244: args[0] = "portsrv"; ! 245: args[1] = foo; ! 246: sprintf(foo, "%d", ProcInput); ! 247: for (i = 0, cp = &cmd; cp[i] != 0; i++) ! 248: args[2 + i] = cp[i]; ! 249: args[2 + i] = 0; ! 250: (void) dup2(toproc[0], 0); ! 251: (void) dup2(ProcOutput, 1); ! 252: (void) dup2(ProcOutput, 2); ! 253: pclose(toproc); ! 254: execv(PORTSRV, args); ! 255: printf("Execl failed.\n"); ! 256: _exit(1); ! 257: } ! 258: ! 259: sighold(SIGCHLD); ! 260: cur_proc = newp = (Process *) malloc(sizeof *newp); ! 261: newp->p_next = procs; ! 262: newp->p_state = NEW; ! 263: newp->p_mark = MakeMark(curline, curchar, FLOATER); ! 264: newp->p_cmd = 0; ! 265: ! 266: cp = &cmd + 1; ! 267: cmdbuf[0] = '\0'; ! 268: while (*cp != 0) ! 269: sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", *cp++); ! 270: newp->p_name = copystr(cmdbuf); ! 271: procs = newp; ! 272: newp->p_portpid = pid; ! 273: newp->p_pid = -1; ! 274: newp->p_buffer = curbuf; ! 275: newp->p_toproc = toproc[1]; ! 276: newp->p_reason = 0; ! 277: newp->p_eof = 0; ! 278: NumProcs++; ! 279: (void) close(toproc[0]); ! 280: sigrelse(SIGCHLD); ! 281: SetWind(owind); ! 282: } ! 283: ! 284: pinit() ! 285: { ! 286: int p[2]; ! 287: ! 288: (void) signal(SIGCHLD, proc_child); ! 289: (void) pipe(p); ! 290: ProcInput = p[0]; ! 291: ProcOutput = p[1]; ! 292: (void) signal(INPUT_SIG, procs_read); ! 293: sighold(INPUT_SIG); /* Released during terminal read */ ! 294: } ! 295: ! 296: doread(fd, buf, n) ! 297: char *buf; ! 298: { ! 299: int nread; ! 300: ! 301: if ((nread = read(fd, buf, n)) != n) ! 302: complain("Cannot read %d (got %d) bytes.", n, nread); ! 303: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.