.ad 8
.bm 8
.fm 4
.bt $Copyright by   Software AG, 1993$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $NME$Project Distributed Database System$vos40c$
.tt 2 $$$
.tt 3 $R.Roedling$TCP/IP$1997-04-28$
***********************************************************
.nf


    ========== licence begin LGPL
    Copyright (C) 2002 SAP AG

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    ========== licence end

.fo
.nf
.sp
Module  : TCP/IP
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :

.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :

.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : R.Roedling
.sp
.cp 3
Created : 13.3.93
.sp
.cp 3
Version :
.sp
.cp 3
Release :  6.2 	 Date : 1997-04-28
.br
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:

.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:

.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:

.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
/*PRETTY*/

/*
 * INCLUDE FILES
 */
#ifndef NO_SOCKET
  #if defined(_WIN32)
    #include         <sys/types.h>
    #include         <winsock.h>
  #else
    #ifndef OS2
      #define OS2
    #endif
    #define          BSD_SELECT
    #include         <types.h>
    #include         <sys\socket.h>
    #include         <sys\select.h>
    #include         <netdb.h>
  #endif
#endif

/*
 *  DEFINES
 */
#define MOD__  "VOS40C : "
#define MF__   MOD__"UNDEFINED"

#ifndef NO_SOCKET
 #if defined(_WIN32)
  #define  TCPErrno                WSAGetLastError()
 #else
  #define  TCPErrno                sock_errno()
 #endif
#endif

#define OLD_TCPIP_CONNECT_REC_SIZE  300

/*
 *  MACROS
 */


/*
 *  LOCAL TYPE AND STRUCT DEFINITIONS
 */
#ifndef NO_SOCKET
 typedef struct hostent          hostent_type;
 typedef struct servent          servent_type;
 typedef struct sockaddr         sockaddr_type;
 typedef INT                     sockopt_type;
 typedef struct timeval          timeval_type;
 typedef struct linger           linger_type;
#endif

/*
 * EXTERNAL VARIABLES
 */


/*
 *  EXPORTED VARIABLES
 */


/*
 * LOCAL VARIABLES
 */
static CHAR cMajorSockVersion;
static CHAR cMinorSockVersion;

/*
 * LOCAL FUNCTION PROTOTYPES
 */


/*
 * ========================== GLOBAL FUNCTIONS ================================
 */

ULONG sql40c_get_dll_version ( PRTE_VERSION_ID pRTEVersion )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_get_dll_version"

  DBGPAS;

  pRTEVersion->ucMajorVersion = MAJOR_VERSION_NO;
  pRTEVersion->ucMinorVersion = MINOR_VERSION_NO;
  pRTEVersion->ucCorrLevel    = CORRECTION_LEVEL;
  pRTEVersion->ucPatchLevel   = PATCH_LEVEL;

  return(NO_ERROR);
  }

/*------------------------------*/

INT sql40c_send_conpkt ( INT                             sd,
                         PCHAR                           pConnectPacket,
                         INT2                            SendLen,
                         PINT                            pBytesSend )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_send_conpkt"

  DBGPAS;

  // --- This function is needed to be compatible to 3.12 and 6.11
  //     and should not longer be used by newer versions
  //
  return ( sql40c_send_packet ( sd, pConnectPacket, SendLen, pBytesSend ) );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_send_conpkt )
#endif

/*------------------------------*/

INT sql40c_recv_conpkt ( INT                             sd,
                         PCHAR                           pConnectPacket,
                         PINT                            pBytesReceived )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_recv_conpkt"

  DBGPAS;

  // --- This function is needed to be compatible to 3.12 and 6.11
  //     and should not longer be used by newer versions.
  //
  return ( sql40c_recv_packet ( sd, pConnectPacket, OLD_TCPIP_CONNECT_REC_SIZE, pBytesReceived ));
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_recv_conpkt )
#endif

/*------------------------------*/

INT sql40c_send_pkt ( INT                             sd,
                      PCHAR                           pPacket,
                      INT2                            SendLen,
                      PINT                            pBytesSend )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_send_pkt"

  DBGPAS;

  // --- This function is needed to be compatible to 3.12 and 6.11
  //     and should not longer be used by newer versions.
  //

  return ( sql40c_send_packet ( sd, pPacket, SendLen, pBytesSend ) );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_send_pkt )
#endif

/*------------------------------*/

INT sql40c_recv_pkt ( INT                             sd,
                      PCHAR                           pPacket,
                      INT2                            ReceiveLen,
                      PINT                            pBytesReceived )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_recv_pkt"

  DBGPAS;

  // --- This function is needed to be compatible to 3.12 and 6.11
  //     and should not longer be used by newer versions.
  //

  return ( sql40c_recv_packet ( sd, pPacket, ReceiveLen, pBytesReceived ) );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_recv_pkt )
#endif

/*------------------------------*/

#if defined(_WIN32)

INT sql40c_gethostname ( PSZ pszHostName, LONG lNameLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_gethostname"

  DBGPAS;

  // --- This function is needed to be compatible to 3.12 and 6.11
  //     and should not longer be used by newer versions.
  //
  if (!GetComputerName(pszHostName, &lNameLen))
    return (GetLastError());

  return (NO_ERROR);
  }

#endif


/*------------------------------*/

#ifdef NO_SOCKET

INT sql40c_sock_init ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_sock_init"

  DBGPAS;
  return ( -1 );
  }

/*------------------------------*/


INT sql40c_get_sock_version ( UCHAR *pcMajorSockVersion,
                              UCHAR *pcMinorSockVersion )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_get_sock_version"

  *pcMajorSockVersion = 0;
  *pcMinorSockVersion = 0;

  DBGPAS;
  return ( -1 );
  }

/*------------------------------*/


INT sql40c_sock_cleanup ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_sock_cleanup"

  DBGPAS;
  return ( -1 );
  }

/*------------------------------*/


INT sql40c_getservbyname ( PCHAR pszService, PUSHORT pusServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_getservbyname"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_gethostbyname ( PSZ      pszHostName,
                           PUCHAR   pucAddr,
                           PINT     pAddrLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_gethostbyname"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_gethostbyaddr ( PSZ      pszHostName,
                           PUCHAR   pucAddr,
                           LONG     lAddrLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_gethostbyaddr"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_stream_socket ( PINT psd )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_socket"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_socket_close ( INT sd )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_socket_close"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_accept_conn_request ( INT    sd,
                                 PINT   psdClient,
                                 PVOID  pSockAddr,
                                 PINT   pLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_accept"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_keep_alive ( INT sd )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_keep_alive"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_linger ( INT sd, BOOL fLinger, INT iSeconds )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_linger"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_bind ( INT sd, USHORT usServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_bind"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_listen ( INT sd, INT Count )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_listen"

  DBGPAS;

  return ( -1 );
  }


/*------------------------------*/

INT sql40c_set_send_buffer_size ( INT sd, PINT pMaxSize, INT MinSize )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_set_send_buffer_size"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_set_recv_buffer_size ( INT sd, PINT pMaxSize, INT MinSize )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_set_recv_buffer_size"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_connect( INT sd, USHORT usServicePort, PUCHAR pucName, INT NameLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_connect"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_send_packet ( INT                             sd,
                         PCHAR                           pPacket,
                         INT                             SendLen,
                         PINT                            pBytesSend )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_send_packet"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_recv_packet ( INT                             sd,
                         PCHAR                           pPacket,
                         INT                             ReceiveLen,
                         PINT                            pBytesReceived )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_recv_packet"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_select ( PINT                            pSDCount,
                    PVOID                           pReadSDMask,
                    PVOID                           pWriteSDMask,
                    PVOID                           pExceptSDMask,
                    USHORT                          usTimeOut )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_select"

  DBGPAS;

  return ( -1 );
  }

/*------------------------------*/

INT sql40c_get_serviceport ( INT sd, PUSHORT pusServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_get_serviceport"

  DBGPAS;

  return ( -1 );
  }


/*------------------------------*/

#else

/*------------------------------*/

INT sql40c_sock_init ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_sock_init"
  #if defined(_WIN32)
    static WSADATA WsaData;
    static INT     Err;
    static BOOL    AlreadyStarted;
    WORD           wVersionRequested;
  #endif

  DBGPAS;

  #if defined(_WIN32)
   if (AlreadyStarted)
     return (Err);
   AlreadyStarted = TRUE;

   wVersionRequested = MAKEWORD( 2, 0 );

   if (WSAStartup(wVersionRequested, &WsaData))
     return (Err = WSAGetLastError());

   #if defined (WINSOCK20)
    /* Confirm that the WinSock DLL supports 2.0.*/
    /* Note that if the DLL supports versions greater    */
    /* than 2.0 in addition to 2.0, it will still return */
    /* 2.0 in wVersion since that is the version we      */
    /* requested.                                        */

    if ( LOBYTE( WsaData.wVersion ) != 2 ||
         HIBYTE( WsaData.wVersion ) != 0 )
      {
      WSACleanup( );
      return (-1);
      }
   #endif

   cMajorSockVersion = LOBYTE( WsaData.wVersion );
   cMinorSockVersion = HIBYTE( WsaData.wVersion );

   return ( NO_ERROR );
  #else
   return ( sock_init() );
  #endif
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_sock_init )
#endif

/*------------------------------*/

INT sql40c_get_sock_version ( UCHAR *pcMajorSockVersion,
                              UCHAR *pcMinorSockVersion )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_get_sock_version"

  *pcMajorSockVersion = cMajorSockVersion;
  *pcMinorSockVersion = cMinorSockVersion;

  DBGPAS;
  return ( NO_ERROR );
  }
#ifdef STATIC_LINK
 #pragma handler ( sql40c_get_sock_version )
#endif


/*------------------------------*/

INT sql40c_sock_cleanup ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_sock_cleanup"

  DBGPAS;

  #if defined(_WIN32)
    WSACleanup();
  #endif

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_sock_cleanup )
#endif

/*------------------------------*/

INT sql40c_getservbyname ( PCHAR pszService, PUSHORT pusServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_getservbyname"
  servent_type   *sp;

  DBGPAS;

  sp = getservbyname ( pszService , SOCKET_PROTOCOL );

  if ( sp != NULL )
    {
    *pusServicePort = ntohs (sp->s_port);
    DBG3((MF__, "The '%s' service port is: %d", pszService, *pusServicePort));
    }
  else
    return ( -1 );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_getservbyname )
#endif

/*------------------------------*/

INT sql40c_gethostbyname ( PSZ      pszHostName,
                           PUCHAR   pucAddr,
                           PINT     pAddrLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_gethostbyname"
  hostent_type  *hp ;

  DBGPAS;

  hp = gethostbyname ( pszHostName );

  if ( hp != NULL )
    {
    if ( hp->h_length > *pAddrLen )
      return ( EINVAL );

    *pAddrLen = hp->h_length;
    memcpy ( pucAddr, (PUCHAR)hp->h_addr , hp->h_length );
    }
  else
    return ( -1 );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_gethostbyname )
#endif

/*------------------------------*/

INT sql40c_gethostbyaddr ( PSZ      pszHostName,
                           PUCHAR   pucAddr,
                           LONG     lAddrLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_gethostbyaddr"
  hostent_type  *hp ;
  PCHAR         pszHName;
  PCHAR         *ppszAlias;

  DBGPAS;

  hp = gethostbyaddr ( (PCHAR) pucAddr , INET_ADDR_SIZE , AF_INET );

  if ( hp != NULL )
    {
    pszHName = (PCHAR)hp->h_name;

    for ( ppszAlias = (PCHAR*)hp->h_aliases;
          ppszAlias && *ppszAlias;
          ppszAlias++ )
      {
      if ( strchr ( *ppszAlias, '.' ) )
        {
        pszHName = *ppszAlias;
        break;
        }
      }

    if ( (LONG) strlen (pszHName) > lAddrLen )
      return ( EINVAL );
    else
      strncpy ( pszHostName, pszHName, lAddrLen );
    }
  else
    return ( -1 );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_gethostbyaddr )
#endif

/*------------------------------*/

INT sql40c_stream_socket ( PINT psd )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_socket"
  #if defined ( NO_SOCKET_DELAY ) && defined (_WIN32)
   BOOL                    NoDelay = TRUE;
   INT                     rc;
  #endif

  DBGPAS;

  *psd = socket ( AF_INET, SOCK_STREAM, 0 );

  if ( *psd == INVALID_SOCKET )
    return ( TCPErrno );

  #if defined ( NO_SOCKET_DELAY ) && defined (_WIN32)
   rc = setsockopt ( *psd, IPPROTO_TCP, TCP_NODELAY, (PUCHAR)&NoDelay, sizeof(BOOL));

   if ( rc < 0 )
     return ( TCPErrno );

  #endif

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_stream_socket )
#endif

/*------------------------------*/

INT sql40c_socket_close ( INT sd )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_socket_close"

  DBGPAS;

  shutdown ( sd, 1 );

  #if defined(_WIN32)
    if ( closesocket( sd ) < 0 )
      return ( TCPErrno );
  #else
    if ( soclose( sd ) < 0 )
      return ( TCPErrno );
  #endif

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_socket_close )
#endif

/*------------------------------*/

INT sql40c_accept_conn_request ( INT    sd,
                                 PINT   psdClient,
                                 PVOID  pSockAddr,
                                 PINT   pLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_accept_conn_request"

  DBGPAS;

  *psdClient = accept ( sd, (sockaddr_type*)pSockAddr, pLen );

  if ( *psdClient == INVALID_SOCKET )
    {
    return ( TCPErrno );
    }

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_accept_conn_request )
#endif

/*------------------------------*/

INT sql40c_keep_alive ( INT sd )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_keep_alive"
  sockopt_type            KeepAlive = (sockopt_type) 1;
  INT                     rc;

  DBGPAS;

  rc = setsockopt ( sd, SOL_SOCKET, SO_KEEPALIVE, (PUCHAR)&KeepAlive, sizeof(sockopt_type));

  if ( rc < 0 )
    return ( TCPErrno );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_keep_alive )
#endif

/*------------------------------*/

INT sql40c_linger ( INT sd, BOOL fLinger, INT iSeconds )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_linger"
  INT                     rc;
  linger_type             Linger;

  DBGPAS;

  Linger.l_onoff  = fLinger;
  Linger.l_linger = iSeconds;

  if ( fLinger )
    rc = setsockopt ( sd, SOL_SOCKET, SO_LINGER, (PUCHAR)&Linger, sizeof(Linger));
  else
    rc = setsockopt ( sd, SOL_SOCKET, SO_DONTLINGER, (PUCHAR)&Linger, sizeof(Linger));

  if ( rc < 0 )
    return ( TCPErrno );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_linger )
#endif

/*------------------------------*/

INT sql40c_bind ( INT sd, USHORT usServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_bind"
  sockaddr_type                   SockAddr;
  INT                             rc;

  DBGPAS;

  // --- host address is implicit, so only address family and
  //     port number are to be determined
  memset ( &SockAddr, 0, sizeof(sockaddr_type) );

  SockAddr.sa_family = AF_INET;

  if ( usServicePort != 0 )
    {
    SockAddr.sa_data [ 0 ] = ( usServicePort >> 8 & 0xFF );   // - high byte
    SockAddr.sa_data [ 1 ] = ( usServicePort      & 0xFF );   // - low  byte
    }

  // --- bind the socket to the server address
  rc = bind ( sd, &SockAddr, sizeof(sockaddr_type) );

  if ( rc < 0 )
    return ( TCPErrno );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_bind )
#endif

/*------------------------------*/

INT sql40c_listen ( INT sd, INT Count )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_listen"
  INT                             rc;

  DBGPAS;

  rc = listen ( sd, Count );

  if ( rc < 0 )
    return ( TCPErrno );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_listen )
#endif

/*------------------------------*/

INT sql40c_set_send_buffer_size ( INT sd, PINT pMaxSize, INT MinSize )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_set_send_buffer_size"
  sockopt_type                    MaxSize  = *pMaxSize;
  sockopt_type                    CurrSize = 0;
  sockopt_type                    OptLen   = sizeof(CurrSize);
  INT                             rc,
                                  i;
  DBGPAS;

  #if defined (OS2)
   rc = getsockopt ( sd, SOL_SOCKET, SO_SNDBUF,
                     (CHAR*) &CurrSize, &OptLen );

   if ((rc >= 0) && ( CurrSize >= MaxSize ))
     return ( NO_ERROR );
  #endif

  for (; MaxSize > MinSize; )
    {
    rc = setsockopt ( sd, SOL_SOCKET, SO_SNDBUF,
                      (CHAR*) &MaxSize, sizeof(MaxSize) );

    if ( (rc >= 0) || ( (rc < 0) && ( TCPErrno != SOCENOBUFS ) ))
      break;


    for ( i = -2; MaxSize; i++ )
      MaxSize = MaxSize >> 1;

    MaxSize = 1 << i;
    }

  if ( rc < 0 )
    return ( TCPErrno );

  *pMaxSize = MaxSize;

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_set_send_buffer_size )
#endif

/*------------------------------*/

INT sql40c_set_recv_buffer_size ( INT sd, PINT pMaxSize, INT MinSize )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_set_recv_buffer_size"
  sockopt_type                    MaxSize  = *pMaxSize;
  sockopt_type                    CurrSize = 0;
  sockopt_type                    OptLen   = sizeof(CurrSize);
  INT                             rc,
                                  i;

  DBGPAS;

  #if defined (OS2)
   rc = getsockopt ( sd, SOL_SOCKET, SO_RCVBUF,
                     (CHAR*) &CurrSize, &OptLen );

   if ((rc >= 0) && ( CurrSize >= MaxSize ))
     return ( NO_ERROR );
  #endif

  for (; MaxSize > MinSize; )
    {
    rc = setsockopt ( sd, SOL_SOCKET, SO_RCVBUF,
                      (CHAR*) &MaxSize, sizeof(MaxSize) );

    if ( (rc >= 0) || ( (rc < 0) && ( TCPErrno != SOCENOBUFS ) ))
      break;

    for ( i = -2; MaxSize; i++ )
      MaxSize = MaxSize >> 1;

    MaxSize = 1 << i;
    }

  if ( rc < 0 )
    return ( TCPErrno );

  *pMaxSize = MaxSize;

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_set_recv_buffer_size )
#endif

/*------------------------------*/

INT sql40c_connect( INT sd, USHORT usServicePort, PUCHAR pucName, INT NameLen )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_connect"
  sockaddr_type                   SockAddr;
  INT                             rc;

  DBGPAS;

  if ( NameLen > sizeof ( SockAddr.sa_data ) - 2)
    return ( EINVAL );

  //
  // --- get socketaddress of server
  //
  memset ( &SockAddr, 0, sizeof(sockaddr_type) );

  SockAddr.sa_family = AF_INET;
  SockAddr.sa_data [ 0 ] = ( usServicePort >> 8 & 0xFF );   // - high byte
  SockAddr.sa_data [ 1 ] = ( usServicePort      & 0xFF );   // - low  byte

  memcpy ( &SockAddr.sa_data [ 2 ], pucName, NameLen );

  rc = connect ( sd, (sockaddr_type*)&SockAddr, sizeof(SockAddr) );

  if ( rc < 0 )
    return ( TCPErrno );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_connect )
#endif

/*------------------------------*/

INT sql40c_send_packet ( INT                             sd,
                         PCHAR                           pPacket,
                         INT                             SendLen,
                         PINT                            pBytesSend )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_send_packet"

  DBGPAS;

  //
  // --- Send packet.
  //
  *pBytesSend = send ( sd, (PCHAR) pPacket, SendLen, 0 );

  if ( *pBytesSend < 0 )
    return ( TCPErrno );

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_send_packet )
#endif

/*------------------------------*/

INT sql40c_recv_packet ( INT                             sd,
                         PCHAR                           pPacket,
                         INT                             ReceiveLen,
                         PINT                            pBytesReceived )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_recv_packet"

  DBGPAS;

  //
  // ---  Receive connect packet.
  //
  do
    {
    *pBytesReceived = recv ( sd, (PCHAR) pPacket,
                             ReceiveLen, 0 );
    }
  while ( TCPErrno == EINTR);

  if ( *pBytesReceived < 0 )
    {
    return ( TCPErrno );
    }

  return ( NO_ERROR );
  }


#ifdef STATIC_LINK
 #pragma handler ( sql40c_recv_packet )
#endif

/*------------------------------*/

INT sql40c_select ( PINT                            pSDCount,
                    PVOID                           pReadSDMask,
                    PVOID                           pWriteSDMask,
                    PVOID                           pExceptSDMask,
                    USHORT                          usTimeOut )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_select"
  timeval_type                   TimeOut;
  timeval_type                   *pTimeOut = NULL;

  DBGPAS;

  if ( usTimeOut != (USHORT)UNDEF )
    {
    TimeOut.tv_sec  = usTimeOut;
    TimeOut.tv_usec = 0;
    pTimeOut        = &TimeOut;
    }

  *pSDCount = select( *pSDCount,
                      (fd_set*)pReadSDMask,
                      (fd_set*)pWriteSDMask,
                      (fd_set*)pExceptSDMask,
                      pTimeOut );



  if ( *pSDCount < 0 )
    return ( TCPErrno );

  if ( *pSDCount == 0 )
    return ( ERROR_TIMEOUT );

  return ( NO_ERROR );
  }


#ifdef STATIC_LINK
 #pragma handler ( sql40c_select )
#endif

/*------------------------------*/

INT sql40c_get_serviceport ( INT sd, PUSHORT pusServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"sql40c_get_serviceport"
  sockaddr_type                   SockAddr;
  INT                             Len;
  INT                             rc;

  DBGPAS;

  // --- host address is implicit, so only address family and
  //     port number are to be determined
  memset ( &SockAddr, 0, sizeof(sockaddr_type) );
  SockAddr.sa_family = AF_INET;

  Len = sizeof(sockaddr_type);

  // --- bind the socket to the server address
  rc = getsockname ( sd, &SockAddr, &Len );

  if ( rc < 0 )
    return ( TCPErrno );

  *pusServicePort  = (USHORT)(SockAddr.sa_data [ 0 ] & 0xff) << 8;
  *pusServicePort |= (USHORT)(SockAddr.sa_data [ 1 ] & 0xff);

  return ( NO_ERROR );
  }

#ifdef STATIC_LINK
 #pragma handler ( sql40c_get_serviceport )
#endif

#endif

/*
 * ========================== LOCAL FUNCTIONS =================================
 */

/*
 * =============================== END ========================================
 */
.CM *-END-* code ----------------------------------------
.SP 2
***********************************************************
