www.pudn.com > watsock.zip > WINSK.C


 
#include "winsock.h"  /* Must be included before TCPSTREAM definition */ 
 
/* TCP input buffer -- must be large enough to prevent overflow */ 
 
#define BUFLEN 512 
#define NIL 0                   /* convenient name */ 
 
/* TCP I/O stream (must be before osdep.h is included) */ 
 
#define TCPSTREAM struct tcp_stream 
TCPSTREAM { 
  char *host;                   /* host name */ 
  char *localhost;              /* local host name */ 
  SOCKET tcps;                   /* tcp socket */ 
  long ictr;                    /* input counter */ 
  char *iptr;                   /* input pointer */ 
  char ibuf[BUFLEN];            /* input buffer */ 
}; 
 
#define __XVT__                 /* To avoid "ERROR redifinition" problem */ 
 
/* Private function prototypes */ 
#include "mail.h" 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include "debug.h" 
 
#define MEM_SAFETY_DEBUG 
// #include  
 
/**** EXTERNALS */ 
extern void ecs_error(char *); 
char *local_hostname = "isa386-15" ; 
 
 
 
/* PROTOTYPES of win_* routines */ 
SOCKET win_socket(int domain, int type, int protocol); 
int win_connect(SOCKET s, unsigned long address, unsigned short s_port); 
int win_close(SOCKET s); 
int win_select(int width, fd_set *readfds, 
		fd_set *writefds, fd_set *exceptfds, long timeout); 
int win_read(SOCKET s, char *buf, int nbyte); 
int win_write(SOCKET s, char *buf, int nbyte); 
unsigned long win_rhost(char **name); 
unsigned long win_htonl(unsigned long hostlong); 
unsigned long win_ntohl(unsigned long netlong); 
unsigned short win_htons(unsigned short hostshort); 
unsigned short win_ntohs(unsigned short netshort); 
unsigned long win_inet_addr(char *cp); 
void fatal (char *string); 
void *fs_get (size_t size); 
 
/* Holds  the addresses of the socket routines in the socket dll */ 
#define SOCKDLL struct SockDll 
SOCKDLL  { 
  SOCKET (PASCAL FAR * socket)(int af, int type, int protocol); 
  int (PASCAL FAR * connect)(SOCKET s, struct sockaddr FAR *name, int namelen); 
  int (PASCAL FAR *closesocket)(SOCKET s); 
  int (PASCAL FAR *select)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, struct timeval FAR *timeout); 
  int (PASCAL FAR *recv)(SOCKET s, char FAR *buf, int len, int flags); 
  int (PASCAL FAR *send)(SOCKET s, char FAR *buf, int len, int flags); 
  struct hostent * (PASCAL FAR *gethostbyname)(char FAR *name); 
  int (PASCAL FAR *gethostname)(char FAR *name, int namelen); 
  unsigned long (PASCAL FAR *inet_addr)(char FAR *cp); 
  unsigned long (PASCAL FAR *so_rhost)(char  **cp); 
  u_long (PASCAL FAR *htonl)(u_long hostlong); 
  u_short (PASCAL FAR *htons)(u_short hostshort); 
  u_long (PASCAL FAR *ntohl)(u_long netlong); 
  u_short (PASCAL FAR *ntohs)(u_short hostshort); 
}; 
 
/****** STATIC DATA ******/ 
 
static SOCKDLL *sockdll = NULL;            /* Global to this file */ 
static HANDLE hLibrary = 0;                /* Used to free library */ 
 
/* END STATIC DATA ***/ 
 
 
int TCP_init_libs(char *global_dir); 
void TCP_free_libs(void); 
void TCP_test(char *buf) ; 
void tcp_close(TCPSTREAM *stream); 
TCPSTREAM *tcp_open (char *host,long port); 
long tcp_soutr (TCPSTREAM *stream,char *string); 
char *tcp_getline (TCPSTREAM *stream); 
long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer); 
 
 
#ifdef MSDOS 
int netshut() {}; 
#endif 
 
/* Global data */ 
 
unsigned long rndm = 0xfeed;    /* initial `random' number */ 
 
/* Write current time in RFC 822 format 
 * Accepts: destination string 
 */ 
 
char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 
 
/* Copy string to free storage 
 * Accepts: source string 
 * Returns: free storage copy of string 
 */ 
 
char *cpystr (char *string) 
{ 
  if (string) {                 /* make sure argument specified */ 
    char *dst = (char *) fs_get (1+strlen (string)); 
    strcpy (dst,string); 
    return (dst); 
  } 
  else return NIL; 
} 
 
/************************************************************************/ 
/* Get a block of free storage 
 * Accepts: size of desired block 
 * Returns: free storage block 
 */ 
 
void *fs_get (size_t size) 
{ 
  void *block = NULL; 
 
  /* Make sure "size" is within the 64K limit */ 
  if(size > (size_t)0xffff){ 
      fatal("Cannot allocate more than 64K memory"); 
      return(NULL);     /* Should  have already quit */ 
  } 
 
  block = (void *)malloc(size);  /* Would use smartheap */ 
  if (!block) 
      fatal ("Out of free storage"); 
 
  /* Set to zero */ 
  memset(block, 0, size); 
  return (block); 
} 
 
 
/* Resize a block of free storage 
 * Accepts: ** pointer to current block 
 *          new size 
 */ 
 
void fs_resize (void **block,size_t size) 
{ 
  if(size > (size_t)0xffff) 
      fatal("Can't resize to more than 64k"); 
 
  if (!(*block = realloc ((char *)*block,size))) 
      fatal ("Can't resize free storage"); 
 
} 
 
 
/* Return a block of free storage 
 * Accepts: ** pointer to free storage block 
 */ 
 
void fs_give (void **block) 
{ 
 
  if(block && *block) 
     free ((char *)*block);  /* Would use smartheap */ 
 
  if(block) 
     *block = NIL; 
} 
 
 
/* Report a fatal error 
 * Accepts: string to output 
 */ 
 
void fatal (char *string) 
{ 
  debug_trace (string);            /* pass the string */ 
  debug_trace ("\n"); 
  abort ();                     /* die horribly */ 
} 
 
 
/* Copy string with CRLF newlines 
 * Accepts: destination string 
 *          pointer to size of destination string 
 *          source string 
 *          length of source string 
 */ 
 
char *strcrlfcpy (char **dst,unsigned long *dstl,char *src,unsigned long srcl) 
{ 
  if (srcl > *dstl) {           /* resize if not enough space */ 
    fs_give ((void **) dst);    /* fs_resize does an unnecessary copy */ 
    *dst = (char *) fs_get ((*dstl = srcl) + 1); 
  } 
				/* copy strings */ 
  if (srcl) memcpy (*dst,src,srcl); 
  *(*dst + srcl) = '\0';        /* tie off destination */ 
  return *dst;                  /* return destination */ 
} 
 
 
/* Length of string after strcrlfcpy applied 
 * Accepts: source string 
 *          length of source string 
 */ 
 
unsigned long strcrlflen (STRING *s) 
{ 
  return SIZE (s);              /* no-brainer on DOS! */ 
} 
 
 
/* Server log in (dummy place holder) 
 * Accepts: user name string 
 *          password string 
 *          optional place to return home directory 
 * Returns: T if password validated, NIL otherwise 
 */ 
 
long server_login (char *user,char *pass,char **home) 
{ 
  return NIL; 
} 
 
 
/*************************************************************************** 
****************************************************************************/ 
 
void TCP_test(char *buf) 
{ 
   TCPSTREAM *stream ;   
   char *string = " " ; 
   long port = 143 ;   /* imapd */ 
   long retval ; 
    
   stream = tcp_open("isasun-1", port); 
   retval = tcp_soutr (stream, string); 
   string = tcp_getline (stream);  
   movmem(string,buf,strlen(string));   
   tcp_close(stream); 
} 
 
 
/*************************************************************************** 
****************************************************************************/ 
 
 
/* TCP/IP send string as record 
 * Accepts: TCP/IP stream 
 * Returns: T if success else NIL 
 */ 
 
long tcp_soutr (TCPSTREAM *stream,char *string) 
{ 
  int a ; 
  long i; 
  unsigned long size = strlen (string); 
  fd_set fds; 
     
  FD_ZERO (&fds);               /* initialize selection vector */ 
  if (stream->tcps == INVALID_SOCKET) return NIL; 
  FD_SET (stream->tcps,&fds);/* set bit in selection vector */ 
   
  while (size > 0) {            /* until request satisfied */ 
    if( (win_select (stream->tcps+1,0,&fds,0,0) < 0) || 
	((i = win_write (stream->tcps,string,size)) < 1) )   
    { 
	win_close (stream->tcps);   /* nuke the socket */ 
	stream->tcps = INVALID_SOCKET; 
	return NIL; 
    } 
    size -= i;                  /* count this size */ 
    string += i; 
  } 
  return T;                     /* all done */ 
} 
 
 
/* TCP/IP send string (Not NULL terminated). 
 * Accepts: TCP/IP stream 
 * Returns: T if success else NIL 
 */ 
 
long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size) 
{ 
  size_t i; 
  fd_set fds; 
  size_t len, MAXLEN = 8192;         /* send no more than this at a time */ 
 
  FD_ZERO (&fds);               /* initialize selection vector */ 
  if (stream->tcps == INVALID_SOCKET) return NIL; 
  FD_SET (stream->tcps,&fds);   /* set bit in selection vector */ 
  len = (size_t)min(size, MAXLEN); 
 
  while (size > 0) {            /* until request satisfied */ 
    if ((win_select (stream->tcps+1,0,&fds,0,0) < 0) || 
	((i = win_write (stream->tcps,string,len)) < 0)) { /* Send len at a time */ 
      win_close (stream->tcps);   /* nuke the socket */ 
      stream->tcps = INVALID_SOCKET; 
      return NIL; 
    } 
    size -= i;                  /* count this size */ 
    string += i; 
  } 
  /* Append a "\n" */ 
  if ((win_select (stream->tcps+1,0,&fds,0,0) < 0) || 
      ((i = win_write (stream->tcps,"\n",1)) < 0)) { 
    win_close (stream->tcps);   /* nuke the socket */ 
    stream->tcps = INVALID_SOCKET; 
    return NIL; 
  } 
  return T;                     /* all done */ 
} 
 
 
/* TCP/IP receive line 
 * Accepts: TCP/IP stream 
 * Returns: text line string or NIL if failure 
 */ 
 
char *tcp_getline (TCPSTREAM *stream) 
{ 
  int a; 
  long n, m; 
  char *st; 
  char *ret; 
  char *stp; 
  char tmp[2]; 
  fd_set fds; 
 
  FD_ZERO (&fds);               /* initialize selection vector */ 
 
  if (stream->tcps == INVALID_SOCKET) return NIL; 
 
  FD_SET (stream->tcps, &fds);   /* set bit in selection vector */ 
 
  while (stream->ictr < 1) {   /* if nothing in the buffer */ 
    /* block and read */ 
    if( (win_select (stream->tcps+1,&fds,0,0,0) < 0) || 
	((stream->ictr = win_read (stream->tcps,stream->ibuf,BUFLEN)) < 1)) 
    { 
	 win_close (stream->tcps);   /* nuke the socket */ 
	 stream->tcps = INVALID_SOCKET; 
	 return NIL; 
    } 
    stream->iptr = stream->ibuf;/* point at TCP buffer */ 
  } 
  st = stream->iptr;            /* save start of string */ 
  n = 0;                        /* init string count */ 
   
  while (stream->ictr--) {      /* look for end of line */ 
				/* saw the trailing CR? */ 
    if (stream->iptr++[0] == '\015') { 
      ret = (char *) fs_get (n+1); 
      memcpy (ret,st,n);        /* copy into a free storage string */ 
      ret[n] = '\0';            /* tie off string with null */ 
				/* eat the line feed */ 
      tcp_getbuffer (stream,(unsigned long) 1,tmp); 
      return ret;               /* return it to caller */ 
    } 
    ++n;                        /* else count and try next character */ 
  } 
  stp = (char *) fs_get (n);    /* copy first part of string */ 
  memcpy (stp,st,n); 
				/* recurse to get remainder */ 
  if (st = tcp_getline (stream)) { 
				/* build total string */ 
    ret = (char *) fs_get (n+1+(m = strlen (st))); 
    memcpy (ret,stp,n);         /* copy first part */ 
    memcpy (ret+n,st,m);        /* and second part */ 
    ret[n+m] = '\0';            /* tie off string with null */ 
    fs_give ((void **) &st);    /* flush partial string */ 
    fs_give ((void **) &stp);   /* flush initial fragment */ 
  } 
  else ret = stp;               /* return the fragment */ 
  return ret; 
} 
 
/* TCP/IP receive buffer 
 * Accepts: TCP/IP stream 
 *          size in bytes 
 *          buffer to read into 
 * Returns: T if success, NIL otherwise 
 */ 
 
long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer) 
{ 
  int a; 
  int retval ; 
  unsigned long n; 
  char *bufptr = buffer; 
  fd_set fds ; 
 
  FD_ZERO (&fds);               /* initialize selection vector */ 
  if (stream->tcps == INVALID_SOCKET) return NIL; 
  FD_SET (stream->tcps, &fds);   /* set bit in selection vector */ 
 
  while (size > 0) {            /* until request satisfied */ 
    while (stream->ictr < 1) {  /* if nothing in the buffer */ 
				/* block and read */ 
      if( (win_select(stream->tcps+1,&fds,0,0,0) < 0) ||  
	  ((stream->ictr = win_read(stream->tcps,stream->ibuf,BUFLEN)) < 1))  
      { 
	   win_close (stream->tcps); /* nuke the socket */ 
	   stream->tcps = INVALID_SOCKET; 
	   return NIL; 
      } 
				/* point at TCP buffer */ 
      stream->iptr = stream->ibuf; 
    }                           /* inner while */ 
 
    n = min (size,stream->ictr);/* number of bytes to transfer */ 
				/* do the copy */ 
    memcpy (bufptr,stream->iptr,n); 
    bufptr += n;                /* update pointer */ 
    stream->iptr +=n; 
    size -= n;                  /* update # of bytes to do */ 
    stream->ictr -=n; 
    bufptr[0] = '\0';             /* tie off string */ 
  }                             /* outer while */ 
  return T; 
} 
 
 
 
/* TCP/IP close 
 * Accepts: TCP/IP stream 
 */ 
 
void tcp_close (TCPSTREAM *stream) 
{ 
				/* nuke the socket */ 
  if (stream->tcps != INVALID_SOCKET) win_close (stream->tcps); 
  stream->tcps = INVALID_SOCKET; 
				/* flush host names */ 
  fs_give ((void **) &stream->host); 
  fs_give ((void **) &stream->localhost); 
  fs_give ((void **) &stream);  /* flush the stream */ 
} 
 
 
 
 
/* TCP/IP open 
 * Accepts: host name 
 *          contact port number 
 * Returns: TCP/IP stream if success else NIL 
 */ 
 
TCPSTREAM *tcp_open (char *host,long port) 
{ 
  TCPSTREAM *stream = NIL; 
  SOCKET sock; 
  unsigned long address; 
  unsigned short s_port; 
  char *s; 
  char tmp[MAILTMPLEN]; 
  char *hostname = cpystr (host); 
				/* set default gets routine */ 
//  if (!mailgets) mailgets = mm_gets 
  /* The domain literal form is used (rather than simply the dotted decimal 
     as with other Unix programs) because it has to be a valid "host name" 
     in mailsystem terminology. 
  */ 
  if (host[0] == '[' && host[(strlen (host))-1] == ']') { 
    strcpy (tmp,host+1);        /* yes, copy number part */ 
    tmp[strlen (tmp)-1] = '\0'; 
    if ((address = win_inet_addr (tmp)) == -1) { 
      sprintf (tmp,"Invalid post office: \"%s\" ",host); 
      ecs_error(tmp); 
      fs_give ((void **)&hostname); 
      return NIL; 
    } 
  } 
  else {                        /* lookup host name */ 
    if ((address = win_rhost (&hostname)) == 0) { 
      sprintf (tmp,"Post office not found: \"%s\" ",host); 
      ecs_error(tmp); 
      fs_give ((void **)&hostname); 
      return NIL; 
    } 
  } 
 
				/* copy port number in network format */ 
  if (!(s_port = win_htons (port))) 
      fatal ("Bad port argument to tcp_open"); 
				/* get a TCP stream */ 
 
  sock = win_socket(AF_INET, SOCK_STREAM, 0); 
  if (sock < 0) { 
    sprintf(tmp, "Cannot connect to post office: \"%s\" - Unable to create TCP socket", host); 
    ecs_error(tmp); 
    return NIL; 
  } 
 
  /* The local PC's hostname MUST be in the external "local_hostname", else 
   * return an error. 
   */ 
  if(local_hostname == NULL){ 
      ecs_error("Could not get the name or IP address of your PC"); 
      return NIL; 
  } 
				/* open connection */ 
  if ((errno = win_connect (sock, address, s_port)) > 10000) { 
    switch (errno) {            /* analyze error */ 
	case WSAENETUNREACH: s = "tcp_open failed"; break; 
	case WSAETIMEDOUT: s = "Timed out"; break; 
	default: s = "Unknown error"; break; 
    } 
    sprintf(tmp,"Connect fail to \"%s\" [%ld] at port %ld. %s\n",hostname,address,port,s); 
    ecs_error(tmp); 
    fs_give ((void **)&hostname); 
    win_close (sock); 
    return NIL; 
  } 
				/* create TCP/IP stream */ 
  stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM)); 
  stream->host = hostname;      /* official host name */ 
  stream->localhost = cpystr (local_hostname); 
  stream->tcps = sock;          /* init socket */ 
  stream->ictr = 0;             /* init input counter */ 
   
  return stream;                /* return success */ 
} 
 
/* TCP/IP authenticated open 
 * Accepts: host name 
 *          service name 
 * Returns: TCP/IP stream if success else NIL 
 */ 
 
TCPSTREAM *tcp_aopen (char *host,char *service) 
{ 
  return NIL;                   /* always NIL on DOS */ 
} 
 
char *tcp_host (TCPSTREAM *stream) 
{ 
  return stream->host;          /* return host name */ 
} 
 
 
/* TCP/IP get local host name 
 * Accepts: TCP/IP stream 
 * Returns: local host name 
 */ 
 
char *tcp_localhost (TCPSTREAM *stream) 
{ 
  return stream->localhost;     /* return local host name */ 
} 
 
/* These functions are only used by rfc822.c for calculating cookies.  So this 
 * is good enough.  If anything better is needed fancier functions will be 
 * needed. 
 */ 
 
 
/* Return host ID 
 */ 
 
#ifndef PCTCP 
unsigned long gethostid () 
{ 
  return (unsigned long) 0; 
} 
#endif 
 
 
/* Return `process ID' 
 */ 
 
long getpid () 
{ 
  return 1; 
} 
 
 
/* These two are used for pattern matching in misc.c, but are actually never 
 * called in DOS. 
 */ 
 
 
/* Dummy re_comp -- always return NIL */ 
 
char *re_comp (char *s) 
{ 
  return NIL; 
} 
 
 
/* Dummy re_exec -- always return T */ 
 
long re_exec (char *s) 
{ 
  return T; 
} 
 
 
 
/* Fill in the function pointers in the sockdll structure. The 
 * functions to be filled into the "sockdll" structure are: 
   - socket, 
   - connect, 
   - closesocket, 
   - select, 
   - recv, 
   - send, 
   - gethostbyname, 
   - net_addr, 
   - htonl, 
   - htons, 
   - ntohl, 
   - ntohs, 
**/ 
 
/* Looks for the file "winsock.dll", loads it and extracts the addresses. 
 * The returned instance of the library is stored in the static "hLibraray" 
 * so it can be free by "TCP_free_libs()" 
 */ 
int TCP_init_libs(char *global_dir) 
{ 
    int (PASCAL FAR *WSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData); 
    WSADATA *lpwsadata; 
    int retval; 
    WORD our_wsock_version = 257;   /* Version 1.1 of winsock */ 
 
    WSAStartup = NULL; 
    lpwsadata = NULL; 
 
    if((hLibrary = LoadLibrary("winsock.dll")) <= 32) 
	return(-1); 
 
    /* Do this for debuggindg */ 
    { 
	char *path = fs_get(256); 
	path[0] = '\0'; 
	/* Get library's path */ 
	GetModuleFileName(hLibrary, path, 255); 
	fs_give((void **)&path); 
    } 
 
    if((WSAStartup = (int  (FAR PASCAL *)())GetProcAddress(hLibrary, "WSAStartup")) == NULL) 
	return(-1); 
 
    /* Allocate */ 
    lpwsadata = fs_get(sizeof(WSADATA)); 
 
    /* Initialize the application */ 
    lpwsadata->wHighVersion = our_wsock_version;  /* In case */ 
    retval = (*WSAStartup)(lpwsadata->wHighVersion, lpwsadata); 
    if(retval != 0)  /* DLL hopefully filled this in!! */ 
	retval = (*WSAStartup)(lpwsadata->wHighVersion, lpwsadata); 
 
    if(retval != 0){    /* Still no success */ 
	char *path = fs_get(256); 
	char *mess = fs_get(256); 
	path[0] = '\0'; 
	mess[0] = '\0'; 
	/* Get library's path */ 
	if(GetModuleFileName(hLibrary, path, 255) == 0) 
	    path[0] == '\0'; 
 
	switch(retval){ 
	    case 0:  /* All's well */ 
	    break; 
	    case WSASYSNOTREADY: 
		sprintf(mess, "Error iniitalizing \"%s\": system not ready", 
			path); 
		ecs_error(mess); 
	    break; 
	    case WSAVERNOTSUPPORTED: 
	    case WSAEINVAL: 
		sprintf(mess, "\"%s\" does not support the winsock version \ 
required by ECS Mail", path); 
		ecs_error(mess); 
	    break; 
	} 
	fs_give((void **)&path); 
	fs_give((void **)&mess); 
	goto error; 
    } 
 
    /* Don't need lpwsadata anymore */ 
    fs_give((void **)&lpwsadata); 
    lpwsadata = NULL; 
 
    /* Ok. All's well */ 
 
    /* Allocate space */ 
    if(sockdll == NULL)  /* Should be */ 
	sockdll = (SOCKDLL *)fs_get(sizeof(SOCKDLL)); 
 
    /* so_rhost accomodates our B&W shim */ 
    sockdll->so_rhost = NULL;   /* Set this explicitly */ 
 
    /* Get addresses of routines */ 
    sockdll->so_rhost = (unsigned long  (FAR PASCAL *)()) 
		GetProcAddress(hLibrary, "so_rhost"); /* Could be NULL */ 
 
    if((sockdll->socket = (int  (FAR PASCAL *)()) 
		GetProcAddress(hLibrary, "socket")) == NULL) 
	goto error; 
    if((sockdll->connect = (int  (FAR PASCAL *)())GetProcAddress(hLibrary, "connect")) == NULL) 
	goto error; 
    if((sockdll->closesocket = (int  (FAR PASCAL *)())GetProcAddress(hLibrary, "closesocket")) == NULL) 
	goto error; 
    if((sockdll->select = (int  (FAR PASCAL *)())GetProcAddress(hLibrary, "select")) == NULL) 
	goto error; 
    if((sockdll->recv = (int  (FAR PASCAL *)())GetProcAddress(hLibrary, "recv")) == NULL) 
	goto error; 
    if((sockdll->send = (int (FAR PASCAL *)())GetProcAddress(hLibrary, "send")) == NULL) 
	goto error; 
    if((sockdll->gethostbyname = (struct hostent * (PASCAL FAR *)())GetProcAddress(hLibrary, "gethostbyname")) == NULL) 
	goto error; 
    if((sockdll->gethostname = (int (PASCAL FAR *)())GetProcAddress(hLibrary, "gethostname")) == NULL) 
	goto error; 
    if((sockdll->inet_addr = (unsigned long (FAR PASCAL *)())GetProcAddress(hLibrary, "inet_addr")) == NULL) 
	goto error; 
    if((sockdll->htonl = (unsigned long (FAR PASCAL *)())GetProcAddress(hLibrary, "htonl")) == NULL) 
	goto error; 
    if((sockdll->ntohl = (unsigned long (FAR PASCAL *)())GetProcAddress(hLibrary, "ntohl")) == NULL) 
	goto error; 
    if((sockdll->htons = (unsigned short (FAR PASCAL *)())GetProcAddress(hLibrary, "htons")) == NULL) 
	goto error; 
    if((sockdll->ntohs = (unsigned short (FAR PASCAL *)())GetProcAddress(hLibrary, "ntohs")) == NULL) 
	goto error; 
     
    return(0); 
 
error: 
	if(sockdll) 
	    fs_give((void **)&sockdll); 
	sockdll = NULL; 
	if(lpwsadata) 
	    fs_give((void **)&lpwsadata); 
	return(-1); 
} 
 
 
 
 
 
/* Free the socket library */ 
void TCP_free_libs(void) 
{ 
    int (PASCAL FAR *WSACleanup)(void); 
 
    WSACleanup = NULL; 
 
    if(hLibrary <= 0) 
	return; 
 
    /* Call WSACleanup now */ 
    if((WSACleanup = (int  (FAR PASCAL *)())GetProcAddress(hLibrary, "WSACleanup")) != NULL) 
	(*WSACleanup)(); 
 
    /* Free sockdll*/ 
    if(sockdll) 
	fs_give((void **)&sockdll); 
    sockdll = NULL; 
 
} 
 
 
 
 
 
/* These routines simply call the address of socket(), etc. */ 
SOCKET win_socket(int domain, int type, int protocol) 
{ 
    if(sockdll && sockdll->socket) 
	return((*sockdll->socket)(domain, type, protocol)); 
} 
 
 
/* NOTE:  s_port already in network order */ 
int win_connect(SOCKET s, unsigned long address, unsigned short s_port) 
{ 
    struct sockaddr_in sin; 
    sin.sin_family = AF_INET; 
    sin.sin_port = s_port; 
    sin.sin_addr.s_addr = address; 
    if(sockdll && sockdll->connect) 
	return((*sockdll->connect)(s, (struct sockaddr *)&sin, sizeof(sin))); 
    return(-1); 
} 
 
 
int win_close(SOCKET s) 
{ 
    if(sockdll && sockdll->closesocket) 
	return((*sockdll->closesocket)(s)); 
    return(-1); 
} 
 
 
/* timwout of 0 means non-blocking */ 
int win_select(int width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, long timeout) 
{ 
    struct timeval tval; 
    int result ; 
 
    tval.tv_sec = timeout; 
    if(tval.tv_sec < 2) 
	tval.tv_sec = 2; 
    tval.tv_usec = 0; 
 
    if(sockdll && sockdll->select) 
	result = (*sockdll->select)(width, readfds, writefds, exceptfds, &tval); 
    if( (result > WSABASEERR) || (result == 0) ) 
	return(-1); 
    return(result) ; 
} 
 
 
int win_read(SOCKET s, char *buf, int nbyte) 
{ 
    if(sockdll && sockdll->recv) 
	return((*sockdll->recv)(s, buf, nbyte, 0)); 
    return(-1); 
} 
 
int win_write(SOCKET s, char *buf, int nbyte) 
{ 
    if(sockdll && sockdll->send) 
	return((*sockdll->send)(s, buf, nbyte, 0)); 
    return(-1); 
} 
 
/* rhost - a short-cut for gethostbyname. 
 * Return 0 on error. 
 */ 
unsigned long win_rhost(char **name) 
{ 
    unsigned long addr; 
    struct hostent *h; 
    struct in_addr sin_addr; 
 
    if(!(name && *name)) 
	return(0L); 
 
    addr = 0L; 
 
    /* If a so_rhost() is provided by the winsock.dll, use it */ 
    if(sockdll && sockdll->so_rhost)  /* Use rhost */ 
	addr = (*sockdll->so_rhost)(name); 
 
    if(addr > 0L) 
	return(addr); 
 
    /* If so_rhost failed, try below */ 
 
    if(!(sockdll && sockdll->inet_addr && sockdll->gethostbyname)) 
	return(0L); 
 
    addr = 0L; 
    addr = (*sockdll->inet_addr)(*name); 
    if (addr == INADDR_NONE) 
    { 
	addr = 0L; 
	h = (*sockdll->gethostbyname)(*name); 
	if(h != NULL){ 
	    memcpy((char *)&sin_addr, h->h_addr, h->h_length); 
	    addr = sin_addr.s_addr; 
	} 
    } 
    return(addr); 
} 
 
unsigned long win_htonl(unsigned long hostlong) 
{ 
    if(sockdll && sockdll->htonl) 
	return((*sockdll->htonl)(hostlong)); 
    return(0L); 
} 
 
unsigned long win_ntohl(unsigned long netlong) 
{ 
    if(sockdll && sockdll->ntohl) 
	return((*sockdll->ntohl)(netlong)); 
    return(0L); 
} 
 
unsigned short win_htons(unsigned short hostshort) 
{ 
    if(sockdll && sockdll->htons) 
	return((*sockdll->htons)(hostshort)); 
    return(0); 
} 
 
unsigned short win_ntohs(unsigned short netshort) 
{ 
    if(sockdll && sockdll->ntohs) 
	return((*sockdll->ntohs)(netshort)); 
    return(0); 
} 
 
 
unsigned long win_inet_addr(char *cp) 
{ 
    if(sockdll && sockdll->inet_addr) 
	return((*sockdll->inet_addr)(cp)); 
    return(0L); 
} 
 
/** Get local host name or IP address. Use "gethostname". 
 * "buf" must be supplied, of length "buflen". 
 * These are simply passed to winsock's gethostname(). 
 * Returns 0 if found, -1 on error. 
 */ 
int ECS_get_local_hostname(char *buf, int buflen) 
{ 
    if(sockdll && sockdll->gethostname) 
	return((*sockdll->gethostname)(buf, buflen)); 
    return(-1); 
}