Commit | Line | Data |
---|---|---|
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 | ||
14 | int proc_child(); | |
15 | ||
16 | #ifdef PIPEPROCS | |
17 | # include "iproc-pipes.c" | |
18 | #else | |
19 | # include "iproc-ptys.c" | |
20 | #endif | |
21 | ||
22 | KillProcs() | |
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 | ||
39 | static Process * | |
40 | proc_exists(name) | |
41 | char *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 | ||
58 | assign_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 | ||
69 | pbuftiedp(b) | |
70 | Buffer *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 | ||
82 | static | |
83 | proc_rec(p, buf) | |
84 | register Process *p; | |
85 | char *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 | ||
118 | proc_kill(p, sig) | |
119 | Process *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 | ||
131 | static | |
132 | DealWDeath() | |
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 | ||
156 | ProcList() | |
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 | ||
178 | ProcNewline() | |
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 | ||
197 | IShell() | |
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 | ||
210 | Iprocess() | |
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 | ||
221 | proc_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 | ||
238 | kill_off(pid, w) | |
239 | int pid; | |
240 | union 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 | ||
265 | struct 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 | ||
273 | struct proc_bind *PBinds = 0; | |
274 | ||
275 | PopPBs() | |
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 | ||
283 | PushPBs() | |
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 | ||
294 | ProcBind() | |
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 | ||
304 | ProcB2(map, lastkey, cmd) | |
305 | data_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 |