|
|
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.