BSD 4_3 development
[unix-history] / usr / contrib / jove / iproc.c
CommitLineData
394a1d25
C
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#include "jove.h"
11
12#ifdef IPROCS
13
14int proc_child();
15
16#ifdef PIPEPROCS
17# include "iproc-pipes.c"
18#else
19# include "iproc-ptys.c"
20#endif
21
22KillProcs()
23{
24 register Process *p;
25 int killem = -1; /* -1 means undetermined */
26 char *yorn;
27
28 for (p = procs; p != 0; p = p->p_next)
29 if (!isdead(p)) {
30 if (killem == -1) {
31 yorn = ask("y", "Should I kill your i-processes? ");
32 killem = (Upper(*yorn) == 'Y');
33 }
34 if (killem)
35 proc_kill(p, SIGKILL);
36 }
37}
38
39static Process *
40proc_exists(name)
41char *name;
42{
43 register Process *p;
44
45 for (p = procs; p != 0; p = p->p_next)
46 if (strcmp(proc_buf(p), name) == 0) {
47 (void) pstate(p);
48 if (p->p_eof) {
49 DealWDeath();
50 return 0;
51 }
52 break;
53 }
54
55 return p;
56}
57
58assign_p()
59{
60 register Process *p;
61
62 for (p = procs; p != 0; p = p->p_next)
63 if (p->p_buffer == curbuf) {
64 cur_proc = p;
65 break;
66 }
67}
68
69pbuftiedp(b)
70Buffer *b;
71{
72 register Process *p;
73
74 for (p = procs; p != 0; p = p->p_next)
75 if (p->p_buffer == b && !p->p_eof)
76 complain("[There is a process tied to %s]", proc_buf(p));
77}
78
79/* Process receive: receives the characters in buf, and appends them to
80 the buffer associated with p. */
81
82static
83proc_rec(p, buf)
84register Process *p;
85char *buf;
86{
87 Buffer *saveb = curbuf;
88 Window *w;
89 Mark *savepoint;
90 int sameplace = 0,
91 do_disp = 0;
92
93 if (curwind->w_bufp == p->p_buffer)
94 w = curwind;
95 else
96 w = windbp(p->p_buffer); /* Is this window visible? */
97 if (w != 0)
98 do_disp = (in_window(w, p->p_mark->m_line) != -1);
99 SetBuf(p->p_buffer);
100 savepoint = MakeMark(curline, curchar, FLOATER);
101 ToMark(p->p_mark); /* Where output last stopped. */
102 if (savepoint->m_line == curline && savepoint->m_char == curchar)
103 sameplace++;
104
105 ins_str(buf, YES);
106 if (do_disp) {
107 w->w_line = curline;
108 w->w_char = curchar;
109 redisplay();
110 }
111 MarkSet(p->p_mark, curline, curchar);
112 if (!sameplace)
113 ToMark(savepoint); /* Back to where we were. */
114 DelMark(savepoint);
115 SetBuf(saveb);
116}
117
118proc_kill(p, sig)
119Process *p;
120{
121 if (p == 0 || p->p_state == DEAD)
122 return;
123 if (killpg(p->p_pid, sig) == -1)
124 s_mess("Cannot kill %s!", proc_buf(p));
125}
126
127/* Deal with a process' death. proc_rec turns on the FREEUP bit when it
128 it gets the "EOF" from portsrv. FREEUP'd processes get unlinked from
129 the list, and the proc stucture and proc_buf(p) get free'd up, here. */
130
131static
132DealWDeath()
133{
134 register Process *p,
135 *next,
136 *prev = 0;
137
138 for (p = procs; p != 0; p = next) {
139 next = p->p_next;
140 if (!p->p_eof) {
141 prev = p;
142 continue;
143 }
144 if (cur_proc == p)
145 cur_proc = next ? next : prev;
146 proc_close(p);
147 free((char *) p->p_name);
148 free((char *) p);
149 if (prev)
150 prev->p_next = next;
151 else
152 procs = next;
153 }
154}
155
156ProcList()
157{
158 register Process *p;
159 char *fmt = "%-15s %-15s %-8s %s",
160 pidstr[10];
161
162 if (procs == 0) {
163 message("[No subprocesses]");
164 return;
165 }
166 TOstart("Process list", TRUE);
167
168 Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
169 Typeout(fmt, "------", "------", "--- ", "-------");
170 for (p = procs; p != 0; p = p->p_next) {
171 sprintf(pidstr, "%d", p->p_pid);
172 Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
173 }
174 DealWDeath();
175 TOstop();
176}
177
178ProcNewline()
179{
180 if (isdead(cur_proc))
181 return;
182 if (lastp(curline)) {
183 Eol();
184 LineInsert();
185 do_rtp(cur_proc->p_mark);
186 MarkSet(cur_proc->p_mark, curline, curchar);
187 } else {
188 Bol();
189 while (LookingAt(proc_prompt, linebuf, curchar))
190 SetDot(dosearch(proc_prompt, 1, 1));
191 strcpy(genbuf, linebuf + curchar);
192 ToLast();
193 ins_str(genbuf, NO);
194 }
195}
196
197IShell()
198{
199 char shell[30];
200 int number = 1;
201
202 do
203 sprintf(shell, "shell-%d", number++);
204 while (proc_exists(shell));
205
206 proc_strt(shell, "i-shell", Shell, basename(Shell), "-i", 0);
207 SetWind(windlook(shell));
208}
209
210Iprocess()
211{
212 extern char ShcomBuf[100],
213 *MakeName();
214 char *command;
215
216 command = ask(ShcomBuf, ProcFmt);
217 null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1);
218 proc_strt(MakeName(command), command, Shell, basename(Shell), ShFlags, command, 0);
219}
220
221proc_child()
222{
223 union wait w;
224 int pid;
225
226 for (;;) {
227#ifndef VMUNIX
228 pid = wait2(&w.w_status, (WNOHANG | WUNTRACED));
229#else
230 pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0);
231#endif
232 if (pid <= 0)
233 break;
234 kill_off(pid, w);
235 }
236}
237
238kill_off(pid, w)
239int pid;
240union wait w;
241{
242 Process *child;
243
244 if ((child = proc_pid(pid)) == 0)
245 return;
246
247 if (WIFSTOPPED(w))
248 child->p_state = STOPPED;
249 else {
250 child->p_state = DEAD;
251 if (WIFEXITED(w))
252 child->p_howdied = EXITED;
253 else if (WIFSIGNALED(w)) {
254 child->p_reason = w.w_termsig;
255 child->p_howdied = KILLED;
256 }
257 proc_close(child);
258 }
259 s_mess("%s [%s] %s", pstate(child), proc_buf(child), proc_cmd(child));
260}
261
262/* Push/pod process bindings. I openly acknowledge that this is a
263 kludge, but I can't be bothered making it right. */
264
265struct proc_bind {
266 int pb_key;
267 data_obj **pb_map;
268 data_obj *pb_push;
269 data_obj *pb_cmd;
270 struct proc_bind *pb_next;
271};
272
273struct proc_bind *PBinds = 0;
274
275PopPBs()
276{
277 register struct proc_bind *p;
278
279 for (p = PBinds; p != 0; p = p->pb_next)
280 p->pb_map[p->pb_key] = p->pb_push;
281}
282
283PushPBs()
284{
285 register struct proc_bind *p;
286
287 for (p = PBinds; p != 0; p = p->pb_next) {
288 p->pb_push = p->pb_map[p->pb_key];
289 p->pb_map[p->pb_key] = p->pb_cmd;
290 }
291}
292/* VARARGS0 */
293
294ProcBind()
295{
296 data_obj *d;
297
298 if ((d = findcom(ProcFmt, NOTHING)) == 0)
299 return;
300 s_mess(": %f %s ", d->Name);
301 ProcB2(mainmap, EOF, d);
302}
303
304ProcB2(map, lastkey, cmd)
305data_obj **map,
306 *cmd;
307{
308 register struct proc_bind *p;
309 data_obj **nextmap;
310 int c;
311
312 c = addgetc();
313 if (c == EOF) {
314 if (lastkey == EOF)
315 complain("[Empty key sequence]");
316 complain("[Unexpected end-of-line]");
317 } else {
318 if (nextmap = IsPrefix(map[c]))
319 ProcB2(nextmap, c, cmd);
320 else {
321 if (curbuf->b_type == B_IPROCESS)
322 PopPBs();
323
324 for (p = PBinds; p != 0; p = p->pb_next)
325 if (p->pb_key == c && p->pb_map == map)
326 break;
327 if (p == 0) {
328 p = (struct proc_bind *) emalloc(sizeof *p);
329 p->pb_next = PBinds;
330 PBinds = p;
331 }
332 p->pb_map = map;
333 p->pb_key = c;
334 p->pb_cmd = cmd;
335
336 if (curbuf->b_type == B_IPROCESS)
337 PushPBs();
338 }
339 }
340}
341
342#endif IPROCS