/
Sapphire/bin/
Sapphire/db/
Sapphire/db/OLC_rooms/
Sapphire/db/abi/
Sapphire/db/em_src/
Sapphire/db/helps/
Sapphire/db/helps/emman/ifunc/
Sapphire/db/npcs/Tatt/
Sapphire/db/objects/Tatt/
Sapphire/db/q_data/
Sapphire/db/rooms/Tatt/
Sapphire/doc/
Sapphire/doc/em/
Sapphire/etc/
Sapphire/src/abic/
Sapphire/src/areacon/
Sapphire/src/client/
Sapphire/src/embc/
Sapphire/src/emi/
Sapphire/src/emi/test/
Sapphire/src/include/
Sapphire/src/sapphire/em/
Sapphire/src/tcon/
/*
 * 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
 */