home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
jove-4.16-src.tgz
/
tar.out
/
bsd
/
jove
/
portsrv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
5KB
|
207 lines
/************************************************************************
* This program is Copyright (C) 1986-1996 by Jonathan Payne. JOVE is *
* provided to you without charge, and with no warranty. You may give *
* away copies of JOVE, including sources, provided that this notice is *
* included in all the files. *
************************************************************************/
/* This program is invoked by JOVE for two purposes related to PIPEPROCS:
* - "kbd": gather tty input into lumps and send them to JOVE proper.
* - "portsrv": gather process output into lumps and send them to JOVE
* These functions are gathered into one program to reduce the number
* of misc. programs to install. The resulting program is small anyway.
*/
#include "jove.h"
#ifdef PIPEPROCS /* almost the whole file! */
#include <signal.h>
#include <errno.h>
#include "sysprocs.h"
#include "iproc.h"
private struct lump lump;
/* JOVE sends KBDSIG whenever it wants the kbd process (this program)
to stop competing for input from the keyboard. JOVE does this when
JOVE realizes that there are no more interactive processes running.
The reason we go through all this trouble is that JOVE slows down
a lot when it's getting its keyboard input via a pipe. */
private SIGRESTYPE strt_read proto((int));
private SIGRESTYPE
hold_read(junk)
int junk; /* passed in when invoked by a signal; of no interest */
{
signal(KBDSIG, strt_read);
pause();
return SIGRESVALUE;
}
private SIGRESTYPE
strt_read(junk)
int junk;
{
signal(KBDSIG, hold_read);
return SIGRESVALUE;
}
private void
kbd_process()
{
int pid,
n;
signal(SIGINT, SIG_IGN);
pid = getpid();
lump.header.pid = pid;
strt_read(0);
for (;;) {
n = read(0, (UnivPtr) lump.data, sizeof(lump.data));
if (n == -1) {
if (errno != EINTR)
break;
continue;
}
lump.header.nbytes = n;
/* It is not clear what we can do if this write fails */
do ; while (write(1, (UnivPtr) &lump, sizeof(struct header) + n) < 0
&& errno == EINTR);
}
}
/* This is a server for jove sub processes. By the time we get here, our
standard output goes to jove's process input. */
private int tty_fd;
private void
proc_write(ptr, n)
UnivConstPtr ptr;
size_t n;
{
/* It is not clear what we can do if this write fails */
do ; while (write(1, ptr, n) < 0 && errno == EINTR);
}
private void
read_pipe(fd)
int fd;
{
register size_t n;
while ((lump.header.nbytes = read(fd, (UnivPtr) lump.data, sizeof lump.data)) > 0) {
n = sizeof(struct header) + lump.header.nbytes;
proc_write((UnivConstPtr) &lump, n);
}
}
private void
proc_error(str)
char *str;
{
lump.header.pid = getpid();
lump.header.nbytes = strlen(str);
strcpy(lump.data, str);
proc_write((UnivConstPtr) &lump, sizeof(struct header) + lump.header.nbytes);
/* It is not clear what we can do if this write fails */
do ; while (write(tty_fd, (UnivConstPtr)str, strlen(str)) < 0 && errno == EINTR);
exit(-2);
}
private void
portsrv_process(argc, argv)
int argc;
char **argv;
{
int p[2];
pid_t pid;
if (pipe(p) == -1)
proc_error("Cannot pipe jove portsrv.\n");
switch (pid = fork()) {
case -1:
proc_error("portsrv: cannot fork.\n");
/*NOTREACHED*/
case 0:
/* We'll intercept child's output in p[0] */
(void) dup2(p[1], 1);
(void) dup2(p[1], 2);
(void) close(p[0]);
(void) close(p[1]);
NEWPG();
execv(argv[1], &argv[2]);
_exit(-4);
/*NOTREACHED*/
default:
(void) close(0);
tty_fd = open("/dev/tty", 1);
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
(void) close(p[1]);
/* tell jove the pid of the real child as opposed to us */
lump.header.pid = getpid();
lump.header.nbytes = sizeof (pid_t);
byte_copy((UnivConstPtr) &pid, (UnivPtr) lump.data, sizeof(pid_t));
/* It is not clear what we can do if this write fails */
do ; while (write(1, (UnivConstPtr) &lump, sizeof(struct header) + sizeof(pid_t)) < 0
&& errno == EINTR);
/* read proc's output and send it to jove */
read_pipe(p[0]);
/* received EOF - wait for child to die and then write the
child's status to JOVE.
Notice that we use a byte count of -1 (an otherwise
impossible value) as a marker. JOVE "knows" the real
length is sizeof(wait_status_t). */
(void) close(p[0]);
lump.header.pid = getpid();
lump.header.nbytes = -1; /* tell jove we are finished */
/* try to exit like our child did ... */
{
wait_status_t status;
do ; while (wait(&status) != pid);
byte_copy((UnivPtr)&status, (UnivPtr)lump.data,
sizeof(status));
}
/* It is not clear what we can do if this write fails */
do ; while (write(1, (UnivConstPtr) &lump,
sizeof(struct header) + sizeof(wait_status_t)) < 0
&& errno == EINTR);
}
}
int
main(argc, argv)
int argc;
char **argv;
{
if (strcmp(argv[0], "kbd") == 0)
kbd_process();
else
portsrv_process(argc, argv);
return 0;
}
#else /* !PIPEPROCS */
int
main()
{
return 0;
}
#endif /* !PIPEPROCS */