fitter
12-05-2001, 01:10 AM
This code mostly works (needs to be compiled with -lutil), but I get looped garbage output when I try to exit. I've only just begun learning how to use openpty properly, so if anyone can give me a bit of help here, I'd appreciate it.
For what it's worth, I don't get the garbage output on a variant of BSD.
/* get pseudo terminal, then fork process and communicate with it through
* slave/master devices returned by openpty()
*/
#include <stdio.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <syslimits.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
int
main( int argc, char *argv[] )
{
size_t c;
int master, slave, i, pid;
char ttyname[ MAXPATHLEN ];
char buf[ LINE_MAX ];
char *execargs[ 2 ] = { "/bin/csh",
NULL };
if ( openpty( &master, &slave, ttyname, NULL, NULL ) < 0 ) {
perror( "openpty" );
exit( 1 );
}
printf( "tty is %s.\n", ttyname );
switch( fork()) {
case 0:
printf( "Entering child...\n" );
for ( i = 0; i < 3; i++ ) {
if ( close( i ) < 0 ) {
perror( "close" );
exit( 2 );
}
}
if ( close( master ) < 0 ) {
perror( "close" );
exit( 2 );
}
for ( i = 0; i < 3; i++ ) {
if ( dup2( slave, i ) < 0 ) {
perror( "dup2" );
exit( 3 );
}
}
if ( setsid() == -1 ) {
perror( "setsid()" );
exit( 4 );
}
if ( ioctl( slave, TIOCSCTTY, 0 ) < 0 ) {
perror( "ioctl" );
exit( -10 );
}
if ( execve( "/bin/csh", execargs, 0 ) < 0 ) {
perror( execargs[ 0 ] );
exit( -9 );
}
_exit( -43 ); /* should not get here */
case -1:
perror( "fork()" );
exit( 5 );
}
fprintf( stderr, "In parent.\n" );
if ( close( slave ) < 0 ) {
perror( "close" );
exit( 2 );
}
if ( fork() == 0 ) {
while(( c = read( 0, buf, LINE_MAX )) > 0 ) {
write( master, buf, c );
}
exit( 0 );
}
while (( c = read( master, buf, LINE_MAX )) > 0 ) {
write( 1, buf, c );
}
pid = wait( &i );
printf( "child with pid %d finished.\n", pid );
#ifdef notdef /* doesn't help */
fflush( stdin );
fflush( stdout );
#endif
close( master );
exit( 0 );
}
--
On a related note, I'd like to get rid of the stdin echo I get as a result of the way I've set this up. Pointers, anyone?
For what it's worth, I don't get the garbage output on a variant of BSD.
/* get pseudo terminal, then fork process and communicate with it through
* slave/master devices returned by openpty()
*/
#include <stdio.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <syslimits.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
int
main( int argc, char *argv[] )
{
size_t c;
int master, slave, i, pid;
char ttyname[ MAXPATHLEN ];
char buf[ LINE_MAX ];
char *execargs[ 2 ] = { "/bin/csh",
NULL };
if ( openpty( &master, &slave, ttyname, NULL, NULL ) < 0 ) {
perror( "openpty" );
exit( 1 );
}
printf( "tty is %s.\n", ttyname );
switch( fork()) {
case 0:
printf( "Entering child...\n" );
for ( i = 0; i < 3; i++ ) {
if ( close( i ) < 0 ) {
perror( "close" );
exit( 2 );
}
}
if ( close( master ) < 0 ) {
perror( "close" );
exit( 2 );
}
for ( i = 0; i < 3; i++ ) {
if ( dup2( slave, i ) < 0 ) {
perror( "dup2" );
exit( 3 );
}
}
if ( setsid() == -1 ) {
perror( "setsid()" );
exit( 4 );
}
if ( ioctl( slave, TIOCSCTTY, 0 ) < 0 ) {
perror( "ioctl" );
exit( -10 );
}
if ( execve( "/bin/csh", execargs, 0 ) < 0 ) {
perror( execargs[ 0 ] );
exit( -9 );
}
_exit( -43 ); /* should not get here */
case -1:
perror( "fork()" );
exit( 5 );
}
fprintf( stderr, "In parent.\n" );
if ( close( slave ) < 0 ) {
perror( "close" );
exit( 2 );
}
if ( fork() == 0 ) {
while(( c = read( 0, buf, LINE_MAX )) > 0 ) {
write( master, buf, c );
}
exit( 0 );
}
while (( c = read( master, buf, LINE_MAX )) > 0 ) {
write( 1, buf, c );
}
pid = wait( &i );
printf( "child with pid %d finished.\n", pid );
#ifdef notdef /* doesn't help */
fflush( stdin );
fflush( stdout );
#endif
close( master );
exit( 0 );
}
--
On a related note, I'd like to get rid of the stdin echo I get as a result of the way I've set this up. Pointers, anyone?