prwopen: A popen-like routine using ptys
John Ioannidis
ji at garfield.columbia.edu
Tue Mar 4 13:49:50 AEST 1986
[ Line eater, I dare yo@^&U. (mjam, slurp, gulp)
In article <641 at puff.UUCP>, tom at puff.wisc.edu (Thomas Scott Christiansen) writes:
> Does anyone have a nice package that allows you to say something
> like
> process("silly_game arg1 arg2",&input_fd,&output_fd,&error_fd)
> and start the process running not on a pipe (I have one of these) but
> rather on a pty so that the proc can 1) do ioctls 2) have line buffered
> output ?
>
Well, here it is, after all.
This is my version of such a thing; it's a substitute for popen(3) when
any of the following bothers you:
* You want to be able to both read from and write to the child process
* You want the program executed in the child process to think it's talking
to a terminal.
There are a couple of things to note: First, I supply it an array of FILE
pointers (`a la pipe(2)), which are subsequently defined for unbufferred I/O.
Second, I have hardwired into the code a maximum of 32 pty's and a maximum
of 20 available file descriptors. The code is pretty much straightforward,
and parts of it are shamelessly stolen from popen(3) and script(1). I guess
there is only one way of doing some things.
----------------- CUT HERE --------------
/* Sample program, it just calls ftp and exits */
#include <stdio.h>
main()
{
FILE *foo[2];
char buf[80];
char pr, cu=0;
prwopen( "ftp -n", foo );
for(;;)
{
pr=cu;
cu=getc( foo[0] );
putchar( cu );
fflush( stdout );
if( pr=='>' && cu==' ' )
break;
}
fprintf( foo[1], "open localhost\n" );
fflush( foo[1] );
for(;;)
{
pr=cu;
cu=getc( foo[0] );
putchar( cu );
fflush( stdout );
if( pr=='>' && cu==' ' )
break;
}
fprintf( foo[1], "quit\n" );
for(;;)
{
pr=cu;
cu=getc( foo[0] );
if( cu==EOF )
break;
putchar( cu );
fflush( stdout );
if( pr=='>' && cu==' ' )
break;
}
printf( "prwclose returns %d\n", prwclose( foo ) );
}
/*
* NAME
* prwopen - modified popen(3) to work with pty's instead of
* pipes, and also provide both read and write
* capabilities to the child process.
*
* SYNOPSIS
* #include <stdio.h>
*
* int prwopen( cmd, streams )
* char *cmd;
* FILE streams[2];
*
* AUTHOR (actually, merger!)
* John Ioannidis, ioannidis at cs.columbia.edu
*
* SEE ALSO
* popen(3), after which this call is modelled.
*
* UNIX SOURCES USED
* popen(3), script(1)
*
*/
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sgtty.h>
static int pip_pid[ 20 ];
int
prwopen( cmd, streams )
char *cmd;
FILE *streams[];
{
int pty, pid, j;
struct stat stb;
char c;
static char *line = "/dev/ptyp0";
for( c = 'p'; c <= 's'; c++ )
{
line[strlen("/dev/pty")] = c;
line[strlen("/dev/ptyp")] = '0';
if( stat( line, &stb ) < 0 )
break;
for( j = 0; j < 16; j++ )
{
line[strlen("/dev/ptyp")] = "0123456789abcdef"[j];
if( ( pty = open( line, 2 )) > 0 )
goto opened;
}
}
return( -1 );
opened:
switch( pid = fork() )
{
case -1:
return( -1 );
case 0:
{
int t, tty;
struct sgttyb bf;
t=open( "/dev/tty", 2 );
if( t >= 0 )
{
ioctl( t, TIOCNOTTY, (char *)0 );
close( t );
}
line[strlen("/dev/")] = 't';
tty = open( line, 2 );
close( pty );
ioctl( tty, TIOCGETP, &bf );
bf.sg_flags &= ~ECHO;
ioctl( tty, TIOCSETP, &bf );
dup2( tty, 0 );
dup2( tty, 1 );
dup2( tty, 2 );
close( tty );
execl( "/bin/sh", "sh", "-c", cmd, 0 );
_exit(1);
}
}
pip_pid[pty]=pid;
if( (streams[0] = fdopen( pty, "r" )) == NULL ||
(streams[1] = fdopen( pty, "w" )) == NULL )
{
return( -1 );
}
setbuf( streams[0], NULL );
setbuf( streams[1], NULL );
return( 0 );
}
prwclose( streams )
FILE *streams[];
{
register f, r, (*hstat)(), (*istat)(), (*qstat)();
int status;
f = fileno(streams[1]);
fclose(streams[0]);
fclose(streams[1]);
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
hstat = signal(SIGHUP, SIG_IGN);
while((r = wait(&status)) != pip_pid[f] && r != -1)
;
if(r == -1)
status = -1;
signal(SIGINT, istat);
signal(SIGQUIT, qstat);
signal(SIGHUP, hstat);
return(status);
}
------- CUT HERE -----
I hope this will be useful.
#include <appropriate_disclaimers>
VOICE: +1 212 280 5510 ARPA: ioannidis at cs.columbia.EDU
USnail: John Ioannidis ji at garfield.columbia.EDU
450 Computer Science
Columbia University, USENET: ...{seismo|topaz}!
New York, NY 10027 columbia!garfield!ji
... It's all Greek to me!
More information about the Comp.unix.wizards
mailing list