/*
* Copyright (C) 1995-1997 Christopher D. Granz
*
* This header may not be removed.
*
* Refer to the file "License" included in this package for further
* information and before using any of the following.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "client.h"
/*
* Prototypes
*/
static char * get_input ( void );
/*
* Globals
*/
static struct timeval tNullTime;
static char cInputBuf[MAX_INPUT];
/*
* Functions
*/
int main( int iArgC, char *pArgV[], char *pEnv[] )
{
struct sockaddr_in siTelnetName;
struct sockaddr_in siBinaryName;
struct hostent *pHost;
fd_set fdsIn;
fd_set fdsOut;
char cBuffer[512];
char *pInput;
int iTelnetSocket = -1;
int iBinarySocket = -1;
int iRead;
bool b = FALSE;
if ( iArgC < 3 || ( iArgC > 2 && is_number( pArgV[2] ) == FALSE ) )
{
fprintf( stderr,
"\nUsage: %s <mud site> <standard port> [binary port]\n",
pArgV[0] );
exit( 1 );
}
signal( SIGPIPE, SIG_IGN );
if ( ( pHost = gethostbyname( pArgV[1] ) ) == NULL )
fatal( "Could not find host." );
if ( ( iTelnetSocket = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
fatal( "%s.", strerror( errno ) );
if ( pArgV[3] != NULL && is_number( pArgV[3] ) == TRUE )
{
if ( ( iBinarySocket = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
fatal( "%s.", strerror( errno ) );
siBinaryName.sin_family = AF_INET;
siBinaryName.sin_port = htons( atoi( pArgV[3] ) );
memcpy( &siBinaryName.sin_addr.s_addr, pHost->h_addr,
pHost->h_length );
}
siTelnetName.sin_family = AF_INET;
siTelnetName.sin_port = htons( atoi( pArgV[2] ) );
memcpy( &siTelnetName.sin_addr.s_addr, pHost->h_addr, pHost->h_length );
if ( connect( iTelnetSocket, (struct sockaddr *) &siTelnetName,
sizeof( siTelnetName ) ) < 0 )
fatal( "%s.", strerror( errno ) );
if ( iBinarySocket > -1 )
{
/*
* Must write to the telnet socket as soon as possible or
* the server may not reconigize this as a Sapphire compatiable
* client.
*/
/* if ( write( iTelnetSocket, SAPPHIRE_IDENT_CODE,
sizeof( SAPPHIRE_IDENT_CODE ) ) < 0 )
fatal( "%s.", strerror( errno ) ); */
errno = 0;
/*
* Loop until the connection is made (or there is an error).
* If the program hangs on connecting to non-Sapphire MUDs, this
* is probably where.
*/
while ( errno != EISCONN )
{
if ( connect( iBinarySocket, (struct sockaddr *) &siBinaryName,
sizeof( siBinaryName ) ) < 0 && errno != EISCONN )
fatal( "%s.", strerror( errno ) );
}
if ( fcntl( iBinarySocket, F_SETFL, O_NONBLOCK ) < 0 )
fatal( "%s.", strerror( errno ) );
}
if ( fcntl( iTelnetSocket, F_SETFL, O_NONBLOCK ) < 0 )
fatal( "%s.", strerror( errno ) );
FD_ZERO( &fdsIn );
FD_ZERO( &fdsOut );
/*
* Main loop.
*/
for ( ; ; )
{
FD_SET( iTelnetSocket, &fdsIn );
FD_SET( iTelnetSocket, &fdsOut );
if ( select( ( iTelnetSocket + 1 ), &fdsIn, &fdsOut, NULL,
&tNullTime ) < 0 )
fatal( "%s.", strerror( errno ) );
if ( FD_ISSET( iTelnetSocket, &fdsIn ) )
{
if ( ( iRead = read( iTelnetSocket, cBuffer,
( sizeof( cBuffer ) - 1 ) ) ) < 0 )
fatal( "%s.", strerror( errno ) );
if ( iRead == 0 )
break;
if ( cBuffer[iRead - 1] == '\n' || cBuffer[iRead - 1] == '\r' )
b = TRUE;
else
b = FALSE;
cBuffer[iRead] = '\0';
print_text( cBuffer );
print_text( cInputBuf );
fflush( stdout );
FD_CLR( iTelnetSocket, &fdsIn );
}
if ( FD_ISSET( iTelnetSocket, &fdsOut )
&& ( pInput = get_input( ) ) != NULL )
{
if ( write( iTelnetSocket, pInput, strlen( pInput ) ) < 0 )
fatal( "%s.", strerror( errno ) );
cInputBuf[0] = '\0';
FD_CLR( iTelnetSocket, &fdsOut );
}
}
if ( b == FALSE )
putc( '\n', stderr );
fprintf( stderr, "Connection closed by remote host.\n" );
close( iTelnetSocket );
if ( iBinarySocket > -1 )
close( iBinarySocket );
return ( 0 );
}
void recv_graphic( int iDesc )
{
}
/*
* Write only printable characters of a string to stdout so we do not
* end up writting garbage to the screen.
*/
void print_text( char *pText )
{
while ( *pText != '\0' )
{
if ( isprint( *pText ) != 0 || isspace( *pText ) != 0 )
putc( *pText, stdout );
pText++;
}
}
/*
* Read one line of input (into static buffer) from stdin,
* if there is one.
*/
char *get_input( void )
{
static int i;
fd_set fdsIn;
char c;
FD_ZERO( &fdsIn );
FD_SET( STDIN_FILENO, &fdsIn );
if ( select( ( STDIN_FILENO + 1 ), &fdsIn, NULL, NULL, &tNullTime )
< 0 )
fatal( "%s.", strerror( errno ) );
if ( !FD_ISSET( STDIN_FILENO, &fdsIn ) )
return ( NULL );
do
{
c = getc( stdin );
if ( c == EOF )
return ( NULL );
cInputBuf[i++] = c;
}
while ( c != '\n' && i < ( MAX_INPUT - 1 ) );
cInputBuf[i] = '\0';
i = 0;
if ( cInputBuf[0] == '\0' )
return ( NULL );
else
return ( cInputBuf );
}
/*
* Returns TRUE if a string is all digits; FALSE otherwise.
*/
bool is_number( char *pStr )
{
while ( *pStr != '\0' )
{
if ( isdigit( *pStr ) == 0 )
return ( FALSE );
pStr++;
}
return ( TRUE );
}
/*
* End of main.c
*/