|
|
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 <signal.h> ! 13: #include <sgtty.h> ! 14: #include "wait.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) == NULL || 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: File *ProcInput; ! 35: int ProcOutput, ! 36: kbd_pid = 0, ! 37: NumProcs = 0; ! 38: ! 39: private Process * ! 40: proc_pid(pid) ! 41: int pid; ! 42: { ! 43: register Process *p; ! 44: ! 45: for (p = procs; p != 0; p = p->p_next) ! 46: if (p->p_portpid == pid) ! 47: break; ! 48: ! 49: return p; ! 50: } ! 51: ! 52: void ! 53: read_proc(pid, nbytes) ! 54: int pid; ! 55: register int nbytes; ! 56: { ! 57: register Process *p; ! 58: int n; ! 59: char ibuf[512]; ! 60: ! 61: if ((p = proc_pid(pid)) == 0) { ! 62: writef("\riproc: unknown pid (%d)", pid); ! 63: return; ! 64: } ! 65: ! 66: if (proc_state(p) == NEW) { ! 67: int rpid; ! 68: /* pid of real child, not of portsrv */ ! 69: ! 70: (void) f_readn(ProcInput, (char *) &rpid, sizeof (int)); ! 71: p->p_pid = rpid; ! 72: p->p_state = RUNNING; ! 73: return; ! 74: } ! 75: ! 76: if (nbytes == EOF) { /* okay to clean up this process */ ! 77: int status, pid; ! 78: ! 79: f_readn(ProcInput, &status, sizeof (int)); ! 80: do { ! 81: pid = wait((int *) 0); ! 82: if (pid < 0) ! 83: break; ! 84: kill_off(pid, status); ! 85: } while (pid != p->p_portpid); ! 86: proc_close(p); ! 87: makedead(p); ! 88: return; ! 89: } ! 90: ! 91: while (nbytes > 0) { ! 92: n = min((sizeof ibuf) - 1, nbytes); ! 93: f_readn(ProcInput, ibuf, n); ! 94: ibuf[n] = 0; /* Null terminate for convenience */ ! 95: nbytes -= n; ! 96: proc_rec(p, ibuf); ! 97: } ! 98: } ! 99: ! 100: void ! 101: ProcKill() ! 102: { ! 103: proc_kill(curbuf->b_process, SIGKILL); ! 104: } ! 105: ! 106: void ! 107: ProcInt() ! 108: { ! 109: proc_kill(curbuf->b_process, SIGINT); ! 110: } ! 111: ! 112: void ! 113: ProcQuit() ! 114: { ! 115: proc_kill(curbuf->b_process, SIGQUIT); ! 116: } ! 117: ! 118: private void ! 119: proc_close(p) ! 120: Process *p; ! 121: { ! 122: if (p->p_toproc >= 0) { ! 123: (void) close(p->p_toproc); ! 124: p->p_toproc = -1; /* writes will fail */ ! 125: NumProcs -= 1; ! 126: } ! 127: } ! 128: ! 129: void ! 130: proc_write(p, buf, nbytes) ! 131: Process *p; ! 132: char *buf; ! 133: size_t nbytes; ! 134: { ! 135: (void) write(p->p_toproc, buf, nbytes); ! 136: } ! 137: ! 138: ! 139: #ifdef STDARGS ! 140: private void ! 141: proc_strt(char *bufname, int clobber, ...) ! 142: #else ! 143: private /*VARARGS3*/ void ! 144: proc_strt(bufname, clobber, va_alist) ! 145: char *bufname; ! 146: int clobber; ! 147: va_dcl ! 148: #endif ! 149: { ! 150: Window *owind = curwind; ! 151: int toproc[2], ! 152: pid; ! 153: Process *newp; ! 154: Buffer *newbuf; ! 155: char *argv[32], ! 156: *cp, ! 157: foo[10], ! 158: cmdbuf[128]; ! 159: int i; ! 160: va_list ap; ! 161: ! 162: isprocbuf(bufname); /* make sure BUFNAME is either nonexistant ! 163: or is of type B_PROCESS */ ! 164: dopipe(toproc); ! 165: ! 166: switch (pid = fork()) { ! 167: case -1: ! 168: pclose(toproc); ! 169: complain("[Fork failed.]"); ! 170: ! 171: case 0: ! 172: argv[0] = "portsrv"; ! 173: va_init(ap, clobber); ! 174: make_argv(&argv[1], ap); ! 175: va_end(ap); ! 176: (void) dup2(toproc[0], 0); ! 177: (void) dup2(ProcOutput, 1); ! 178: (void) dup2(ProcOutput, 2); ! 179: pclose(toproc); ! 180: execv(Portsrv, argv); ! 181: writef("execl failed\n"); ! 182: _exit(1); ! 183: } ! 184: ! 185: newp = (Process *) malloc(sizeof *newp); ! 186: newp->p_next = procs; ! 187: newp->p_state = NEW; ! 188: ! 189: cmdbuf[0] = '\0'; ! 190: va_init(ap, clobber); ! 191: while (cp = va_arg(ap, char *)) ! 192: swritef(&cmdbuf[strlen(cmdbuf)], "%s ", cp); ! 193: va_end(ap); ! 194: va_init(ap, clobber); ! 195: newp->p_name = copystr(cmdbuf); ! 196: procs = newp; ! 197: newp->p_portpid = pid; ! 198: newp->p_pid = -1; ! 199: ! 200: newbuf = do_select((Window *) 0, bufname); ! 201: newbuf->b_type = B_PROCESS; ! 202: newp->p_buffer = newbuf; ! 203: newbuf->b_process = newp; /* sorta circular, eh? */ ! 204: pop_wind(bufname, clobber, B_PROCESS); ! 205: ToLast(); ! 206: if (!bolp()) ! 207: LineInsert(1); ! 208: /* Pop_wind() after everything is set up; important! ! 209: Bindings won't work right unless newbuf->b_process is already ! 210: set up BEFORE NEWBUF is first SetBuf()'d. */ ! 211: newp->p_mark = MakeMark(curline, curchar, M_FLOATER); ! 212: newp->p_dbx_mode = NO; ! 213: ! 214: newp->p_toproc = toproc[1]; ! 215: newp->p_reason = 0; ! 216: NumProcs += 1; ! 217: if (NumProcs == 1) ! 218: (void) kbd_strt(); ! 219: (void) close(toproc[0]); ! 220: SetWind(owind); ! 221: } ! 222: ! 223: void ! 224: pinit() ! 225: { ! 226: int p[2]; ! 227: ! 228: (void) pipe(p); ! 229: ProcInput = fd_open("process-input", F_READ|F_LOCKED, p[0], ! 230: (char *) 0, 512); ! 231: ProcOutput = p[1]; ! 232: if ((kbd_pid = fork()) == -1) { ! 233: printf("Cannot fork kbd process!\n"); ! 234: finish(1); ! 235: } ! 236: if (kbd_pid == 0) { ! 237: signal(SIGINT, SIG_IGN); ! 238: signal(SIGALRM, SIG_IGN); ! 239: close(1); ! 240: dup(ProcOutput); ! 241: execl(Kbd_Proc, "kbd", 0); ! 242: write(2, "kdb exec failed\n", 16); ! 243: exit(-1); ! 244: } ! 245: } ! 246: ! 247: private int kbd_state = OFF; ! 248: ! 249: /* kbd_strt() and kbd_stop() return true if they changed the state ! 250: of the keyboard process. E.g., kbd_strt() returns TRUE if the ! 251: kbd process was previously stopped. This is so kbd starting and ! 252: stopping in pairs works - see finish() in jove.c. */ ! 253: ! 254: kbd_strt() ! 255: { ! 256: if (kbd_state == OFF) { ! 257: kbd_state = ON; ! 258: kill(kbd_pid, SIGQUIT); ! 259: return TRUE; ! 260: } ! 261: return FALSE; ! 262: } ! 263: ! 264: kbd_stop() ! 265: { ! 266: if (kbd_state == ON) { ! 267: kbd_state = OFF; ! 268: kill(kbd_pid, SIGQUIT); ! 269: return TRUE; ! 270: } ! 271: return FALSE; ! 272: } ! 273: ! 274: kbd_kill() ! 275: { ! 276: if (kbd_pid != 0) { ! 277: kill(kbd_pid, SIGKILL); ! 278: kbd_pid = 0; ! 279: } ! 280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.