1 /************************************************************************
2  * This program is Copyright (C) 1986-1996 by Jonathan Payne.  JOVE is  *
3  * 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 
10 #ifdef IPROCS	/* the body is the rest of this file */
11 
12 #include <signal.h>
13 
14 #include "re.h"
15 #include "jctype.h"
16 #include "disp.h"
17 #include "fp.h"
18 #include "sysprocs.h"
19 #include "iproc.h"
20 #include "ask.h"
21 #include "extend.h"
22 #include "fmt.h"
23 #include "insert.h"
24 #include "marks.h"
25 #include "move.h"
26 #include "proc.h"
27 #include "wind.h"
28 
29 #ifdef USE_KILLPG
30 # ifndef FULL_UNISTD
31 extern int	UNMACRO(killpg) proto((int /*pgrp*/, int /*sig*/));
32 # endif
33 #else /* !USE_KILLPG */
34 #define killpg(pid, sig)	kill(-(pid), (sig))
35 #endif /* USE_KILLPG */
36 
37 #include <errno.h>
38 
39 struct process {
40 	Process	p_next;
41 #ifdef PIPEPROCS
42 	int	p_toproc;	/* write end of pipe to process */
43 	pid_t	p_portpid,	/* pid of direct child (the portsrv) */
44 		p_pid;		/* pid of real child i.e. not portsrv */
45 	bool	p_portlive;	/* is portsrv still live? */
46 #else
47 	int	p_fd;		/* file descriptor of pty? opened r/w */
48 # define	p_portpid	p_pid	/* pid of direct child (the shell) */
49 	pid_t	p_pid;		/* pid of child (the shell) */
50 #endif
51 	Buffer	*p_buffer;	/* add output to end of this buffer */
52 	char	*p_name;	/* ... */
53 	int	p_io_state;	/* state of communication with child and descendents */
54 #		define IO_NEW	0	/* brand new, process has not yet sent output */
55 #		define IO_RUNNING	1	/* just running */
56 #		define IO_EOFED	2	/* we have sent EOF, or have received it */
57 	int	p_child_state;	/* state of child process, as disclosed by SIGCHLD/wait */
58 #		define C_LIVE	0	/* no news is good news */
59 #		define C_STOPPED	1
60 #		define C_EXITED	2
61 #		define C_KILLED	3
62 	int	p_reason;	/* If killed, p_reason is the signal;
63 				   if exited, it is the the exit code */
64 	Mark	*p_mark;	/* where output left us */
65 	bool	p_dbx_mode;	/* whether to parse output for file/lineno
66 				   pairs */
67 };
68 
69 private void
70 	jputenv proto((char *)),
71 	proc_rec proto((Process, char *, size_t)),
72 	proc_close proto ((Process)),
73 	SendData proto((bool)),
74 	obituary proto((register Process child, wait_status_t w));
75 
76 private bool
77 	proc_kill proto((Process, int));
78 
79 #define child_dead(p)	((p)->p_child_state >= C_EXITED)
80 #define io_eofed(p)	((p)->p_io_state == IO_EOFED)
81 
82 private bool
dead(p)83 dead(p)
84 Process	p;
85 {
86 	return p == NULL || (io_eofed(p) && child_dead(p));
87 }
88 
89 
90 #define proc_cmd(p)	((p)->p_name)
91 
92 private Process	procs = NULL;
93 
94 private Process
proc_pid(pid)95 proc_pid(pid)
96 pid_t	pid;
97 {
98 	register Process	p;
99 
100 	for (p = procs; ; p = p->p_next)
101 		if (p == NULL || p->p_portpid == pid)
102 			return p;
103 }
104 
105 private char *
proc_bufname(p)106 proc_bufname(p)
107 Process	p;
108 {
109 	Buffer	*b = p->p_buffer;
110 
111 	return (b != NULL) ? b->b_name : "<Deleted>";
112 }
113 
114 void
ProcKill()115 ProcKill()
116 {
117 	(void) proc_kill(
118 		buf_exists(ask_buf(curbuf, ALLOW_OLD | ALLOW_INDEX))->b_process,
119 		SIGKILL);
120 }
121 
122 private void
make_argv(argv,ap)123 make_argv(argv, ap)
124 register char	*argv[];
125 va_list	ap;
126 {
127 	register int	i = 0;
128 
129 	argv[i++] = va_arg(ap, char *);
130 	argv[i++] = basename(argv[0]);
131 	do ; while ((argv[i++] = va_arg(ap, char *)) != NULL);
132 }
133 
134 /* There are two very different implementation techniques: pipes and ptys.
135  * The following two chunks of code implement the same operations using
136  * the two techniques: the first uses pipes and the second uses ptys.
137  */
138 
139 #ifdef PIPEPROCS
140 
141 #include <sgtty.h>
142 
143 char	Portsrv[FILESIZE];	/* path to portsrv program (in LibDir) */
144 
145 int	NumProcs = 0;
146 
147 File	*ProcInput;
148 private int	ProcOutput = -1;
149 
150 pid_t	kbd_pid = -1;
151 
152 void
read_pipe_proc(pid,nbytes)153 read_pipe_proc(pid, nbytes)
154 pid_t	pid;
155 register int	nbytes;
156 {
157 	register Process	p = proc_pid(pid);
158 
159 	if (p == NULL) {
160 		writef("\riproc: unknown pid (%d)", (int)pid);
161 	} else if (p->p_io_state == IO_NEW) {
162 		/* first message: pid of real child, not of portsrv */
163 		pid_t	rpid;
164 
165 		(void) f_readn(ProcInput, (char *) &rpid, sizeof(pid_t));
166 		p->p_pid = rpid;
167 		p->p_io_state = IO_RUNNING;
168 		UpdModLine = YES;
169 	} else if (nbytes == -1) {
170 		/* okay to clean up this process */
171 		wait_status_t	status;
172 
173 		(void) f_readn(ProcInput, (char *) &status, sizeof(status));
174 		/* Reap portsrv process, if it still remains.
175 		 * Note that any status for this process is uninteresting:
176 		 * the interesting status came (just now) by pipe.
177 		 */
178 		while (p->p_portlive) {
179 			wait_status_t	w;
180 			pid_t	rpid = wait(&w);
181 
182 			if (rpid == -1) {
183 				if (errno == ECHILD) {
184 					/* oops: no children, not even portsrv */
185 					p->p_portlive = NO;
186 				}
187 			} else {
188 				kill_off(rpid, w);
189 			}
190 		}
191 		proc_close(p);
192 		obituary(p, status);
193 	} else {
194 		/* regular data */
195 		while (nbytes > 0) {
196 			char	ibuf[512+1];	/* NOTE: room for added NUL */
197 			size_t n = f_readn(ProcInput, ibuf,
198 				(size_t)min((int)(sizeof ibuf) - 1, nbytes));
199 
200 			nbytes -= n;
201 			proc_rec(p, ibuf, n);
202 		}
203 	}
204 }
205 
206 void
ProcInt()207 ProcInt()
208 {
209 	(void) proc_kill(curbuf->b_process, SIGINT);
210 }
211 
212 void
ProcQuit()213 ProcQuit()
214 {
215 	(void) proc_kill(curbuf->b_process, SIGQUIT);
216 }
217 
218 private void
proc_close(p)219 proc_close(p)
220 Process	p;
221 {
222 	if (p->p_toproc >= 0) {
223 		(void) close(p->p_toproc);
224 		p->p_toproc = -1;	/* writes will fail */
225 		NumProcs -= 1;
226 		p->p_io_state = IO_EOFED;	/* process output EOF is tied to reaping */
227 		UpdModLine = YES;
228 	}
229 }
230 
231 private void
proc_write(p,buf,nbytes)232 proc_write(p, buf, nbytes)
233 Process	p;
234 char	*buf;
235 size_t	nbytes;
236 {
237 	if (p->p_toproc >= 0) {
238 		while (nbytes != 0) {
239 			SSIZE_T	wr = write(p->p_toproc, (UnivConstPtr)buf, nbytes);
240 
241 			if (wr >= 0) {
242 				nbytes -= wr;
243 				buf += wr;
244 			} else if (errno != EINTR) {
245 				complain("[error writing to iproc: %d %s]", errno, strerror(errno));
246 			}
247 		}
248 	}
249 }
250 
251 
252 # ifdef STDARGS
253 private void
proc_strt(char * bufname,bool clobber,char * procname,...)254 proc_strt(char *bufname, bool clobber, char *procname, ...)
255 # else
256 private /*VARARGS3*/ void
257 proc_strt(bufname, clobber, procname, va_alist)
258 	char	*bufname;
259 	bool	clobber;
260 	char	*procname;
261 	va_dcl
262 # endif
263 {
264 	Window	*owind = curwind;
265 	int	toproc[2];
266 	pid_t	pid;
267 	Process	newp;
268 	Buffer	*newbuf;
269 	char	*argv[32];
270 	va_list	ap;
271 
272 	untieDeadProcess(buf_exists(bufname));
273 	isprocbuf(bufname);	/* make sure BUFNAME is either nonexistant
274 				   or is of type B_PROCESS */
275 	if (access(Portsrv, X_OK) < 0) {
276 		complain("[Couldn't access %s: %s]", Portsrv, strerror(errno));
277 		/* NOTREACHED */
278 	}
279 
280 	dopipe(toproc);
281 
282 	if (NumProcs++ == 0)
283 		kbd_strt();	/* may create kbd process: must be done before fork */
284 	switch (pid = fork()) {
285 	case -1:
286 		pipeclose(toproc);
287 		if (--NumProcs == 0)
288 			kbd_stop();
289 		complain("[Fork failed: %s]", strerror(errno));
290 		/* NOTREACHED */
291 
292 	case 0:
293 		argv[0] = "portsrv";
294 		va_init(ap, procname);
295 		make_argv(&argv[1], ap);
296 		va_end(ap);
297 		(void) dup2(toproc[0], 0);
298 		(void) dup2(ProcOutput, 1);
299 		(void) dup2(ProcOutput, 2);
300 		pipeclose(toproc);
301 		jcloseall();
302 		jputenv("EMACS=t");
303 		jputenv("TERM=emacs");
304 		/* ??? the following line is not useful for terminfo systems */
305 		jputenv(sprint("TERMCAP=emacs:co#%d:tc=unknown:", CO-1));
306 		execv(Portsrv, argv);
307 		raw_complain("execl failed: %s", strerror(errno));
308 		_exit(1);
309 	}
310 
311 	newp = (Process) emalloc(sizeof *newp);
312 	newp->p_next = procs;
313 	newp->p_io_state = IO_NEW;
314 	newp->p_child_state = C_LIVE;
315 	newp->p_name = copystr(procname);
316 	procs = newp;
317 	newp->p_portpid = pid;
318 	newp->p_pid = -1;
319 	newp->p_portlive = YES;
320 
321 	newbuf = do_select((Window *)NULL, bufname);
322 	newbuf->b_type = B_PROCESS;
323 	newp->p_buffer = newbuf;
324 	newbuf->b_process = newp;	/* sorta circular, eh? */
325 	pop_wind(bufname, clobber, B_PROCESS);
326 	ToLast();
327 	if (!bolp())
328 		LineInsert(1);
329 	/* Pop_wind() after everything is set up; important!
330 	   Bindings won't work right unless newbuf->b_process is already
331 	   set up BEFORE NEWBUF is first SetBuf()'d. */
332 	newp->p_mark = MakeMark(curline, curchar);
333 	newp->p_dbx_mode = NO;
334 
335 	newp->p_toproc = toproc[1];
336 	(void) close(toproc[0]);
337 	SetWind(owind);
338 }
339 
340 void
closeiprocs()341 closeiprocs()
342 {
343 	Process	p;
344 
345 	if (ProcOutput != -1)
346 		close(ProcOutput);
347 	for (p=procs; p!=NULL; p=p->p_next)
348 		if (p->p_toproc >= 0)
349 			close(p->p_toproc);
350 }
351 
352 private void
kbd_init()353 kbd_init()
354 {
355 	/* Initiate the keyboard process.
356 	 * We only get here after a portsrv process has been started
357 	 * so we know that the portsrv program must exist -- no need to test.
358 	 */
359 	int	p[2];
360 
361 	(void) pipe(p);
362 	ProcInput = fd_open("process-input", F_READ|F_LOCKED, p[0],
363 			    (char *)NULL, 512);
364 	ProcOutput = p[1];
365 	switch (kbd_pid = fork()) {
366 	case -1:
367 		complain("Cannot fork kbd process! %s\n", strerror(errno));
368 		/* NOTREACHED */
369 
370 	case 0:
371 		(void) setsighandler(SIGINT, SIG_IGN);
372 		(void) setsighandler(SIGALRM, SIG_IGN);
373 		close(1);
374 		dup(ProcOutput);
375 		jcloseall();
376 		execl(Portsrv, "kbd", (char *)NULL);
377 		raw_complain("kbd exec failed: %s", strerror(errno));
378 		exit(-1);
379 	}
380 }
381 
382 /* kbd_stop() returns true if it changes the state of (i.e. stops)
383    the keyboard process.  This is so kbd stopping and starting in
384    pairs works - see finish() in jove.c. */
385 
386 private bool	kbd_state = NO;
387 
388 void
kbd_strt()389 kbd_strt()
390 {
391 	if (!kbd_state) {
392 		if (kbd_pid == -1)
393 			kbd_init();
394 		else
395 			kill(kbd_pid, KBDSIG);
396 		kbd_state = YES;
397 	}
398 }
399 
400 bool
kbd_stop()401 kbd_stop()
402 {
403 	if (kbd_state) {
404 		kbd_state = NO;
405 		kill(kbd_pid, KBDSIG);
406 		return YES;
407 	}
408 	return NO;
409 }
410 
411 void
kbd_kill()412 kbd_kill()
413 {
414 	if (kbd_pid != -1) {
415 		kill(kbd_pid, SIGKILL);
416 		kbd_pid = -1;
417 	}
418 }
419 
420 #else /* !PIPEPROCS */
421 
422 #include <sys/time.h>
423 #include <fcntl.h>
424 #include "select.h"
425 
426 #include "ttystate.h"
427 
428 # ifdef SVR4_PTYS
429 #  include <stdlib.h>	/* for grantpt and unlockpt, at least in Solaris 2.3 */
430 #  include <sys/stropts.h>
431   extern char	*ptsname proto((int /*filedes*/));	/* get name of slave */
432 # endif
433 
434 # ifdef IRIX_PTYS
435 #  include <sys/types.h>
436 #  include <sys/stat.h>
437 # endif
438 
439 void
read_pty_proc(fd)440 read_pty_proc(fd)
441 register int	fd;
442 {
443 	register Process	p;
444 	int	n;
445 	char	ibuf[1024+1];	/* NOTE: room for added NUL */
446 
447 	for (p = procs; ; p = p->p_next) {
448 		if (p == NULL) {
449 			writef("\riproc: unknown fd %d", fd);
450 			return;
451 		}
452 		if (p->p_fd == fd)
453 			break;
454 	}
455 
456 	n = read(fd, (UnivPtr) ibuf, sizeof(ibuf) - 1);
457 	if (n <= 0) {
458 		if (n < 0) {
459 			switch (errno) {
460 			case EIO:
461 			case EWOULDBLOCK:
462 #if EWOULDBLOCK != EAGAIN
463 			case EAGAIN:
464 #endif
465 				/* ??? On some systems, pty reads fail initially, for
466 				 * reasons that are not clear to me (DHR).  This code
467 				 * forgives these specific kinds of failure until the
468 				 * process leaves the NEW state.  We hope that this
469 				 * does not cause a long busy wait.
470 				 */
471 				if (p->p_io_state == IO_NEW)
472 					return;
473 
474 				/* We get here if the i-proc closes stdout
475 				 * before exiting (eg. Bourne Shell),
476 				 * so we treat it as a simple EOF.
477 				 */
478 				break;
479 			default:
480 				/* true I/O error */
481 				swritef(ibuf, sizeof(ibuf),
482 					"\n[pty read error: %s]\n", strerror(errno));
483 				proc_rec(p, ibuf, strlen(ibuf));
484 				/* now treat as EOF... */
485 			}
486 		} /* else, EOF received */
487 		proc_close(p);
488 	} else {
489 		if (p->p_io_state == IO_NEW) {
490 			p->p_io_state = IO_RUNNING;
491 			UpdModLine = YES;
492 		}
493 		proc_rec(p, ibuf, (size_t)n);
494 	}
495 }
496 
497 void
ProcCont()498 ProcCont()
499 {
500 	Process	p = curbuf->b_process;
501 
502 	if (proc_kill(p, SIGCONT) && p->p_child_state == C_STOPPED) {
503 		p->p_child_state = C_LIVE;
504 		UpdModLine = YES;
505 	}
506 }
507 
508 /* Sending non-character info through "keyboard"
509  *
510  * There are two kinds of "out of band" signals we wish to send
511  * through the pty: signals (such as SIGINT) and EOF.  On top
512  * of that, there is a kind of out of band signal we wish not to
513  * send: ERASE and KILL.  Unfortunately, there are a number of ways
514  * in which our environment may vary.  Two ioctls are useful:
515  * TIOCREMOTE and TIOCSIGNAL/TIOCSIG.
516  *
517  *
518  * TIOCREMOTE:
519  *
520  * Some systems support the TIOCREMOTE ioctl.  With this ioctl,
521  * the "input editing" is suppressed on the characters sent
522  * to the slave.  Input editing involves interpreting ERASE,
523  * KILL, INTERRUPT, QUIT, EOF, etc. characters.  It is best
524  * to run this way since JOVE already does input editing.
525  *
526  * The scant documentation on TIOCREMOTE in Solaris2.3 suggests
527  * that the third argument to the TIOCREMOTE ioctl ought to be
528  * an integer (but a pointer to the integer works).  The SunOS4
529  * ldterm(4m) manpage says that the third argument is to be a
530  * pointer to an integer.  At the moment, we only use the pointer
531  * form.
532  *
533  * Although IRIX defines TIOCREMOTE, it does not seem to work.
534  * This may well be true of other systems, so as a safety,
535  * we support "NO_TIOCREMOTE" as a feature deselect macro
536  * for systems that define TIOCREMOTE but are broken.
537  *
538  * Under BSDI's BSD/386 v1.[01], the TIOCREMOTE ioctls appear to fail
539  * for send_xc (without an error indication), but work otherwise.  This
540  * only affects dstop-process, so it is probably best not to define
541  * NO_TIOCREMOTE.  Even if we do define NO_TIOCREMOTE, the dstop-process
542  * may require the user to do a process-newline (apparently, if the tty
543  * input is being canonicalized).  How odd.
544  *
545  *
546  * TIOCSIGNAL/TIOCSIG:
547  *
548  * Some systems support the TIOCSIGNAL ioctl.  With this ioctl,
549  * a signal can be sent through the pty.  Recent (4.3 or later?)
550  * BSD systems seem to provide a TIOCSIG ioctl which is similar.
551  *
552  * The TIOCSIGNAL ioctl is not well documented and seems to be
553  * broken on at least IRIX 5.3.  Again, we provide "NO_TIOCSIGNAL"
554  * to prevent using it on systems that define it but are broken.
555  *
556  * Another mystery: systems vary on how the signal number should be
557  * passed in the TIOCSIGNAL ioctl.  SunOS4 requires that the third
558  * argument be a pointer to an integer, the signal number.  Vanilla
559  * SVR4 requires that the third argument be a an integer, the signal
560  * number.  Solaris2.3 accepts either.  The SunOS 5.3 STREAMS
561  * Programmer's Guide says that the third argument is an int.  We have
562  * not figured out, for an arbitrary system with TIOCSIGNAL, how to
563  * tell which form the third argument should take.  For now, it is
564  * conditionalized on SVR4_PTYS.
565  *
566  * If TIOCSIGNAL/TIOCSIG isn't supplied (perhaps from termios.h), we
567  * cannot send signals to the child when TIOCREMOTE is on, so we just
568  * turn it off for a moment.  This is pretty dubious because the user
569  * might have done an stty to change or disable the characters.
570  *
571  * We don't know how to implement dstop using TIOCSIGNAL/TIOCSIG, so
572  * we use the dubious trick.
573  */
574 
575 # if !defined(NO_TIOCREMOTE) && !defined(TIOCREMOTE)
576 #  define NO_TIOCREMOTE	1
577 # endif
578 
579 # if !defined(NO_TIOCSIGNAL) && !defined(TIOCSIGNAL) && !defined(TIOCSIG)
580 #  define NO_TIOCSIGNAL	1
581 # endif
582 
583 # ifdef NO_TIOCSIGNAL
584 
585 #  define kbd_sig(sig, tch, sch)	send_oxc(tch, sch)
586 
587 # else /* !NO_TIOCSIGNAL */
588 
589 #  define kbd_sig(sig, tch, sch)	send_sig(sig)
590 
591 private void
send_sig(sig)592 send_sig(sig)
593 int	sig;
594 {
595 	Process	p;
596 
597 	if ((p = curbuf->b_process) == NULL || p->p_fd < 0)
598 		complain("[No process]");
599 	ToLast();
600 #  ifdef TIOCSIG
601 	if (ioctl(p->p_fd, TIOCSIG, sig) < 0)
602 		complain("TIOCSIG failed: %d %s", errno, strerror(errno));
603 #  else /* !TIOCSIG */
604 #   ifdef SVR4_PTYS
605 	if (ioctl(p->p_fd, TIOCSIGNAL, sig) < 0)
606 		complain("TIOCSIGNAL failed: %d %s", errno, strerror(errno));
607 #   else /* !SVR4_PTYS */
608 	if (ioctl(p->p_fd, TIOCSIGNAL, (void *) &sig) < 0)
609 		complain("TIOCSIGNAL failed: %d %s", errno, strerror(errno));
610 #   endif /* !SVR4_PTYS */
611 #  endif /* !TIOCSIG */
612 }
613 
614 # endif /* !NO_TIOCSIGNAL */
615 
616 # if defined(NO_TIOCREMOTE) || defined(NO_TIOCSIGNAL) || (!defined(TERMIO) && !defined(TERMIOS)) || defined(VDSUSP)
617 
618 #  if defined(TERMIO) || defined(TERMIOS)
619 #   define send_oxc(tch, sch)	send_xc(sg[NO].c_cc[tch])
620 #  else
621 #   define send_oxc(tch, sfld)	send_xc(tc[NO].sfld)
622 #  endif
623 
624 private void
send_xc(c)625 send_xc(c)
626 char	c;
627 {
628 	Process	p;
629 
630 	if ((p = curbuf->b_process) == NULL || p->p_fd < 0)
631 		complain("[No process]");
632 	ToLast();
633 	{
634 		char	buf[1+1];	/* NOTE: room for added NUL */
635 
636 		buf[0] = c;
637 		proc_rec(p, buf, (size_t)1);
638 
639 		{
640 #  ifndef NO_TIOCREMOTE
641 			int
642 				off = 0,
643 				on = 1;
644 
645 			while (ioctl(p->p_fd, TIOCREMOTE, (UnivPtr) &off) < 0)
646 				if (errno != EINTR)
647 					complain("TIOCREMOTE OFF failed: %d %s", errno, strerror(errno));
648 #  endif /* !NO_TIOCREMOTE */
649 			for (;;) {
650 				switch (write(p->p_fd, (UnivPtr) &c, sizeof(c))) {
651 				case -1: /* error: consider ERRNO */
652 					if (errno == EINTR)
653 						continue;	/* interrupted: try again */
654 					complain("pty write of control failed: %d %s", errno, strerror(errno));
655 					/* NOTREACHED */
656 				case 0: /* nothing happened: try again */
657 					continue;
658 				case 1: /* done */
659 					break;
660 				}
661 				break;
662 			}
663 #  ifndef NO_TIOCREMOTE
664 			while (ioctl(p->p_fd, TIOCREMOTE, (UnivPtr) &on) < 0)
665 				if (errno != EINTR)
666 					complain("TIOCREMOTE ON failed: %d %s", errno, strerror(errno));
667 #  endif /* !NO_TIOCREMOTE */
668 		}
669 	}
670 }
671 
672 # endif /* defined(NO_TIOCREMOTE) || defined(NO_TIOCSIGNAL) */
673 
674 void
ProcEof()675 ProcEof()
676 {
677 # ifdef NO_TIOCREMOTE
678 	/* we have to write a char */
679 	send_oxc(VEOF, t_eofc);
680 # else /* !NO_TIOCREMOTE */
681 	/* write a zero-length record to signify EOF */
682 	static char mess[] = "<EOF> ";	/* NOTE: NUL will be overwritten */
683 	Process	p;
684 
685 	if ((p = curbuf->b_process) == NULL || p->p_fd < 0)
686 		complain("[No process]");
687 	ToLast();
688 	proc_rec(p, mess, sizeof(mess)-1);
689 	while (write(p->p_fd, (UnivPtr) mess, (size_t)0) < 0)
690 		if (errno != EINTR)
691 			complain("[error writing EOF to iproc: %d %s]", errno, strerror(errno));
692 # endif /* !NO_TIOCREMOTE */
693 }
694 
695 void
ProcInt()696 ProcInt()
697 {
698 	kbd_sig(SIGINT, VINTR, t_intrc);
699 }
700 
701 void
ProcQuit()702 ProcQuit()
703 {
704 	kbd_sig(SIGQUIT, VQUIT, t_quitc);
705 }
706 
707 void
ProcStop()708 ProcStop()
709 {
710 # if (!defined(TERMIO) && !defined(TERMIOS)) || defined(VSUSP)
711 	kbd_sig(SIGTSTP, VSUSP, t_suspc);
712 # else
713 	complain("[stop-process not supported]");
714 # endif
715 }
716 
717 void
ProcDStop()718 ProcDStop()
719 {
720 	/* we don't know how to send a dstop via TIOCSIGNAL/TIOCSIG */
721 # if (!defined(TERMIO) && !defined(TERMIOS)) || defined(VDSUSP)
722 	send_oxc(VDSUSP, t_dsuspc);
723 # else
724 	complain("[dstop-process not supported]");
725 # endif
726 }
727 
728 private void
proc_close(p)729 proc_close(p)
730 Process p;
731 {
732 	if (p->p_fd >= 0) {
733 		(void) close(p->p_fd);
734 		FD_CLR(p->p_fd, &global_fd);
735 		p->p_fd = -1;
736 		p->p_io_state = IO_EOFED;	/* I/O is finished */
737 		UpdModLine = YES;
738 	}
739 }
740 
741 private void
proc_write(p,buf,nbytes)742 proc_write(p, buf, nbytes)
743 Process p;
744 char	*buf;
745 size_t	nbytes;
746 {
747 	if (p->p_fd >= 0) {
748 		fd_set	mask;
749 
750 		FD_ZERO(&mask);
751 		FD_SET(p->p_fd, &mask);
752 		while (write(p->p_fd, (UnivPtr) buf, nbytes) <  0)
753 			(void) select(p->p_fd + 1, (fd_set *)NULL, &mask, (fd_set *)NULL,
754 				(struct timeval *)NULL);
755 	}
756 }
757 
758 # ifdef STDARGS
759 private void
proc_strt(char * bufname,bool clobber,char * procname,...)760 proc_strt(char *bufname, bool clobber, char *procname, ...)
761 # else
762 private /*VARARGS2*/ void
763 proc_strt(bufname, clobber, procname, va_alist)
764 	char	*bufname;
765 	bool	clobber;
766 	char	*procname;
767 	va_dcl
768 # endif
769 {
770 	va_list	ap;
771 	char	*argv[32];
772 	Window *owind = curwind;
773 	pid_t	pid;
774 	Process	newp;
775 	Buffer	*newbuf;
776 	int	i,
777 		ptyfd = -1;
778 
779 # if !defined(TERMIO) && !defined(TERMIOS)
780 #  ifdef TIOCSETD
781 	int	ldisc;	/* tty line discipline */
782 #  endif
783 #  ifdef TIOCLSET
784 	int	lmode;	/* tty local flags */
785 #  endif
786 # endif
787 	register char	*s,
788 			*t;
789 	char	ttybuf[32];
790 # ifdef TERMIO
791 	struct termio sgt;
792 # endif
793 # ifdef TERMIOS
794 	struct termios sgt;
795 # endif
796 # ifdef SGTTY
797 	struct sgttyb sgt;
798 # endif
799 
800 # ifdef TIOCGWINSZ
801 	struct winsize win;
802 # else
803 #  ifdef BTL_BLIT
804 #  include <sys/jioctl.h>
805 	struct jwinsize jwin;
806 #  endif
807 # endif
808 
809 	untieDeadProcess(buf_exists(bufname));
810 	isprocbuf(bufname);	/* make sure BUFNAME is either nonexistant
811 				   or is of type B_PROCESS */
812 	va_init(ap, procname);
813 	make_argv(argv, ap);
814 	va_end(ap);
815 	if (access(argv[0], X_OK) != 0) {
816 		complain("[Couldn't access %s: %s]", argv[0], strerror(errno));
817 		/* NOTREACHED */
818 	}
819 
820 # ifdef IRIX_PTYS
821 	/*
822 	 * _getpty may fork off a child to execute mkpts to make a slave pty
823 	 * in /dev (if we need more) and set the correct ownership and
824 	 * modes on the slave pty.  Since _getpty uses waitpid this works
825 	 * fine with regard to our other children, but we do have to be
826 	 * prepared to catch a SIGCHLD for an unknown child and ignore it ...
827 	 */
828 	s = _getpty(&ptyfd, O_RDWR|O_NDELAY, 0600, 0);
829 	if (s == NULL) {
830 		message("[No ptys!]");
831 		goto fail;
832 	}
833 	(void)strcpy(ttybuf, s);
834 # endif /* IRIX_PTYS */
835 # ifdef SVR4_PTYS
836 	if ((ptyfd = open("/dev/ptmx", O_RDWR)) < 0) {
837 		message("[No ptys!]");
838 		goto fail;
839 	}
840 #  ifndef GRANTPT_BUG
841 	/* grantpt() seems to be implemented using a fork/exec.
842 	 * This is done to allow grantpt do do priviledged things
843 	 * via a setuid program.  One consequence is that JOVE's
844 	 * SIGCLD/SIGCHLD handler must not do a wait that would
845 	 * reap the grantpt process.  So much for library routines
846 	 * being black boxes.  Worse, this restriction is not documented.
847 	 */
848 	if (grantpt(ptyfd) < 0) {
849 		message("[grantpt failed]");
850 		goto fail;
851 	}
852 	if (unlockpt(ptyfd) < 0) {
853 		message("[unlockpt failed]");
854 		goto fail;
855 	}
856 #  endif /* !GRANTPT_BUG */
857 	if ((s = ptsname(ptyfd)) == NULL) {
858 		message("[ptsname failed]");
859 		goto fail;
860 	}
861 	strcpy(ttybuf, s);
862 	(void) ioctl(ptyfd, TIOCFLUSH, (UnivPtr) NULL);	/* ??? why? */
863 # endif /* SVR4_PTYS */
864 # ifdef BSD_PTYS
865 	for (s = "pqrs"; ptyfd<0; s++) {
866 		if (*s == '\0') {
867 			message("[Out of ptys!]");
868 			goto fail;
869 		}
870 		for (t = "0123456789abcdef"; *t; t++) {
871 			swritef(ttybuf, sizeof(ttybuf), "/dev/pty%c%c", *s, *t);
872 			if ((ptyfd = open(ttybuf, 2)) >= 0) {
873 				ttybuf[5] = 't';	/* pty => tty */
874 #  ifdef NEVER
875 				/* Make sure both ends are available.
876 				 * ??? This code seems to confuse BSDI's BSD/386 v1.[01]
877 				 * so we have eliminated it.  We leave this scar
878 				 * in case the checking was in fact useful on other
879 				 * systems.  Part of this checking will still be
880 				 * done by the "access" below, but with no recovery.
881 				 */
882 				if ((i = open(ttybuf, 2)) < 0) {
883 					(void) close(ptyfd);
884 					ptyfd = -1;
885 				} else {
886 					(void) close(i);
887 					break;
888 				}
889 #  else
890 				break;
891 #  endif
892 			}
893 		}
894 	}
895 # endif /* BSD_PTYS */
896 	/* Check that we can write to the pty, else things will fail in the
897 	 * child, where they're harder to detect.  This will not work with
898 	 * GRANTPT_BUG because the grantpt and unlockpt have not been done yet.
899 	 */
900 # ifndef GRANTPT_BUG
901 	if (access(ttybuf, W_OK) != 0) {
902 		int	ugh = errno;
903 
904 		message("[Couldn't access ");
905 		message(ttybuf);
906 		message(": ");
907 		message(strerror(ugh));
908 		message("]");
909 		goto fail;
910 	}
911 # endif /* !GRANTPT_BUG */
912 
913 # if !defined(TERMIO) && !defined(TERMIOS)
914 #  ifdef TIOCGETD
915 	(void) ioctl(0, TIOCGETD, (UnivPtr) &ldisc);
916 #  endif
917 #  ifdef TIOCLGET
918 	(void) ioctl(0, TIOCLGET, (UnivPtr) &lmode);
919 #  endif
920 # endif /* !defined(TERMIO) && !defined(TERMIOS) */
921 
922 # ifdef TIOCGWINSZ
923 	(void) ioctl(0, TIOCGWINSZ, (UnivPtr) &win);
924 # else
925 #  ifdef BTL_BLIT
926 	(void) ioctl(0, JWINSIZE, (UnivPtr) &jwin);
927 #  endif /* BTL_BLIT */
928 # endif
929 
930 	switch (pid = fork()) {
931 	case -1:
932 		/* fork failed */
933 
934 		{
935 		int	ugh = errno;	/* hold across library calls */
936 
937 		message("[Fork failed! ");
938 		message(strerror(ugh));
939 		message("]");
940 		goto fail;
941 		}
942 
943 	case 0:
944 		/* child process */
945 
946 # ifdef GRANTPT_BUG
947 		/* grantpt() seems to be implemented using a fork/exec.
948 		 * This is done to allow grantpt do do priviledged things
949 		 * via a setuid program.  One consequence is that JOVE's
950 		 * SIGCLD/SIGCHLD handler must not do a wait that would
951 		 * reap the grantpt process.  So much for library routines
952 		 * being black boxes.  Worse, this restriction is not documented.
953 		 *
954 		 * Worse still, at least Solaris 2.0 and SVR4.0 appear to have
955 		 * a bug: the wait is not restarted once interrupted.  If the wait
956 		 * is interrupted, (1) the grantpt will return a failure status
957 		 * and (2) the process will not be reaped -- it will remain a
958 		 * zombie until JOVE exits or happens to reap it accidentally.
959 		 * Any interrupt could cause the premature end of the wait,
960 		 * but SIGCHLD (actually, SIGCLD) is the most probable.
961 		 *
962 		 * To dodge these bullets, we moved the grantpt into the child
963 		 * where we can turn off signal handling.  Too bad this prevents
964 		 * us giving good diagnostics for grantpt and unlockpt.
965 		 * I hope I've found all the signals caught everywhere else.
966 		 */
967 		(void) setsighandler(SIGCHLD, SIG_DFL);
968 		(void) setsighandler(SIGWINCH, SIG_DFL);
969 		(void) setsighandler(SIGALRM, SIG_DFL);
970 		(void) setsighandler(SIGINT, SIG_DFL);
971 		/* (void) setsighandler(SIGQUIT, SIG_DFL); */	/* dead anyway */
972 		/* (void) setsighandler(SIGHUP, SIG_DFL); */	/* dead anyway */
973 		/* (void) setsighandler(SIGTERM, SIG_DFL); */	/* no longer used */
974 		/* (void) setsighandler(SIGBUS, SIG_DFL); */	/* dead anyway */
975 		/* (void) setsighandler(SIGSEGV, SIG_DFL); */	/* dead anyway */
976 		/* (void) setsighandler(SIGPIPE, SIG_DFL); */	/* dead anyway */
977 
978 		if (grantpt(ptyfd) < 0) {
979 			_exit(errno + 1);
980 		}
981 
982 		if (unlockpt(ptyfd) < 0) {
983 			_exit(errno + 1);
984 		}
985 # endif /* GRANTPT_BUG */
986 		jcloseall();
987 		(void) close(0);
988 		(void) close(1);
989 		(void) close(2);
990 
991 # ifdef TERMIOS
992 		setsid();
993 # else /* !TERMIOS */
994 #  ifdef TIOCNOTTY
995 		/* get rid of controlling tty */
996 		if ((i = open("/dev/tty", 2)) >= 0) {
997 			(void) ioctl(i, TIOCNOTTY, (UnivPtr)NULL);
998 			(void) close(i);
999 		}
1000 #  endif /* TIOCNOTTY */
1001 # endif /* !TERMIOS */
1002 		if (open(ttybuf, 2) != 0)
1003 			_exit(errno+1);
1004 		(void) dup2(0, 1);
1005 		(void) dup2(0, 2);
1006 
1007 # ifdef SVR4_PTYS
1008 		(void) ioctl(0, I_PUSH, (UnivPtr) "ptem");
1009 		(void) ioctl(0, I_PUSH, (UnivPtr) "ldterm");
1010 		(void) ioctl(0, I_PUSH, (UnivPtr) "ttcompat");
1011 # endif
1012 
1013 # ifdef TIOCSCTTY
1014 		/* This is needed by OSF.  It may be needed by BSDPOSIX systems.
1015 		 * It should not hurt any system that define TIOCSCTTY.
1016 		 */
1017 		(void) ioctl(0, TIOCSCTTY); /* make this controling tty */
1018 # endif
1019 
1020 # ifndef NO_TIOCREMOTE
1021 		/* The TIOCREMOTE ioctl prevents the pty code from doing
1022 		 * input editing on characters from the master.  In particular
1023 		 * we don't want ERASE, KILL, INTERRUPT,  QUIT, etc. characters
1024 		 * interpreted.
1025 		 * On SVR4, this must be done *after* the slave side is set up.
1026 		 * The easiest way to ensure this is to put it here, in the child
1027 		 * after the slave is opened and has the STREAMS modules pushed,
1028 		 * and before the master is closed.
1029 		 */
1030 		{
1031 			int	on = 1;
1032 
1033 			if (ioctl(ptyfd, TIOCREMOTE, (UnivPtr) &on) < 0)
1034 				_exit(errno+1);	/* no good way to signal user */
1035 		}
1036 # endif
1037 		close(ptyfd);
1038 
1039 # if !defined(TERMIO) && !defined(TERMIOS)
1040 #  ifdef TIOCSETD
1041 		(void) ioctl(0, TIOCSETD, (UnivPtr) &ldisc);
1042 #  endif
1043 #  ifdef TIOCLSET
1044 		(void) ioctl(0, TIOCLSET, (UnivPtr) &lmode);
1045 #  endif
1046 #  ifdef TIOCSETC
1047 		(void) ioctl(0, TIOCSETC, (UnivPtr) &tc[NO]);
1048 #  endif
1049 #  ifdef USE_TIOCSLTC
1050 		(void) ioctl(0, TIOCSLTC, (UnivPtr) &ls[NO]);
1051 #  endif
1052 # endif /* !defined(TERMIO) && !defined(TERMIOS) */
1053 
1054 # ifdef TIOCGWINSZ
1055 		win.ws_row = curwind->w_height;
1056 		(void) ioctl(0, TIOCSWINSZ, (UnivPtr) &win);
1057 # else /* !TIOCGWINSZ */
1058 #  ifdef BTL_BLIT
1059 		jwin.bytesy = curwind->w_height;
1060 		(void) ioctl(0, JSWINSIZE, (UnivPtr) &jwin);
1061 #  endif
1062 # endif /* !TIOCGWINSZ */
1063 
1064 # if defined(TERMIO) || defined(TERMIOS)
1065 		sgt = sg[NO];
1066 		sgt.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | ICRNL
1067 #  ifdef IXANY	/* not in QNX */
1068 			| IXANY
1069 #  endif
1070 			| IXON | IXOFF);
1071 		sgt.c_lflag &= ~(ECHO);
1072 		sgt.c_oflag &= ~(ONLCR | TABDLY);
1073 #  ifdef TERMIO
1074 		do ; while (ioctl(0, TCSETAW, (UnivPtr) &sgt) < 0 && errno == EINTR);
1075 #  endif
1076 #  ifdef TERMIOS
1077 		do ; while (tcsetattr(0, TCSADRAIN, &sgt) < 0 && errno == EINTR);
1078 #  endif
1079 # else /* !(defined(TERMIO) || defined(TERMIOS)) */
1080 		sgt = sg[NO];
1081 		sgt.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
1082 		(void) stty(0, &sgt);
1083 # endif /* !(defined(TERMIO) || defined(TERMIOS)) */
1084 
1085 		NEWPG();
1086 # ifdef POSIX_PROCS
1087 		tcsetpgrp(0, getpid());
1088 # else /* !POSIX_PROCS */
1089 		i = getpid();
1090 		(void) ioctl(0, TIOCSPGRP, (UnivPtr) &i);
1091 # endif /* POSIX_PROCS */
1092 
1093 		jputenv("EMACS=t");
1094 		jputenv("TERM=emacs");
1095 		/* ??? the following line is not useful for terminfo systems */
1096 		jputenv(sprint("TERMCAP=emacs:co#%d:tc=unknown:", CO-1));
1097 		execvp(argv[0], &argv[1]);
1098 		raw_complain("execvp failed! %s", strerror(errno));
1099 		_exit(errno + 1);
1100 	}
1101 
1102 	newp = (Process) emalloc(sizeof *newp);
1103 
1104 # ifdef O_NDELAY
1105 	fcntl(ptyfd, F_SETFL, O_NDELAY);
1106 # endif
1107 # ifdef O_NONBLOCK
1108 	fcntl(ptyfd, F_SETFL, O_NONBLOCK);
1109 # endif
1110 	newp->p_fd = ptyfd;
1111 	newp->p_pid = pid;
1112 
1113 	newbuf = do_select((Window *)NULL, bufname);
1114 	newbuf->b_type = B_PROCESS;
1115 	newp->p_buffer = newbuf;
1116 	newbuf->b_process = newp;	/* sorta circular, eh? */
1117 	pop_wind(bufname, clobber, B_PROCESS);
1118 	/* Pop_wind() after everything is set up; important!
1119 	   Bindings won't work right unless newbuf->b_process is already
1120 	   set up BEFORE NEWBUF is first SetBuf()'d. */
1121 	ToLast();
1122 	if (!bolp())
1123 		LineInsert(1);
1124 
1125 	newp->p_name = copystr(procname);
1126 	newp->p_io_state = IO_NEW;
1127 	newp->p_child_state = C_LIVE;
1128 	newp->p_mark = MakeMark(curline, curchar);
1129 	newp->p_dbx_mode = NO;
1130 
1131 	newp->p_next = procs;
1132 	procs = newp;
1133 	FD_SET(newp->p_fd, &global_fd);
1134 	if (global_maxfd <= newp->p_fd)
1135 		global_maxfd = newp->p_fd + 1;
1136 	SetWind(owind);
1137 	return;
1138 
1139 fail:
1140 	if (ptyfd >= 0)
1141 		close(ptyfd);
1142 }
1143 
1144 /* NOTE 1: SIGCHLD is an asynchronous signal.  To safely handle it,
1145  * the sigchld_handler simply sets a flag requesting later processing.
1146  * reap_procs is called synchronously to do the actual work.
1147  *
1148  * NOTE 2: SIGCHLD is "level triggered" on some systems (HPUX, IRIX, ...).
1149  * If the signal signal handler is re-established before the child is reaped,
1150  * another signal will be generated immediately.  For this reason, we
1151  * defer the re-establishment until reap_procs is done.
1152  */
1153 
1154 volatile bool	procs_to_reap = NO;
1155 
1156 /*ARGSUSED*/
1157 SIGRESTYPE
sigchld_handler(junk)1158 sigchld_handler(junk)
1159 int	junk;	/* needed for signal handler; not used */
1160 {
1161 	procs_to_reap = YES;
1162 	return SIGRESVALUE;
1163 }
1164 
1165 void
reap_procs()1166 reap_procs()
1167 {
1168 	wait_status_t	w;
1169 	register pid_t	pid;
1170 
1171 	for (;;) {
1172 		pid = wait_opt(&w, (WNOHANG | WUNTRACED));
1173 		if (pid <= 0) {
1174 			if (procs_to_reap) {
1175 				resetsighandler(SIGCHLD, sigchld_handler);
1176 				procs_to_reap = NO;
1177 				/* go around once more to avoid window of vulnerability */
1178 			} else {
1179 				break;
1180 			}
1181 		} else {
1182 			kill_off(pid, w);
1183 		}
1184 	}
1185 }
1186 
1187 void
closeiprocs()1188 closeiprocs()
1189 {
1190 	Process	p;
1191 
1192 	for (p=procs; p!=NULL; p=p->p_next)
1193 		if (p->p_fd >= 0)
1194 			close(p->p_fd);
1195 }
1196 
1197 #endif /* !PIPEPROCS */
1198 
1199 extern char **environ;
1200 
1201 private void
jputenv(def)1202 jputenv(def)
1203 char *def;	/* Note: caller must ensure string persists */
1204 {
1205 	char	**p, *eq;
1206 	static int	headroom = -1;	/* trick: -1 is flag for first time */
1207 
1208 	if ((eq = strchr(def, '=')) == NULL)
1209 		return;
1210 
1211 	for (p = environ; ; p++) {
1212 		if (*p == NULL) {
1213 			if (headroom <= 0) {
1214 #				define JENV_INCR	5
1215 				size_t	sz = ((p-environ) + 1) * sizeof(char *);
1216 				char	**ne = (char **)malloc(sz + JENV_INCR*sizeof(char *));
1217 
1218 				if (ne == NULL)
1219 					break;
1220 				byte_copy(environ, ne, sz);
1221 				p = ne + (p-environ);
1222 				if (headroom == 0)
1223 					free((UnivPtr)environ);
1224 				headroom = JENV_INCR;
1225 				environ = ne;
1226 #				undef JENV_INCR
1227 			}
1228 			headroom -= 1;
1229 			*p++ = def;
1230 			*p = NULL;
1231 			break;
1232 		}
1233 		if (strncmp(*p, def, (size_t) (eq - def + 1)) == 0) {
1234 			*p = def;
1235 			break;
1236 		}
1237 	}
1238 }
1239 
1240 char	proc_prompt[128] = "% ";	/* VAR: process prompt */
1241 
1242 const char *
dbxness(p)1243 dbxness(p)
1244 Process p;
1245 {
1246 	return (p == NULL || !p->p_dbx_mode)? NullStr : "DBX ";
1247 }
1248 
1249 const char *
pstate(p)1250 pstate(p)
1251 Process	p;
1252 {
1253 	static const char	*const ios_name[] = { "New", "Running", "EOFed" };
1254 
1255 	if (p == NULL)
1256 		return "No process";
1257 
1258 	/* Try *not* to report the whole cross-product of child and IO states. */
1259 	switch (p->p_child_state) {
1260 	case C_LIVE:
1261 		return ios_name[p->p_io_state];
1262 	case C_STOPPED:
1263 		return io_eofed(p)? "Stopped; EOFed" : "Stopped";
1264 	case C_EXITED:
1265 		if (io_eofed(p) && p->p_reason == 0)
1266 			return "Done";
1267 		/* FALLTHROUGH */
1268 	default:
1269 		return sprint("%s %d%s",
1270 			(p->p_child_state == C_EXITED? "Exited" : "Killed"),
1271 			p->p_reason,
1272 			(io_eofed(p)? "" : "; not EOFed"));
1273 	}
1274 }
1275 
1276 bool
KillProcs()1277 KillProcs()
1278 {
1279 	register Process	p;
1280 	bool	asked = NO;
1281 
1282 	for (p = procs; p != NULL; p = p->p_next) {
1283 		if (!dead(p)) {
1284 			if (!asked) {
1285 				if (!yes_or_no_p("Some interactive processes are still running; leave anyway? "))
1286 					return NO;	/* processes not killed */
1287 				asked = YES;
1288 			}
1289 			if (!child_dead(p))
1290 				(void) proc_kill(p, SIGKILL);
1291 			proc_close(p);
1292 		}
1293 	}
1294 	return YES;	/* processes killed */
1295 }
1296 
1297 /* VAR: dbx-mode parse string */
1298 char	dbx_parse_fmt[128] = "line \\([0-9]*\\) in \\{file\\|\\} *\"\\([^\"]*\\)\"";
1299 
1300 void
DBXpoutput()1301 DBXpoutput()
1302 {
1303 	if (curbuf->b_process == NULL)
1304 		complain("[Must be in a process buffer to enable dbx mode]");
1305 	curbuf->b_process->p_dbx_mode = !curbuf->b_process->p_dbx_mode;
1306 	UpdModLine = YES;
1307 }
1308 
1309 private void
watch_input(m)1310 watch_input(m)
1311 Mark	*m;
1312 {
1313 	Bufpos	save;
1314 	char	fname[FILESIZE],
1315 		lineno[FILESIZE];
1316 	int	lnum;
1317 	Window	*savew = curwind;
1318 	Buffer	*buf;
1319 
1320 	DOTsave(&save);
1321 	ToMark(m);
1322 	if (dosearch(dbx_parse_fmt, FORWARD, YES) != NULL) {
1323 		get_FL_info(fname, lineno);
1324 		buf = do_find((Window *)NULL, fname, YES, YES);
1325 		pop_wind(buf->b_name, NO, -1);
1326 		lnum = atoi(lineno);
1327 		SetLine(next_line(buf->b_first, lnum - 1));
1328 		SetWind(savew);
1329 	}
1330 	SetDot(&save);
1331 }
1332 
1333 /* Process receive: receives the characters in buf, and appends them to
1334    the buffer associated with p. */
1335 
1336 private void
proc_rec(p,buf,len)1337 proc_rec(p, buf, len)
1338 register Process	p;
1339 char	*buf;
1340 size_t	len;
1341 {
1342 	Buffer	*saveb = curbuf;
1343 	register Window	*w;
1344 	register Mark	*savepoint;
1345 	bool	sameplace,
1346 		do_disp;
1347 
1348 	if (curwind->w_bufp == p->p_buffer)
1349 		w = curwind;
1350 	else
1351 		w = windbp(p->p_buffer);	/* Is this window visible? */
1352 	do_disp = w != NULL && in_window(w, p->p_mark->m_line) != -1;
1353 	SetBuf(p->p_buffer);
1354 	savepoint = MakeMark(curline, curchar);
1355 	ToMark(p->p_mark);		/* where output last stopped */
1356 	sameplace = savepoint->m_line == curline && savepoint->m_char == curchar;
1357 
1358 	/* insert contents of buffer, carefully translating NUL to ^@ */
1359 	buf[len] = '\0';	/* NUL-terminate buffer */
1360 	while (len != 0) {
1361 		if (*buf == '\0') {
1362 			ins_str_wrap("^@", YES, WrapProcessLines ? CO-1 : LBSIZE-1);
1363 			buf++;
1364 			len--;
1365 		} else {
1366 			size_t	sublen = strlen(buf);
1367 
1368 			ins_str_wrap(buf, YES, WrapProcessLines ? CO-1 : LBSIZE-1);
1369 			buf += sublen;
1370 			len -= sublen;
1371 		}
1372 	}
1373 
1374 	if (do_disp && p->p_dbx_mode)
1375 		watch_input(p->p_mark);
1376 	MarkSet(p->p_mark, curline, curchar);
1377 	if (!sameplace)
1378 		ToMark(savepoint);	/* back to where we were */
1379 	DelMark(savepoint);
1380 	/* redisplay now, instead of right after the ins_str, so that
1381 	   we don't get a bouncing effect if point is not the same as
1382 	   the process output position */
1383 	if (do_disp) {
1384 		w->w_line = curline;
1385 		w->w_char = curchar;
1386 		redisplay();
1387 	}
1388 	SetBuf(saveb);
1389 }
1390 
1391 private bool
proc_kill(p,sig)1392 proc_kill(p, sig)
1393 register Process	p;
1394 int	sig;
1395 {
1396 	if (p == NULL)
1397 		complain("[no process]");
1398 	if (!child_dead(p)) {
1399 		if (killpg(p->p_pid, sig) != -1)
1400 			return YES;
1401 		s_mess("Cannot kill %s!", proc_bufname(p));
1402 	}
1403 	return NO;
1404 }
1405 
1406 /* Free process CHILD.  Do all the necessary cleaning up (closing fd's,
1407    etc.). */
1408 
1409 private void
free_proc(child)1410 free_proc(child)
1411 Process	child;
1412 {
1413 	register Process
1414 		p,
1415 		prev = NULL;
1416 
1417 	if (!dead(child))
1418 		return;
1419 	untieDeadProcess(child->p_buffer);
1420 
1421 	for (p = procs; p != child; prev = p, p = p->p_next)
1422 		;
1423 
1424 	if (prev == NULL)
1425 		procs = child->p_next;
1426 	else
1427 		prev->p_next = child->p_next;
1428 	proc_close(child);		/* if not already closed */
1429 
1430 	free((UnivPtr) child->p_name);
1431 	free((UnivPtr) child);
1432 }
1433 
1434 void
untieDeadProcess(b)1435 untieDeadProcess(b)
1436 register Buffer	*b;
1437 {
1438 	if (b != NULL) {
1439 		register Process	p = b->b_process;
1440 
1441 		if (p != NULL) {
1442 			Buffer	*old = curbuf;
1443 
1444 			if (!dead(p))
1445 				complain("Process %s, attached to %b, is %s.",
1446 					 proc_cmd(p), b, pstate(p));
1447 			SetBuf(p->p_buffer);
1448 			DelMark(p->p_mark);
1449 			SetBuf(old);
1450 			p->p_buffer = NULL;
1451 			b->b_process = NULL;
1452 		}
1453 	}
1454 }
1455 
1456 void
ProcList()1457 ProcList()
1458 {
1459 	register Process
1460 		p,
1461 		next;
1462 	char	*fmt = "%-15s  %-15s  %-8s %s",
1463 		pidstr[16];
1464 
1465 	if (procs == NULL) {
1466 		message("[No subprocesses]");
1467 		return;
1468 	}
1469 	TOstart("Process list");
1470 
1471 	Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
1472 	Typeout(fmt, "------", "------", "--- ", "-------");
1473 	for (p = procs; p != NULL; p = next) {
1474 		next = p->p_next;
1475 		swritef(pidstr, sizeof(pidstr), "%d", (int) p->p_pid);
1476 		Typeout(fmt, proc_bufname(p), pstate(p), pidstr, p->p_name);
1477 		if (dead(p)) {
1478 			free_proc(p);
1479 			UpdModLine = YES;
1480 		}
1481 	}
1482 	TOstop();
1483 }
1484 
1485 private void
do_rtp(mp)1486 do_rtp(mp)
1487 register Mark	*mp;
1488 {
1489 	register Process	p = curbuf->b_process;
1490 	LinePtr	line1 = curline,
1491 		line2 = mp->m_line;
1492 	int	char1 = curchar,
1493 		char2 = mp->m_char;
1494 	char	*gp;
1495 	size_t	nbytes;
1496 
1497 	if (dead(p) || p->p_buffer != curbuf)
1498 		return;
1499 
1500 	(void) fixorder(&line1, &char1, &line2, &char2);
1501 	while (line1 != line2->l_next) {
1502 		gp = ltobuf(line1, genbuf) + char1;
1503 		if (line1 == line2) {
1504 			nbytes = char2 - char1;
1505 		} else {
1506 			genbuf[Jr_Len] = EOL;	/* replace NUL with EOL */
1507 			nbytes = Jr_Len - char1 + 1;	/* and include it */
1508 		}
1509 		if (nbytes != 0)
1510 			proc_write(p, gp, nbytes);
1511 		line1 = line1->l_next;
1512 		char1 = 0;
1513 	}
1514 }
1515 
1516 void
ProcNewline()1517 ProcNewline()
1518 {
1519 #ifdef ABBREV
1520 	MaybeAbbrevExpand();
1521 #endif
1522 	SendData(YES);
1523 }
1524 
1525 void
ProcSendData()1526 ProcSendData()
1527 {
1528 #ifdef ABBREV
1529 	MaybeAbbrevExpand();
1530 #endif
1531 	SendData(NO);
1532 }
1533 
1534 private void
SendData(newlinep)1535 SendData(newlinep)
1536 bool	newlinep;
1537 {
1538 	register Process	p = curbuf->b_process;
1539 	register char	*lp,
1540 			*gp;	/* JF fix for better prompt handling */
1541 
1542 	if (dead(p))
1543 		return;
1544 	/* If the process mark was involved in a big deletion, because
1545 	   the user hit ^W or something, then let's do some magic with
1546 	   the process mark.  Problem is that if the user yanks back the
1547 	   text he deleted, the mark stays at the beginning of the region,
1548 	   and so the next time SendData() is called the entire region
1549 	   will be sent.  That's not good.  So, to deal with that we reset
1550 	   the mark to the last line, after skipping over the prompt, etc. */
1551 	if (p->p_mark->m_big_delete) {
1552 		Bufpos	bp;
1553 
1554 		p->p_mark->m_big_delete = NO;
1555 
1556 		DOTsave(&bp);
1557 		ToLast();
1558 		Bol();
1559 		/* While we're looking at a prompt, and while we're
1560 		   moving forward.  This is for people who accidently
1561 		   set their process-prompt to ">*" which will always
1562 		   match! */
1563 		while (LookingAt(proc_prompt, linebuf, curchar)
1564 		&& (REeom > curchar))
1565 			curchar = REeom;
1566 		MarkSet(p->p_mark, curline, curchar);
1567 		SetDot(&bp);
1568 	}
1569 
1570 	if (lastp(curline)) {
1571 		Eol();
1572 		if (newlinep)
1573 			LineInsert(1);
1574 		do_rtp(p->p_mark);
1575 		MarkSet(p->p_mark, curline, curchar);
1576 	} else {
1577 		/* Either we're looking at a prompt, or we're not, in
1578 		   which case we want to strip off the beginning of the
1579 		   line anything that looks like what the prompt at the
1580 		   end of the file is.  In other words, if "(dbx) stop in
1581 		   ProcessNewline" is the line we're on, and the last
1582 		   line in the buffer is "(dbx) ", then we strip off the
1583 		   leading "(dbx) " from this line, because we know it's
1584 		   part of the prompt.  But this only happens if "(dbx) "
1585 		   isn't one of the process prompts ... follow what I'm
1586 		   saying? */
1587 		Bol();
1588 		if (LookingAt(proc_prompt, linebuf, curchar)) {
1589 			do {
1590 				curchar = REeom;
1591 			} while (LookingAt(proc_prompt, linebuf, curchar)
1592 			&& (REeom > curchar));
1593 			strcpy(genbuf, linebuf + curchar);
1594 			Eof();
1595 			ins_str(genbuf);
1596 		} else {
1597 			strcpy(genbuf, linebuf + curchar);
1598 			Eof();
1599 			gp = genbuf;
1600 			lp = linebuf;
1601 			while (*lp == *gp && *lp != '\0') {
1602 				lp += 1;
1603 				gp += 1;
1604 			}
1605 			ins_str(gp);
1606 		}
1607 	}
1608 }
1609 
1610 void
ShellProc()1611 ShellProc()
1612 {
1613 	char	shbuf[20];
1614 	register Buffer	*b;
1615 
1616 	swritef(shbuf, sizeof(shbuf), "*shell-%d*", arg_value());
1617 	b = buf_exists(shbuf);
1618 	if (b == NULL || dead(b->b_process))
1619 		proc_strt(shbuf, NO, "i-shell", Shell, "-is", pr_name(curbuf->b_fname, NO),
1620 			(char *)NULL);
1621 	pop_wind(shbuf, NO, -1);
1622 }
1623 
1624 void
Iprocess()1625 Iprocess()
1626 {
1627 	char	scratch[64],
1628 		*bnm;
1629 	int	cnt = 1;
1630 	Buffer	*bp;
1631 	char	*fn = pr_name(curbuf->b_fname, NO);
1632 
1633 	null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
1634 	bnm = MakeName(ShcomBuf);
1635 	null_ncpy(scratch, bnm, (sizeof scratch) - 1);
1636 	while ((bp = buf_exists(scratch)) != NULL && !dead(bp->b_process))
1637 		swritef(scratch, sizeof(scratch), "%s.%d", bnm, cnt++);
1638 	proc_strt(scratch, YES, ShcomBuf, Shell, ShFlags, ShcomBuf, fn, fn, (char *)NULL);
1639 }
1640 
1641 pid_t	DeadPid;	/* info about ChildPid, if reaped by kill_off */
1642 wait_status_t	DeadStatus;
1643 
1644 #ifdef USE_PROTOTYPES
1645 void
kill_off(pid_t pid,wait_status_t w)1646 kill_off(pid_t pid, wait_status_t w)
1647 #else
1648 void
1649 kill_off(pid, w)
1650 register pid_t	pid;
1651 wait_status_t	w;
1652 #endif
1653 {
1654 	register Process	child;
1655 
1656 	if (pid == ChildPid) {
1657 		/* we are reaping the non-iproc process: record info */
1658 		DeadPid = pid;
1659 		DeadStatus = w;
1660 		return;
1661 	}
1662 
1663 	if ((child = proc_pid(pid)) == NULL)
1664 		return;
1665 
1666 	UpdModLine = YES;		/* we're changing state ... */
1667 	if (WIFSTOPPED(w))
1668 		child->p_child_state = C_STOPPED;
1669 	else {
1670 #ifdef PIPEPROCS
1671 		/* the true process status comes by pipe, not from wait().
1672 		 * However, we must note the death of portsrv processes.
1673 		 */
1674 		child->p_portlive = NO;
1675 #else /* !PIPEPROCS */
1676 		/* record the details of the death of the process.
1677 		 * Kludge: see if we can get any queued EOF from pty first.
1678 		 * We wish to do this to make our message less confusing.
1679 		 */
1680 		while (!io_eofed(child)) {
1681 			int	nfds;
1682 			fd_set	reads;
1683 			struct timeval	notime;
1684 
1685 			FD_ZERO(&reads);
1686 			FD_SET(child->p_fd, &reads);
1687 			notime.tv_sec = 0;
1688 			notime.tv_usec = 0;
1689 			nfds = select(global_maxfd, &reads,
1690 				(fd_set *)NULL, (fd_set *)NULL, &notime);
1691 			if (nfds == 1)
1692 				read_pty_proc(child->p_fd);
1693 			else if (nfds >= 0 || errno != EINTR) {
1694 # ifdef NO_EOF_FROM_PTY
1695 				/* Certain systems never indicate EOF from a slave.
1696 				 * On those systems, we force a close when the direct
1697 				 * child terminates.
1698 				 */
1699 				proc_close(child);
1700 # endif
1701 				break;
1702 			}
1703 		}
1704 		obituary(child, w);
1705 #endif /* !PIPEPROCS */
1706 	}
1707 }
1708 
1709 #ifdef USE_PROTOTYPES
1710 private void
obituary(register Process child,wait_status_t w)1711 obituary(register Process child, wait_status_t w)
1712 #else
1713 private void
1714 obituary(child, w)
1715 register Process	child;
1716 wait_status_t	w;
1717 #endif
1718 {
1719 	UpdModLine = YES;		/* we're changing state ... */
1720 	if (WIFEXITED(w)) {
1721 		child->p_child_state = C_EXITED;
1722 		child->p_reason = WEXITSTATUS(w);
1723 	} else if (WIFSIGNALED(w)) {
1724 		child->p_child_state = C_KILLED;
1725 		child->p_reason = WTERMSIG(w);
1726 	} else {
1727 		/* presume it died peacefully! */
1728 		child->p_child_state = C_EXITED;
1729 		child->p_reason = 0;
1730 	}
1731 
1732 	{
1733 		Buffer	*save = curbuf;
1734 		Bufpos	bp;
1735 		char	mesg[128];
1736 
1737 		/* insert status message now */
1738 		swritef(mesg, sizeof(mesg), "[Process %s: %s]\n",
1739 			proc_cmd(child), pstate(child));
1740 		SetBuf(child->p_buffer);
1741 		DOTsave(&bp);
1742 		ToLast();
1743 		ins_str(mesg);
1744 		SetDot(&bp);
1745 		SetBuf(save);
1746 		redisplay();
1747 	}
1748 }
1749 
1750 #endif /* IPROCS */
1751