/* ******************************************************************************* ** FILE: TELNET_SAMPLE.C -- example program demonstrating usage of ** TELNET library functions. ** ** PRODUCT: TCPware for VMS ** ** VERSION: V5.6 ** ** Copyright (c) 2001, 2002 by ** Process Software LLC ** Framingham, Massachusetts ** ** Copyright (c) 1997-1999 by ** Process Software Corporation ** Framingham, Massachusetts ** ** This software is furnished under a license for use on a ** single computer system and may be copied only with the ** inclusion of the above copyright notice. This software, or ** any other copies thereof, may not be provided or otherwise ** made available to any other person except for use on such ** system and to one who agrees to these license terms. Title ** to and ownership of the software shall at all times remain ** in Process Software LLC's name. ** ** The information in this document is subject to change ** without notice and should not be construed as a commitment ** by Process Software LLC. Process Software LLC assumes no ** responsibility for any errors that may appear in this document. ** ** ** ** ABSTRACT: ** ** This example program demonstrates the usage of the TCPware's TELNET ** library functions. It connects to three TCPware services -- CHARGEN at ** port 19, DAYTIME at port 13 and ECHO at port 7. By connecting to the ** appropriate port through TELNET library functions. We exchange data ** with the remote host. ** ** In this program, the following TELNET library functions are used: ** ** TEL_ALLOCATE_CCB ** TEL_OPEN_CONNECTION ** TEL_SEND_DATA ** TEL_RECEIVE_DATA ** TEL_CLOSE_CONNECTION ** TEL_DEALLOCATE_CCB ** ** ** IMPLEMENTATION: ** ** Define a foreign command to run this program and then specify the ** remote host and service port on the command line: ** $ TELNET_SAMPLE :== $ TELNET_SAMPLE ** $ TELNET_SAMPLE ** ** ** The following services are implemented in this program: ** ** CHARGEN: The remote host keeps pumping back the printable ascii characters, ** The connection is not closed until you type into CTRL-C. ** This is analogous to the following command at the DCL prompt: ** ** $ telnet 19 ** ** DAYTIME: The remote host returns the time at the host side in ascii ** form, then the host close the connection. Upon receiving ** this close, local side closes the connection and deallocate ** the connection control block. ** This is analogous to the following command at the DCL prompt: ** ** $ telnet 13 ** ** ECHO: The standard echo service will echo back, one-by-one, the ** charater you typed at the terminal. This example performs ** a string-based echo service. Enter a string, then the whole ** string is sent character by character, as if you are typing ** at the terminal. Then the characters are echoed back one by ** one, then combined to a string. ** This is analogous to the following command at the DCL prompt: ** ** $ telnet 7 ** ** ** BUILDING EXECUTABLES: ** ** 1. with DECC: ** $ CC/PREFIX_LIBRARY_ENTRIES=ALL TELNET_SAMPLE ** $ LINK TELNET_SAMPLE, SYS$INPUT/OPTIONS ** TCPWARE:TELLIB/LIB ** SYS$SHARE:TCPWARE_SOCKLIB_SHR/SHARE ** ** 2. with VAXC: ** $ CC TELNET_SAMPLE.C ** $ LINK TELNET_SAMPLE, SYS$INPUT/OPTIONS ** TCPWARE:TELLIB/LIB ** SYS$SHARE:TCPWARE_SOCKLIB_SHR/SHARE ** SYS$SHARE:VAXCRTL.EXE/SHARE ** ******************************************************************************* */ #include #include #include #include #include #include /* for STS$M_SUCCESS */ #include #include #include #include "tcpware_include:_ccbfld.h" /* ** Macros to check VMS success/failure status */ #define SUCCESS(status) (status & STS$M_SUCCESS) #define FAILURE(status) (!(status & STS$M_SUCCESS)) /* ** ccb *MUST* be at a fixed location for a single connection from ** TEL_ALLOCATE_CCB() to TEL_DEALLOCATE_CCB(). ** For simplicity let it be a global or static variable. */ unsigned long int ccb_ptr; /* pointer to Connection Control Block */ /* ** Telnet receive and send data buffer size, as recommended in the ** Programmer's Guide */ #define TEL_RCVSIZ 1024 #define TEL_SNDSIZ 1024 /* function prototypes */ long TEL_ABORT_CONNECTION( void *ccb_ptr); long TEL_ALLOCATE_CCB( void *ccb_ptr, unsigned short *rcv_buf_size, unsigned short *snd_buf_size); long TEL_CLOSE_CONNECTION( void *ccb_ptr); long TEL_CREATE_TERMINAL( void *ccb_ptr, unsigned long *ia, struct dsc$descriptor *host, void (*cmdrtn)(), unsigned long *efn, void (*ast)(), unsigned short *port, unsigned long *timo, long flags); long TEL_DEALLOCATE_CCB( void *ccb_ptr); long TEL_GET_CCB( void *ccb_ptr, unsigned short *field_code, void *value); long TEL_OPEN_CONNECTION( void *ccb_ptr, unsigned long *ia, struct dsc$descriptor *host, void (*cmdrtn)(), unsigned long *efn, void (*ast)(), unsigned short *port, unsigned long *timeout); long TEL_RECEIVE_DATA( void *ccb_ptr, unsigned short *buf_siz, char *buffer, unsigned short *byte_count); long TEL_SEND_COMMAND( void *ccb_ptr, char *buffer, unsigned short *byte_count); long TEL_SEND_DATA( void *ccb_ptr, char *buffer, unsigned short *byte_count); long TEL_SEND_URGENT( void *ccb_ptr, char *buffer, unsigned short *byte_count); long TEL_SET_CCB( void *ccb_ptr, unsigned short *field_code, void *value); long ef_output_data(); main(int argc, char *argv[]) { unsigned long ia; /* host internet address */ unsigned short portnum; /* for the tcpware service */ unsigned short rcv_buf_size = TEL_RCVSIZ; unsigned short snd_buf_size = TEL_SNDSIZ; unsigned short byte_count = 1; struct hostent *he; /* Host entry */ char sendbuf[TEL_SNDSIZ]; /* Send buffer */ int i; /* Loop index */ unsigned long efn; /* Event flag number */ long status; /* Return status */ /* ** Check the command line arguments */ if (argc != 3) { printf( "\nUsage: \n"); printf( "service_port: 19 (Chargen) or 13 (Daytime) or 7 (Echo)\n\n"); exit( 1); } portnum = atoi( argv[2]); /* clear terminal IO */ printf( "\n"); fflush( stdin); /* ** Find remote host IP address, which is obtained from the host name ** or its dotted digits, then saved into a unsigned long integer ia. */ he = gethostbyname( argv[1]); if (he != NULL) ia = *( (unsigned long int *)he->h_addr); else ia = inet_addr( argv[1]); if (ia == -1) { printf( "Could not lookup remote host name.\n"); exit( 1); } /* ** Allocate the Connection Control Block */ status = TEL_ALLOCATE_CCB( &ccb_ptr, &rcv_buf_size, &snd_buf_size); if ( FAILURE( status) ) { perror( "TEL_ALLOCATE_CCB"); exit( 1); } /* ** Open telnet connection to host, when data arrives, the efn is set */ lib$get_ef( &efn); status = TEL_OPEN_CONNECTION( &ccb_ptr, &ia, 0, 0, &efn, 0, &portnum, 0); if ( FAILURE( status) ) { perror( "TEL_OPEN_CONNECTION"); exit( 1); } switch (portnum) { case 19: /* CHARGEN */ case 13: /* DAYTIME */ /* ** In the following loop, the process waits until the event ** flag efn is set, then output the data in the receive buffer. ** If the connection is still in normal state, repeat the process */ do { status = sys$waitfr( efn); if ( FAILURE( status) ) lib$signal( status); else status = ef_output_data(); } while ( SUCCESS( status) ); break; case 7: /* ECHO */ do { /* ** Enter a string */ printf( "SEND: "); if ( gets( sendbuf) == NULL) break; /* exit loop on ^Z */ printf( "ECHO: "); /* ** Send data to remote host, character by character. ** The remote ECHO service will echo back each character ** immediately, the event flag gets set, and the ** TEL_RECEIVE_DATA is called to receive the character */ for (i = 0; (i < TEL_SNDSIZ) && (sendbuf[i] != '\0'); i++) { status = TEL_SEND_DATA(&ccb_ptr, &sendbuf[i], &byte_count); if ( FAILURE( status) ) { perror( "TEL_SEND_DATA"); exit( 1); } sys$waitfr( efn); status = ef_output_data(); } printf("\n"); } while ( SUCCESS( status) ); break; default: printf( "Specified port number is not handled by this program\n"); break; } /* ** Close the telnet connection and deallocate the CCB */ TEL_CLOSE_CONNECTION( &ccb_ptr); TEL_DEALLOCATE_CCB( &ccb_ptr); lib$free_ef( &efn); exit( 1); } /* ** Routine to output currently received data */ long ef_output_data() { char rcvbuf[TEL_RCVSIZ + 1]; unsigned short buf_size = TEL_RCVSIZ; unsigned short rcvlen; long status; /* ** Receive data from remote host */ status = TEL_RECEIVE_DATA( &ccb_ptr, &buf_size, rcvbuf, &rcvlen); if ( SUCCESS( status) ) { rcvbuf[rcvlen] = '\0'; printf( "%s", rcvbuf); } return (status); }