ji@garfield.columbia.edu (John Ioannidis) (03/04/86)
[ Line eater, I dare yo@^&U. (mjam, slurp, gulp) In article <641@puff.UUCP>, tom@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@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@cs.columbia.EDU USnail: John Ioannidis ji@garfield.columbia.EDU 450 Computer Science Columbia University, USENET: ...{seismo|topaz}! New York, NY 10027 columbia!garfield!ji ... It's all Greek to me!