/* * 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 */