|
|
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: #ifdef BSD4_2
9: # include <sys/wait.h>
10: #else
11: # include <wait.h>
12: #endif
13: #include <signal.h>
14: #include <sgtty.h>
15: #include <errno.h>
16:
17: #define DEAD 1 /* dead but haven't informed user yet */
18: #define STOPPED 2 /* job stopped */
19: #define RUNNING 3 /* just running */
20: #define NEW 4 /* brand new, never been ... received no input */
21:
22: /* If process is dead, flags says how. */
23: #define EXITED 1
24: #define KILLED 2
25:
26: #define isdead(p) (p == 0 || proc_state(p) == DEAD || p->p_fd == -1)
27: #define makedead(p) (proc_state(p) = DEAD)
28:
29: #define proc_buf(p) (p->p_buffer->b_name)
30: #define proc_cmd(p) (p->p_name)
31: #define proc_state(p) (p->p_state)
32:
33: private Process *procs = 0;
34:
35: long global_fd = 1;
36: int NumProcs = 0;
37:
38: #ifdef BRLUNIX
39: extern struct sg_brl sg1;
40: #else
41: extern struct sgttyb sg1;
42: #endif
43:
44: extern struct tchars tc1;
45:
46: #ifdef TIOCSLTC
47: extern struct ltchars ls1;
48: #endif
49:
50: char *
51: pstate(p)
52: Process *p;
53: {
54: switch (proc_state(p)) {
55: case STOPPED:
56: return "Stopped";
57:
58: case RUNNING:
59: return "Running";
60:
61: case DEAD:
62: if (p->p_howdied == EXITED) {
63: if (p->p_reason == 0)
64: return "Done";
65: return sprint("Exit %d", p->p_reason);
66: }
67: return sprint("Killed %d", p->p_reason);
68:
69: case NEW:
70: return "New";
71:
72: default:
73: return "Unknown state";
74: }
75: }
76:
77: static Process *
78: proc_pid(pid)
79: {
80: register Process *p;
81:
82: for (p = procs; p != 0; p = p->p_next)
83: if (p->p_pid == pid)
84: break;
85:
86: return p;
87: }
88:
89: read_proc(fd)
90: register int fd;
91: {
92: register Process *p;
93: unsigned int n;
94: char ibuf[1024];
95:
96: for (p = procs; p != 0; p = p->p_next)
97: if (p->p_fd == fd)
98: break;
99:
100: if (p == 0) {
101: printf("\riproc: unknown fd %d", fd);
102: return;
103: }
104:
105: n = read(fd, ibuf, sizeof(ibuf) - 1);
106: if (n == -1 && errno == EIO) {
107: if (proc_state(p) == NEW)
108: return;
109: proc_close(p);
110: makedead(p);
111: return;
112: } else {
113: if (proc_state(p) != RUNNING) {
114: proc_state(p) = RUNNING;
115: UpdModLine = YES;
116: }
117: }
118: if (n <= 0) {
119: if (n == 0)
120: strcpy(ibuf, "[Process EOF]");
121: else
122: sprintf(ibuf, "\n[pty read error: %d]\n", errno);
123: } else
124: ibuf[n] = '\0';
125: proc_rec(p, ibuf);
126: }
127:
128: ProcKill()
129: {
130: register Buffer *b;
131: Process *buf_to_proc();
132: char *bname;
133:
134: bname = ask_buf(curbuf);
135:
136: if ((b = buf_exists(bname)) == 0)
137: complain("[No such buffer]");
138: if (b->b_process == 0)
139: complain("%s not tied to a process.", bname);
140: proc_kill(b->b_process, SIGKILL);
141: }
142:
143: ProcCont()
144: {
145: Process *p;
146:
147: if ((p = curbuf->b_process) == 0)
148: complain("[No process]");
149: if (p->p_state != DEAD) {
150: proc_kill(p, SIGCONT);
151: p->p_state = RUNNING;
152: }
153: }
154:
155: ProcEof()
156: {
157: send_p(tc1.t_eofc);
158: }
159:
160: ProcInt()
161: {
162: send_p(tc1.t_intrc);
163: }
164:
165: ProcQuit()
166: {
167: send_p(tc1.t_quitc);
168: }
169:
170: ProcStop()
171: {
172: send_p(ls1.t_suspc);
173: }
174:
175: ProcDStop()
176: {
177: send_p(ls1.t_dsuspc);
178: }
179:
180: send_p(c)
181: char c;
182: {
183: Process *p;
184: char buf[2];
185:
186: if ((p = curbuf->b_process) == 0)
187: complain("[No process]");
188: ToLast();
189: buf[0] = c;
190: buf[1] = '\0';
191: proc_rec(p, buf);
192: (void) write(p->p_fd, &c, 1);
193: }
194:
195: private
196: proc_close(p)
197: Process *p;
198: {
199: sighold(SIGCHLD); /* be mutually exclusive */
200:
201: if (p->p_fd >= 0) {
202: (void) close(p->p_fd);
203: global_fd &= ~(1L << p->p_fd);
204: NumProcs -= 1;
205: p->p_fd = -1;
206: }
207:
208: sigrelse(SIGCHLD);
209: }
210:
211: do_rtp(mp)
212: register Mark *mp;
213: {
214: register Process *p = curbuf->b_process;
215: Line *line1 = curline,
216: *line2 = mp->m_line;
217: int char1 = curchar,
218: char2 = mp->m_char;
219: char *gp;
220: int nbytes;
221:
222: if (isdead(p) || p->p_buffer != curbuf)
223: return;
224:
225: (void) fixorder(&line1, &char1, &line2, &char2);
226: while (line1 != line2->l_next) {
227: gp = ltobuf(line1, genbuf) + char1;
228: if (line1 == line2)
229: gp[char2] = '\0';
230: else
231: strcat(gp, "\n");
232: if (nbytes = strlen(gp))
233: (void) write(p->p_fd, gp, nbytes);
234: line1 = line1->l_next;
235: char1 = 0;
236: }
237: }
238:
239: /* VARARGS2 */
240:
241: private
242: proc_strt(bufname, clobber, va_alist)
243: char *bufname;
244: va_dcl
245: {
246: va_list ap;
247: char *argv[32],
248: *cp;
249: Window *owind = curwind;
250: int pid;
251: Process *newp;
252: Buffer *newbuf;
253: int i,
254: ptyfd,
255: ttyfd,
256: ldisc,
257: lmode;
258: register char *s,
259: *t;
260: extern int errno;
261: static char ttybuf[11],
262: ptybuf[11];
263: char cmdbuf[128];
264: #ifdef BRLUNIX
265: struct sg_brl sg;
266: #else
267: struct sgttyb sg;
268: #endif
269:
270: #ifdef TIOCGWINSZ
271: struct winsize win;
272: #else
273: # ifdef BTL_BLIT
274: # include <sys/jioctl.h>
275: struct jwinsize jwin;
276: # endif
277: #endif
278:
279: isprocbuf(bufname); /* make sure BUFNAME is either nonexistant
280: or is of type B_PROCESS */
281: for (s = "pqrs"; *s; s++) {
282: for (t = "0123456789abcdef"; *t; t++) {
283: sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
284: if ((ptyfd = open(ptybuf, 2)) >= 0) {
285: strcpy(ttybuf, ptybuf);
286: ttybuf[5] = 't';
287: /* make sure both ends are available */
288: if ((i = open(ttybuf, 2)) < 0)
289: continue;
290: (void) close(i);
291: goto out;
292: }
293: }
294: }
295:
296: out: if (s == 0 && t == 0)
297: complain("[Out of ptys!]");
298:
299: #ifdef TIOCGETD
300: (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
301: #endif
302: #ifdef TIOCLGET
303: (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
304: #endif
305: #ifdef TIOCGWINSZ
306: (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
307: #else
308: # ifdef BTL_BLIT
309: (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
310: # endif /* BTL_BLIT */
311: #endif
312:
313: sighold(SIGCHLD);
314: #ifdef SIGWINCH
315: sighold(SIGWINCH);
316: #endif
317: switch (pid = fork()) {
318: case -1:
319: (void) close(ptyfd);
320: message("[Fork failed!]");
321: goto fail;
322:
323: case 0:
324: sigrelse(SIGCHLD);
325: #ifdef SIGWINCH
326: sigrelse(SIGWINCH);
327: #endif
328: for (i = 0; i < 32; i++)
329: (void) close(i);
330:
331: #ifdef TIOCNOTTY
332: if ((i = open("/dev/tty", 2)) >= 0) {
333: (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
334: (void) close(i);
335: }
336: #endif
337: if ((ttyfd = open(ttybuf, 2)) < 0)
338: exit(-1);
339: (void) dup2(ttyfd, 1);
340: (void) dup2(ttyfd, 2);
341:
342: #ifdef TIOCSETD
343: (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
344: #endif
345: #ifdef TIOCLSET
346: (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
347: #endif
348: #ifdef TIOCSETC
349: (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
350: #endif
351: #ifdef TIOCSLTC
352: (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
353: #endif
354:
355: #ifdef TIOCGWINSZ
356: # ifdef SIGWINCH
357: (void) signal(SIGWINCH, SIG_IGN);
358: # endif
359: win.ws_row = curwind->w_height;
360: (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
361: #else
362: # ifdef BTL_BLIT
363: jwin.bytesy = curwind->w_height;
364: (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
365: # endif
366: #endif
367:
368: sg = sg1;
369: sg.sg_flags &= ~(ECHO | CRMOD);
370: (void) stty(0, &sg);
371:
372: i = getpid();
373: (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
374: (void) setpgrp(0, i);
375: va_start(ap);
376: make_argv(argv, ap);
377: va_end(ap);
378: execv(argv[0], &argv[1]);
379: (void) write(1, "execve failed!\n", 15);
380: _exit(errno + 1);
381: }
382:
383: newp = (Process *) emalloc(sizeof *newp);
384:
385: newp->p_fd = ptyfd;
386: newp->p_pid = pid;
387:
388: newbuf = do_select((Window *) 0, bufname);
389: newbuf->b_type = B_PROCESS;
390: newp->p_buffer = newbuf;
391: newbuf->b_process = newp; /* sorta circular, eh? */
392: pop_wind(bufname, clobber, B_PROCESS);
393: /* Pop_wind() after everything is set up; important!
394: Bindings won't work right unless newbuf->b_process is already
395: set up BEFORE NEWBUF is first SetBuf()'d. */
396: ToLast();
397: if (!bolp())
398: LineInsert(1);
399:
400: cmdbuf[0] = '\0';
401: va_start(ap);
402: while (cp = va_arg(ap, char *))
403: sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++);
404: va_end(ap);
405:
406: newp->p_name = copystr(cmdbuf);
407: newp->p_state = NEW;
408: newp->p_reason = 0;
409: newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
410:
411: newp->p_next = procs;
412: procs = newp;
413: NumProcs += 1;
414: global_fd |= 1L << newp->p_fd;
415: SetWind(owind);
416:
417: fail: sigrelse(SIGCHLD);
418: #ifdef SIGWINCH
419: sigrelse(SIGWINCH);
420: #endif
421: }
422:
423: pinit()
424: {
425: (void) signal(SIGCHLD, proc_child);
426: }
427:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.