|
|
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: #include "jove.h"
9: #include "re.h"
10: #include <varargs.h>
11:
12: #ifdef IPROCS
13:
14: int proc_child();
15:
16: #ifdef PIPEPROCS
17: # include "iproc-pipes.c"
18: #else
19: # include "iproc-ptys.c"
20: #endif
21:
22: char proc_prompt[128] = "% ";
23:
24: KillProcs()
25: {
26: register Process *p;
27: register int killem = -1; /* -1 means undetermined */
28: register char *yorn;
29:
30: for (p = procs; p != 0; p = p->p_next)
31: if (!isdead(p)) {
32: if (killem == -1) {
33: yorn = ask("y", "Should I kill your i-processes? ");
34: killem = (CharUpcase(*yorn) == 'Y');
35: }
36: if (killem)
37: proc_kill(p, SIGKILL);
38: }
39: }
40:
41: pbuftiedp(b)
42: register Buffer *b;
43: {
44: register Process *p = b->b_process;
45:
46: if (!isdead(p))
47: complain("Process %s, attached to %b, is %s.",
48: proc_cmd(p), b, pstate(p));
49: }
50:
51: /* Process receive: receives the characters in buf, and appends them to
52: the buffer associated with p. */
53:
54: private
55: proc_rec(p, buf)
56: register Process *p;
57: char *buf;
58: {
59: Buffer *saveb = curbuf;
60: register Window *w;
61: register Mark *savepoint;
62: int sameplace = NO,
63: do_disp = NO;
64:
65: if (curwind->w_bufp == p->p_buffer)
66: w = curwind;
67: else
68: w = windbp(p->p_buffer); /* Is this window visible? */
69: if (w != 0)
70: do_disp = (in_window(w, p->p_mark->m_line) != -1);
71: SetBuf(p->p_buffer);
72: savepoint = MakeMark(curline, curchar, M_FLOATER);
73: ToMark(p->p_mark); /* where output last stopped */
74: if (savepoint->m_line == curline && savepoint->m_char == curchar)
75: sameplace = YES;
76:
77: ins_str(buf, YES);
78: MarkSet(p->p_mark, curline, curchar);
79: if (!sameplace)
80: ToMark(savepoint); /* back to where we were */
81: DelMark(savepoint);
82: /* redisplay now, instead of right after the ins_str, so that
83: we don't get a bouncing effect if point is not the same as
84: the process output position */
85: if (do_disp) {
86: w->w_line = curline;
87: w->w_char = curchar;
88: redisplay();
89: }
90: SetBuf(saveb);
91: }
92:
93: proc_kill(p, sig)
94: register Process *p;
95: {
96: if (isdead(p))
97: return;
98: if (killpg(p->p_pid, sig) == -1)
99: s_mess("Cannot kill %s!", proc_buf(p));
100: }
101:
102: /* Free process CHILD. Do all the necessary cleaning up (closing fd's,
103: etc.). */
104:
105: free_proc(child)
106: Process *child;
107: {
108: register Process *p,
109: *prev = 0;
110:
111: if (!isdead(child))
112: return;
113: for (p = procs; p != child; prev = p, p = p->p_next)
114: ;
115: if (prev == 0)
116: procs = child->p_next;
117: else
118: prev->p_next = child->p_next;
119: proc_close(child); /* if not already closed */
120:
121: /* It's possible that the buffer has been given another process
122: between the time CHILD dies and CHILD's death is noticed (via
123: list-processes). So we only set it the buffer's process to
124: 0 if CHILD is still the controlling process. */
125: if (child->p_buffer->b_process == child) {
126: child->p_buffer->b_process = 0;
127: if (curbuf == child->p_buffer)
128: PopPBs();
129: }
130: {
131: Buffer *old = curbuf;
132:
133: SetBuf(child->p_buffer);
134: DelMark(child->p_mark);
135: SetBuf(old);
136: }
137: free((char *) child->p_name);
138: free((char *) child);
139: }
140:
141: ProcList()
142: {
143: register Process *p,
144: *next;
145: char *fmt = "%-15s %-15s %-8s %s",
146: pidstr[16];
147:
148: if (procs == 0) {
149: message("[No subprocesses]");
150: return;
151: }
152: TOstart("Process list", TRUE);
153:
154: Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
155: Typeout(fmt, "------", "------", "--- ", "-------");
156: for (p = procs; p != 0; p = next) {
157: next = p->p_next;
158: sprintf(pidstr, "%d", p->p_pid);
159: Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
160: if (isdead(p)) {
161: free_proc(p);
162: UpdModLine = YES;
163: }
164: }
165: TOstop();
166: }
167:
168: ProcNewline()
169: {
170: #ifdef ABBREV
171: MaybeAbbrevExpand();
172: #endif
173: SendData(YES);
174: }
175:
176: ProcSendData()
177: {
178: #ifdef ABBREV
179: MaybeAbbrevExpand();
180: #endif
181: SendData(NO);
182: }
183:
184: private
185: SendData(newlinep)
186: {
187: register Process *p = curbuf->b_process;
188: register char *lp,
189: *gp; /* JF fix for better prompt handling */
190:
191: if (isdead(p))
192: return;
193: /* If the process mark was involved in a big deletion, because
194: the user hit ^W or something, then let's do some magic with
195: the process mark. Problem is that if the user yanks back the
196: text he deleted, the mark stays at the beginning of the region,
197: and so the next time SendData() is called the entire region
198: will be sent. That's not good. So, to deal with that we reset
199: the mark to the last line, after skipping over the prompt, etc. */
200: if (p->p_mark->m_flags & M_BIG_DELETE) {
201: Bufpos bp;
202:
203: p->p_mark->m_flags &= ~M_BIG_DELETE;
204:
205: DOTsave(&bp);
206: ToLast();
207: Bol();
208: /* While we're looking at a prompt, and while we're
209: moving forward. This is for people who accidently
210: set their process-prompt to ">*" which will always
211: match! */
212: while ((LookingAt(proc_prompt, linebuf, curchar)) &&
213: (REeom > curchar))
214: curchar = REeom;
215: MarkSet(p->p_mark, curline, curchar);
216: SetDot(&bp);
217: }
218:
219: if (lastp(curline)) {
220: Eol();
221: if (newlinep)
222: LineInsert(1);
223: do_rtp(p->p_mark);
224: MarkSet(p->p_mark, curline, curchar);
225: } else {
226: /* Either we're looking at a prompt, or we're not, in
227: which case we want to strip off the beginning of the
228: line anything that looks like what the prompt at the
229: end of the file is. In other words, if "(dbx) stop in
230: ProcessNewline" is the line we're on, and the last
231: line in the buffer is "(dbx) ", then we strip off the
232: leading "(dbx) " from this line, because we know it's
233: part of the prompt. But this only happens if "(dbx) "
234: isn't one of the process prompts ... follow what I'm
235: saying? */
236: Bol();
237: if (LookingAt(proc_prompt, linebuf, curchar)) {
238: do
239: curchar = REeom;
240: while ((LookingAt(proc_prompt, linebuf, curchar)) &&
241: (REeom > curchar));
242: strcpy(genbuf, linebuf + curchar);
243: Eof();
244: ins_str(genbuf, NO);
245: } else {
246: strcpy(genbuf, linebuf + curchar);
247: Eof();
248: gp = genbuf;
249: lp = linebuf;
250: while (*lp == *gp && *lp != '\0') {
251: lp += 1;
252: gp += 1;
253: }
254: ins_str(gp, NO);
255: }
256: }
257: }
258:
259: ShellProc()
260: {
261: char *shbuf = "*shell*";
262: register Buffer *b;
263:
264: b = buf_exists(shbuf);
265: if (b == 0 || isdead(b->b_process))
266: proc_strt(shbuf, NO, Shell, "-i", (char *) 0);
267: pop_wind(shbuf, NO, -1);
268: }
269:
270: Iprocess()
271: {
272: extern char ShcomBuf[100],
273: *MakeName();
274: register char *command;
275: char scratch[64],
276: *bufname;
277: int cnt = 1;
278: Buffer *bp;
279:
280: command = ask(ShcomBuf, ProcFmt);
281: null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1);
282: bufname = MakeName(command);
283: strcpy(scratch, bufname);
284: while ((bp = buf_exists(scratch)) && !isdead(bp->b_process))
285: sprintf(scratch, "%s.%d", bufname, cnt++);
286: proc_strt(scratch, YES, Shell, ShFlags, command, (char *) 0);
287: }
288:
289: proc_child()
290: {
291: union wait w;
292: register int pid;
293:
294: for (;;) {
295: #ifndef BSD4_2
296: pid = wait2(&w.w_status, (WNOHANG | WUNTRACED));
297: #else
298: pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0);
299: #endif
300: if (pid <= 0)
301: break;
302: kill_off(pid, w);
303: }
304: }
305:
306: kill_off(pid, w)
307: register int pid;
308: union wait w;
309: {
310: register Process *child;
311:
312: if ((child = proc_pid(pid)) == 0)
313: return;
314:
315: UpdModLine = YES; /* we're changing state ... */
316: if (WIFSTOPPED(w))
317: child->p_state = STOPPED;
318: else {
319: child->p_state = DEAD;
320: if (WIFEXITED(w))
321: child->p_howdied = EXITED;
322: else if (WIFSIGNALED(w)) {
323: child->p_reason = w.w_termsig;
324: child->p_howdied = KILLED;
325: }
326: {
327: Buffer *save = curbuf;
328: char mesg[128];
329:
330: /* insert status message now */
331: sprintf(mesg, "[Process %s: %s]\n",
332: proc_cmd(child),
333: pstate(child));
334: SetBuf(child->p_buffer);
335: ins_str(mesg, NO);
336: SetBuf(save);
337: redisplay();
338: }
339: }
340: }
341:
342: /* Push/pod process bindings. I openly acknowledge that this is a
343: kludge, but I can't be bothered making it right. */
344:
345: struct proc_bind {
346: int pb_key;
347: data_obj **pb_map;
348: data_obj *pb_push;
349: data_obj *pb_cmd;
350: struct proc_bind *pb_next;
351: };
352:
353: struct proc_bind *PBinds = 0;
354:
355: PopPBs()
356: {
357: register struct proc_bind *p;
358:
359: for (p = PBinds; p != 0; p = p->pb_next)
360: p->pb_map[p->pb_key] = p->pb_push;
361: }
362:
363: PushPBs()
364: {
365: register struct proc_bind *p;
366:
367: for (p = PBinds; p != 0; p = p->pb_next) {
368: p->pb_push = p->pb_map[p->pb_key];
369: p->pb_map[p->pb_key] = p->pb_cmd;
370: }
371: }
372: /* VARARGS0 */
373:
374: ProcBind()
375: {
376: register data_obj *d;
377:
378: if ((d = findcom(ProcFmt)) == 0)
379: return;
380: s_mess(": %f %s ", d->Name);
381: ProcB2(mainmap, EOF, d);
382: }
383:
384: ProcB2(map, lastkey, cmd)
385: data_obj **map,
386: *cmd;
387: {
388: register struct proc_bind *p;
389: register data_obj **nextmap;
390: int c;
391:
392: c = addgetc();
393: if (c == EOF) {
394: if (lastkey == EOF)
395: complain("[Empty key sequence]");
396: complain("[Unexpected end-of-line]");
397: } else {
398: if (nextmap = IsPrefix(map[c]))
399: ProcB2(nextmap, c, cmd);
400: else {
401: if (curbuf->b_process)
402: PopPBs();
403:
404: for (p = PBinds; p != 0; p = p->pb_next)
405: if (p->pb_key == c && p->pb_map == map)
406: break;
407: if (p == 0) {
408: p = (struct proc_bind *) emalloc(sizeof *p);
409: p->pb_next = PBinds;
410: PBinds = p;
411: }
412: p->pb_map = map;
413: p->pb_key = c;
414: p->pb_cmd = cmd;
415:
416: if (curbuf->b_process)
417: PushPBs();
418: }
419: }
420: }
421:
422: #endif /* IPROCS */
423:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.