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