/*!
  @file           veo40.c
  @author         JoergM
  @special area   TCP/IP routines via SAP NI ( network interface )
  @brief          description ...
  @see            example.html ...

\if EMIT_LICENCE

    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG

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

    This program 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 General Public License for more details.

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



\endif
*/

#if ! defined DUMMY_MODULE && ! defined STUB_MODULE
#define IMPLEMENTATION_MODULE
#endif

/*===========================================================================*/
#if defined IMPLEMENTATION_MODULE || defined STUB_MODULE
/*===========================================================================*/
/*--------------------------------------------------------------------*/
/* SAP includes                                                       */
/*--------------------------------------------------------------------*/
/*The following platforms already use the 6.20 Unicode NI libraries */
#if !defined (WIN32) || (defined (WIN32) && defined (AMD64))
#define SAPwithUNICODE 
#endif

#ifdef WIN32
  #define SAPonNT
#endif

#ifdef _IBMR2
  #define SAPonRS6000
#endif

#if PA11 || PA20W
  #define SAPonHPPA
#endif

#if defined (HP_IA64)
  #define SAPonHPPA
  #define SAPonHPIA64
#endif

#if defined(SVR4) && defined(SUN)
  #define SAPonSUN
#endif

#if defined(OSF1)
  #define SAPonALPHA
#endif

#if defined(LINUX)
#define SAPonLIN
#endif

#if defined SAPwithUNICODE
#if defined (LINUX) && (defined (X86_64) || (defined (IA64) && SLES_VER >= 9))
#include "sap/700/saptype.h"	/* nocheck */
#include "sap/700/saptypeb.h"	/* nocheck */
#include "sap/700/saptypec.h"	/* nocheck */
#include "sap/700/sapuc.h"		/* nocheck */
#include "sap/700/err.h"		/* nocheck */
#include "sap/700/nixx.h"		/* nocheck */
#include "sap/700/dptrace.h"	/* nocheck */
#include "sap/700/sapuc2.h"		/* nocheck */
#else
#include "sap/640/saptype.h"	/* nocheck */
#include "sap/640/saptypeb.h"	/* nocheck */
#include "sap/640/saptypec.h"	/* nocheck */
#include "sap/640/sapuc.h"		/* nocheck */
#include "sap/640/err.h"		/* nocheck */
#include "sap/640/nixx.h"		/* nocheck */
#include "sap/640/dptrace.h"	/* nocheck */
#include "sap/640/sapuc2.h"		/* nocheck */
#endif
#else /* Windows uses header from 46D (no unicode)! */
#include "sap/saptype.h"	/* nocheck */
#include "sap/saptypeb.h"	/* nocheck */
#include "sap/saptypec.h"	/* nocheck */
#include "sap/sapuc.h"		/* nocheck */
#include "sap/err.h"		/* nocheck */
#include "sap/nixx.h"		/* nocheck */
#include "sap/dptrace.h"	/* nocheck */
#endif
/*===========================================================================*/
#endif /* IMPLEMENTATION_MODULE || STUB_MODULE */
/*===========================================================================*/

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
/* externC is defined in SAP-Includes (sapuc.h) too   */
#undef externC
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#include "geo007_2.h"
#include "heo420.h"
#include "geo40.h"
#include "heo46.h"
#include "heo47.h"
#include "geo60.h"

#define MOD__ "veo40.c:"

/*===========================================================================*/
#ifdef IMPLEMENTATION_MODULE
/*===========================================================================*/
/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#ifdef NO_INLINES
# define _INLINE
#else
# define _INLINE	__inline
#endif

#ifdef DEBUG_RTE
#define DBGNI(_arg) {printf("%s", MOD__); printf _arg ; printf("\n");}
#else
#define DBGNI(_arg)
#endif

#define NI_DEFAULT_SERVICE 7269


#define MAX_LENGTH_OF_UNICODE_CHARACTER		4
#define MAX_PORT_LENGTH                     6
/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/



/*===========================================================================*
 *  LOCAL CLASSES, STRUCTURES, TYPES, UNIONS ...                             *
 *===========================================================================*/



/*===========================================================================*
 *  GLOBAL VARIABLES                                                         *
 *===========================================================================*/

extern FILE *tf ; /* SAP global trace/error file descriptor */


/*===========================================================================*
 *  LOCAL VARIABLES                                                          *
 *===========================================================================*/



/*===========================================================================*
 *  STATIC/INLINE FUNCTIONS (PROTOTYPES)                                     *
 *===========================================================================*/
static void
eo40NiBuildErrorString  ( tsp00_ErrTextc VAR_ARRAY_REF  pErrText,
                          char                         *ErrorMsgHeader,
                          SAPRETURN                     SapRc );

static void *
eo40NiDupHandle         ( void                         *NiHandle );


static void
eo40GetServiceAsString  ( unsigned short               *Service,
                          int                           szServiceLen,
#if defined SAPwithUNICODE
                          SAP_UC                       *szService);
#else
                          char                         *szService);
#endif

/*===========================================================================*
 *  PUBLIC FUNCTIONS (CODE)                                                  *
 *===========================================================================*/

#endif /* IMPLEMENTATION_MODULE */

#if defined IMPLEMENTATION_MODULE

/*===========================================================================*/

externC int
eo40NiIsAvailable()
{
  return(TRUE);
}

/*===========================================================================*/

#define CTRC_TRUNC      1

externC tsp00_Uint
eo40NiInit        ( tsp00_Pathc     VAR_ARRAY_REF  TraceFile,
                    int                            TraceLevel,
                    tsp00_ErrTextc  VAR_ARRAY_REF  ErrText )
{
  SAPRETURN             SapRc ;
  tsp00_Uint            ulCommState;
#if defined SAPwithUNICODE
  SAP_UC *				pTraceFileNameUC;
  SAP_UC				nullByte = {'\0'};

  pTraceFileNameUC = (SAP_UC *) alloca ((strlen (TraceFile) + 1) * MAX_LENGTH_OF_UNICODE_CHARACTER);
  A7sToUcs (pTraceFileNameUC, TraceFile);
  tf = (FILE *)CTrcInit (pTraceFileNameUC[0] != nullByte ? pTraceFileNameUC : NULL ,
                         CTRC_TRUNC, TraceLevel);
#else
  tf = (FILE *)CTrcInit (TraceFile[0] != '\0' ? (char *)TraceFile : NULL , 
						 CTRC_TRUNC, TraceLevel);

#endif

  SapRc = NiInit();

  if ( SapRc == SAP_O_K)
    ulCommState = commErrOk_esp01 ;
  else
  {
    ulCommState = commErrNotOk_esp01 ;
    eo40NiBuildErrorString ( ErrText, ERRMSG_NICOM_INIT_ERROR, SapRc );
  }
  return ( ulCommState ) ;
}

/*===========================================================================*/
#define ERRMSG_NICOM_GET_SD_ERROR "Can't get sd from NiHdl:"

externC tsp00_Uint
eo40NiHandleToSocket        ( void                         *NiHandle ,
                              int                          *Sd,
                              tsp00_ErrTextc  VAR_ARRAY_REF  ErrText )
{
  tsp00_Uint              ulCommState;
  SAPRETURN               SapRc ;

  SapRc = NiHdlToSock 	 (*(NI_HDL *)NiHandle, Sd ) ;

  if ( SapRc == SAP_O_K)
    ulCommState = commErrOk_esp01 ;
  else
  {
    ulCommState = commErrNotOk_esp01 ;
    eo40NiBuildErrorString ( ErrText, ERRMSG_NICOM_GET_SD_ERROR, SapRc );
    ErrTrace(tf);
  }

  return ( ulCommState );

}


/*===========================================================================*/

externC tsp00_Uint
eo40NiDataAvailable   ( void                         *NiHandle ,
                        tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  #undef  MF__
  #define MF__ MOD__"eo40NiDataAvailable"
  tsp00_Uint              ulCommState;
  SAPRETURN               SapRc ;

  SapRc = NiPeek ( *(NI_HDL *)NiHandle, 0 ) ;

  switch (SapRc)
  {
    case SAP_O_K    : ulCommState = commErrOk_esp01 ;        break ;
    case NIETIMEOUT : ulCommState = commErrWouldBlock_esp01; break ;
    default         : ulCommState = commErrNotOk_esp01;
                      eo40NiBuildErrorString ( pErrText,
                                               ERRMSG_NICOM_PEEK_ERROR, SapRc );
                      ErrTrace(tf);
                      break ;
  }
  return ( ulCommState );
}

/*===========================================================================*/

int eo40NiIsValidHandle      ( void                     *NiHandle )
{
  return ( NiHandle != NULL && *(NI_HDL *)NiHandle != NI_INVALID_HDL ) ;
}


/*===========================================================================*/

externC tsp00_Uint
eo40NiClose     ( void                         **NiHandle)
{
  tsp00_Uint              ulCommState = commErrOk_esp01;
  SAPRETURN               SapRc ;

  if ( eo40NiIsValidHandle ( *NiHandle) )
  {
    SapRc = NiCloseHandle (**(NI_HDL **)NiHandle) ;
    free ( *NiHandle ) ;
    *NiHandle = NULL ;
  }
  return ( ulCommState );
}

/*===========================================================================*/

externC tsp00_Uint
eo40NiFinish(tsp00_ErrTextc VAR_ARRAY_REF   pErrText)
{
  SAPRETURN               SapRc = NiExit() ;
  tsp00_Uint              ulCommState ;

  if ( SapRc  == SAP_O_K )
    ulCommState = commErrOk_esp01 ;
  else
  {
    ulCommState = commErrNotOk_esp01 ;
    eo40NiBuildErrorString ( pErrText, ERRMSG_NICOM_FINISH_ERROR, SapRc );
    ErrTrace(tf);
  }
  return ( commErrOk_esp01 );
}

/*===========================================================================*/

externC tsp00_Uint
eo40NiListen    ( void                        **NiHandle,
                  unsigned short               *Service,
                  tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  tsp00_Uint              CommState = commErrOk_esp01;
  SAPRETURN               SapRc ;
  NI_HDL                  ListenHandle ;
  SAPDB_Char			  szService[MAX_PORT_LENGTH * MAX_LENGTH_OF_UNICODE_CHARACTER];	/* Maximal 6 unicode character   */
																			            /* (we suppose that an charakter */
																			            /* needs maximal 4 bytes)        */
#if defined SAPwithUNICODE
  eo40GetServiceAsString (Service, MAX_PORT_LENGTH, (SAP_UC *)szService);
  SapRc = NiListen ((SAP_UC *)szService, &ListenHandle) ;
#else
  eo40GetServiceAsString (Service, MAX_PORT_LENGTH, szService);
  SapRc = NiListen (szService, &ListenHandle) ;
#endif

  if ( SapRc == SAP_O_K)
  {
    *NiHandle = eo40NiDupHandle( &ListenHandle ) ;
    CommState = *NiHandle ? commErrOk_esp01 : commErrNotOk_esp01 ;
  }
  else
  {
    eo40NiBuildErrorString ( pErrText, ERRMSG_NICOM_LISTEN_ERROR, SapRc );
    CommState = commErrNotOk_esp01 ;
    ErrTrace(tf);
  }
  return ( CommState );
}

/*===========================================================================*/

externC tsp00_Uint
eo40NiAccept    ( void                        *NiListenHandle,
                  void                       **NiCommHandle,
                  char                        *ServerNode,
                  int                          MaxServerNodeLen,
                  tsp00_ErrTextc VAR_ARRAY_REF ErrText )
{
  tsp00_Uint              CommState = commErrOk_esp01;
  SAPRETURN               SapRc ;
  NI_HOSTADR              hostaddr ;
  NI_HDL                  NiHandle ;

  SapRc = NiAccept (*(NI_HDL *)NiListenHandle, NI_BLOCK, &NiHandle, &hostaddr );

  if ( SapRc == SAP_O_K)
  {
#if defined SAPwithUNICODE
    SAP_UC *pHostNameUC = NiAddrToHost (&hostaddr);
	if ( pHostNameUC == NULL )
      pHostNameUC = NiAdrToStr (&hostaddr);

	if ( pHostNameUC != NULL )
#else
    char *pHostName = NiAddrToHost (&hostaddr) ;
    if ( pHostName == NULL )
        pHostName = NiAdrToStr (&hostaddr);

	if ( pHostName != NULL )
#endif
    {
#if defined SAPwithUNICODE
      SAP_A7	* pHostName;

	  pHostName = (SAP_A7 *) alloca (strlenU (pHostNameUC) + 1);
	  UcnToA7n(pHostName, pHostNameUC, strlenU (pHostNameUC));
#endif
      strncpy ( ServerNode, (SAPDB_Char *)pHostName, MaxServerNodeLen ) ;
      ServerNode [ MaxServerNodeLen -1 ] = '\0' ;
    }
    *NiCommHandle = eo40NiDupHandle( &NiHandle ) ;
    CommState = *NiCommHandle ? commErrOk_esp01 : commErrNotOk_esp01 ;
  }
  else
  {
    CommState = commErrNotOk_esp01 ;
    eo40NiBuildErrorString ( ErrText, ERRMSG_NICOM_ACCEPT_ERROR, SapRc );
    ErrTrace(tf);
  }

  return ( CommState );
}



/*===========================================================================*/

tsp00_Uint
eo40NiSend ( void                         *SendHandle,
             char                         *pData,
             int                           Len,
             tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  tsp00_Uint              CommState = commErrOk_esp01;
  SAPRETURN               SapRc ;
  NI_HDL                  NiHandle = *((NI_HDL *)SendHandle ) ;
  int                     BytesSend;

  for (BytesSend = 0;
       Len > 0 && CommState == commErrOk_esp01 ;
       pData += BytesSend, Len -= BytesSend )
  {
    SapRc = NiRawWrite (NiHandle, (SAP_BYTE *)pData, Len, NI_BLOCK, &BytesSend);
    if ( SapRc != SAP_O_K)
    {
      eo40NiBuildErrorString ( pErrText, ERRMSG_NICOM_SOCKET_SND_ERROR, SapRc );
      CommState = commErrNotOk_esp01 ;
      ErrTrace(tf);
    }
  }
  return ( CommState );
}

/*===========================================================================*/
tsp00_Uint
eo40NiReceive ( void                         *RecvHandle,
                char                         *pData,
                tsp00_Uint                    ulMaxDataLen,
                tsp00_Uint                   *BytesReceived,
                tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  #undef  MF__
  #define MF__ MOD__"eo40NiReceive"

  tsp00_Uint              CommState = commErrOk_esp01;
  SAPRETURN               SapRc ;
  SAP_INT                 readLen;
  NI_HDL                  NiHandle = *((NI_HDL *)RecvHandle ) ;

  SapRc = NiRawRead (NiHandle, (SAP_BYTE *)pData, ulMaxDataLen, NI_BLOCK, &readLen);

  DBGNI(( "header: wanted %d bytes, read %d, SapRc = %d",
           BytesRemaining, *BytesReceived, SapRc ));

  if ( SapRc != SAP_O_K )
  {
      eo40NiBuildErrorString ( pErrText, ERRMSG_NICOM_REC_ERROR, SapRc );
      CommState = commErrNotOk_esp01 ;
      ErrTrace(tf);
  }
  else
  {
     *BytesReceived = readLen;
  }

  return ( CommState );
}

/*===========================================================================*/
tsp00_Uint
eo40NiConnectToServer( teo40_NiConnectInfoRecord    *pNIConnInfo,
                       tsp00_ErrTextc VAR_ARRAY_REF  ErrText )
{
  SAPRETURN      SapRc ;
  tsp00_Uint     CommState;
  NI_HDL         NiHandle ;
  SAPDB_Char	 szService[MAX_PORT_LENGTH * MAX_LENGTH_OF_UNICODE_CHARACTER];  /* Maximal 6 unicode character   */
															                    /* (we suppose that an charakter */
															                    /* needs maximal 4 bytes)        */
#if defined SAPwithUNICODE
  SAP_UC *		 pSapRouterString;		


  eo40GetServiceAsString (&pNIConnInfo->usServicePort, MAX_PORT_LENGTH, (SAP_UC *)szService);

  pSapRouterString = (SAP_UC *) alloca ((strlen (pNIConnInfo->szSapRouterString) + 1) * MAX_LENGTH_OF_UNICODE_CHARACTER);
  A7sToUcs (pSapRouterString, pNIConnInfo->szSapRouterString);

  SapRc = NiRawConnect (pSapRouterString, (SAP_UC *)szService, NI_BLOCK, &NiHandle);
#else
  eo40GetServiceAsString ( &pNIConnInfo->usServicePort, MAX_PORT_LENGTH, szService);
  SapRc = NiRawConnect (pNIConnInfo->szSapRouterString, szService, 
                        NI_BLOCK, &NiHandle);
#endif

  if ( SapRc == SAP_O_K )
  {
    pNIConnInfo->NiHandle = eo40NiDupHandle( &NiHandle ) ;
    CommState = pNIConnInfo->NiHandle ? commErrOk_esp01 : commErrNotOk_esp01 ;
  }
  else
  {
    eo40NiBuildErrorString ( ErrText, ERRMSG_NICOM_CONNECT_ERROR, SapRc );
    CommState = commErrNotOk_esp01 ;
    ErrTrace(tf);
  }
  /* ?? socket options ?? */
  return ( CommState ) ;
}


/*===========================================================================*
 *  LOCAL/PRIVATE/PROTECTED FUNCTIONS (CODE)                                 *
 *===========================================================================*/

/*===========================================================================*/

#define ERR_NIEINTERN           "internal error"
#define ERR_NIEHOST_UNKNOWN     "unknown Host"
#define ERR_NIESERV_UNKNOWN     "unknown Service"
#define ERR_NIESERV_USED        "Service in use"
#define ERR_NIETIMEOUT          "timeout"
#define ERR_NIECONN_BROKEN      "connection broken"
#define ERR_NIECONN_REFUSED     "connection refused"

#define ERR_NIEINVAL            "invalid parameter"
#define ERR_NIEPING             "ping received"
#define ERR_NIECONN_PENDING     "NIECONN_PENDING"
#define ERR_NIEVERSION          "bad version"

#define ERR_NIEROUT_HOST_UNKNOWN "ROUT: unknown host"
#define ERR_NIEROUT_SERV_UNKNOWN "ROUT: unknown service"
#define ERR_NIEROUT_PERM_DENIED  "ROUT: perm. denied"
#define ERR_NIEROUT_CONN_REFUSED "ROUT: conn. refused"
#define ERR_NIEROUT_CONN_BROKEN  "ROUT: conn. broken"
#define ERR_NIEROUT_INTERN       "ROUT: intern. error"
#define ERR_NIEROUT_VERSION      "ROUT: bad version"
#define ERR_NIEROUT_CANCELED     "ROUT: comm. canceled"

#define ERR_NIEROUT_SHUTDOWN     "ROUT: shutdown"
#define ERR_NIEROUT_INFO_DENIED  "ROUT: info denied"
#define ERR_NIEROUT_OVERFLOW     "ROUT: client overflow"
#define ERR_NIEROUT_MODE_DENIED  "ROUT: talkmode forbidden"
#define ERR_NIEROUT_NOCLIENT     "ROUT: client missing"
#define ERR_NIEROUT_EXTERN       "ROUT: ext. lib error"
#define ERR_NIEROUT_SNC_FAILURE  "ROUT: SNC Error"

#define ERR_NI_UNKNOWN_RC        "NI: RC="
/*===========================================================================*/

static void
eo40NiBuildErrorString ( tsp00_ErrTextc VAR_ARRAY_REF ErrTextC,
                         char                        *ErrorMsgHeader,
                         SAPRETURN                    SapRc )
{
  char *NiErrorString ;
  char UnknownRC[sizeof(ERR_NI_UNKNOWN_RC) + 8];
  int  ErrorHeaderLen  = (int)strlen(ErrorMsgHeader) ;
  int  ErrorTrailerLen = sizeof(tsp00_ErrTextc) - ErrorHeaderLen - 1 ;

  switch ( SapRc )
  {
    case NIEHOST_UNKNOWN     : NiErrorString = ERR_NIEHOST_UNKNOWN     ; break ;
    case NIESERV_UNKNOWN     : NiErrorString = ERR_NIESERV_UNKNOWN     ; break ;
    case NIESERV_USED        : NiErrorString = ERR_NIESERV_USED        ; break ;
    case NIETIMEOUT          : NiErrorString = ERR_NIETIMEOUT          ; break ;
    case NIECONN_BROKEN      : NiErrorString = ERR_NIECONN_BROKEN      ; break ;
    case NIEINVAL            : NiErrorString = ERR_NIEINVAL            ; break ;
    case NIECONN_REFUSED     : NiErrorString = ERR_NIECONN_REFUSED     ; break ;
    case NIEPING             : NiErrorString = ERR_NIEPING             ; break ;
    case NIECONN_PENDING     : NiErrorString = ERR_NIECONN_PENDING     ; break ;
    case NIEVERSION          : NiErrorString = ERR_NIEVERSION          ; break ;
    case NIEINTERN           : NiErrorString = ERR_NIEINTERN           ; break ;

    case NIEROUT_HOST_UNKNOWN: NiErrorString = ERR_NIEROUT_HOST_UNKNOWN; break ;
    case NIEROUT_SERV_UNKNOWN: NiErrorString = ERR_NIEROUT_SERV_UNKNOWN; break ;
    case NIEROUT_PERM_DENIED : NiErrorString = ERR_NIEROUT_PERM_DENIED ; break ;
    case NIEROUT_CONN_REFUSED: NiErrorString = ERR_NIEROUT_CONN_REFUSED; break ;
    case NIEROUT_CONN_BROKEN : NiErrorString = ERR_NIEROUT_CONN_BROKEN ; break ;
    case NIEROUT_INTERN      : NiErrorString = ERR_NIEROUT_INTERN      ; break ;
    case NIEROUT_VERSION     : NiErrorString = ERR_NIEROUT_VERSION     ; break ;
    case NIEROUT_CANCELED    : NiErrorString = ERR_NIEROUT_CANCELED    ; break ;

    case NIEROUT_SHUTDOWN    : NiErrorString = ERR_NIEROUT_SHUTDOWN    ; break ;
    case NIEROUT_INFO_DENIED : NiErrorString = ERR_NIEROUT_INFO_DENIED ; break ;
    case NIEROUT_OVERFLOW    : NiErrorString = ERR_NIEROUT_OVERFLOW    ; break ;
    case NIEROUT_MODE_DENIED : NiErrorString = ERR_NIEROUT_MODE_DENIED ; break ;
    case NIEROUT_NOCLIENT    : NiErrorString = ERR_NIEROUT_NOCLIENT    ; break ;
    case NIEROUT_EXTERN      : NiErrorString = ERR_NIEROUT_EXTERN      ; break ;
    case NIEROUT_SNC_FAILURE : NiErrorString = ERR_NIEROUT_SNC_FAILURE ; break ;

    default                  : strcpy(UnknownRC, ERR_NI_UNKNOWN_RC) ;
                               sql47_itoa(SapRc, UnknownRC  + sizeof(ERR_NI_UNKNOWN_RC),
                                          sizeof(UnknownRC) - sizeof(ERR_NI_UNKNOWN_RC) ) ;
                               NiErrorString = UnknownRC               ; break ;
  }

  strcpy( ErrTextC, ErrorMsgHeader ) ;

  if ( ErrorTrailerLen > 0 )
  {
    ErrTextC [ ErrorHeaderLen ] = ':';
    strncpy( &ErrTextC [ ErrorHeaderLen + 1] , NiErrorString, ErrorTrailerLen ) ;
  }

}

/*===========================================================================*/

static void *
eo40NiDupHandle ( void *NiHandle )
{
  void *NiDupHandle = malloc ( sizeof(NI_HDL) ) ;

  if ( NiDupHandle )
    memcpy( NiDupHandle, NiHandle, sizeof(NI_HDL) ) ;

  return ( NiDupHandle ) ;
}

/*===========================================================================*/
static void
eo40GetServiceAsString ( unsigned short *Service,
                         int             szServiceLen,
#if defined SAPwithUNICODE
                         SAP_UC         *szService)
#else
                         char           *szService)
#endif
{
  unsigned short NiServiceNo ;
  SAPDB_Char *   szServiceAsChar;

  szServiceAsChar = (SAPDB_Char *)alloca (szServiceLen);

  if ( !Service || *Service == 0 )
  {
    NiServiceNo = NI_DEFAULT_SERVICE ;
    if (Service)
      *Service = NiServiceNo; /* give used ServiceNo back */
  }
  else
    NiServiceNo = *Service ;

  sql47_itoa( ( int )NiServiceNo, szServiceAsChar, szServiceLen);

#if defined SAPwithUNICODE
  A7sToUcs (szService, szServiceAsChar);
#else
  strcpy (szService, szServiceAsChar);
#endif
}

/*===========================================================================*/

#if defined(LINUX)
/* On LINUX the dladdr() is contained in libdl which is normally not used during link step. */
/* Since dladdr() is only needed in Stack back trace routine of R/3 which is never called here */
/* there is no reason to have a usefull implementation for it. So we put a dummy here, that satisfies the linker */
/* Structure containing information about object searched using `dladdr'.  */

/* copied from /usr/include/dlfcn.h ... */
typedef struct
{
  const char *dli_fname;      /* File name of defining object.  */
  void *dli_fbase;              /* Load address of that object.  */
  const char *dli_sname;      /* Name of nearest symbol.  */
  void *dli_saddr;              /* Exact value of nearest symbol.  */
} Dl_info;

/* Fill in *INFO with the following information about ADDRESS.
   Returns 0 iff no shared object's segments contain that address.  */
int dladdr (const void *__address, Dl_info *__info)
{
    return 0;
}
#endif /* LINUX */

/*===========================================================================*/

#endif /* IMPLEMENTATION_MODULE */

#ifdef DUMMY_MODULE

/*===========================================================================*/

externC int
eo40NiIsAvailable()
{
  return( 0 );
}

externC tsp00_Uint
eo40NiInit        ( tsp00_Pathc     VAR_ARRAY_REF  TraceFile,
                    int                            TraceLevel,
                    tsp00_ErrTextc  VAR_ARRAY_REF  ErrText )
{
  return ( commErrNotOk_esp01 );
}

externC tsp00_Uint
eo40NiHandleToSocket        ( void                         *NiHandle ,
                              int                          *Sd,
                              tsp00_ErrTextc  VAR_ARRAY_REF  ErrText )
{
  return ( commErrNotOk_esp01 );
}

externC tsp00_Uint
eo40NiDataAvailable   ( void                         *NiHandle ,
                        tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  return ( commErrNotOk_esp01 );
}

externC tsp00_Uint
eo40NiSqlCancelDump       ( teo40_NiConnectInfoRecord    *pNIConnInfo,
                            tsp00_Uint                    ulReqType,
                            tsp00_ErrTextc VAR_ARRAY_REF  ErrText )
{
  return ( commErrNotOk_esp01 );
}


externC int
eo40NiExtractDBNodeFromSaprouterSring ( char                         *SaprouterString,
                                        tsp00_NodeIdc  VAR_ARRAY_REF  ServerNode  )
{
  return ( commErrNotOk_esp01 );
}

externC int
eo40NiExtractServiceFromSaprouterSring ( char                        *SaprouterString,
                                         unsigned short              *Service )
{
  *Service = 0 ;
  return ( commErrNotOk_esp01 );
}

externC int
eo40NiIsSaprouterSring   (  char                  *StrToCheck )
{
  return ( 0);
}

externC int
eo40NiIsValidHandle      ( void                   *NiHandle )
{
  return ( 0 );
}

externC tsp00_Uint
eo40NiClose     ( void                         **NiHandle)
{
  return ( commErrNotOk_esp01 );
}

externC tsp00_Uint
eo40NiFinish(tsp00_ErrTextc VAR_ARRAY_REF   pErrText)
{
  return ( commErrNotOk_esp01 );
}

externC tsp00_Uint
eo40NiListen    ( void                         **NiHandle,
                  unsigned short                *Service,
                  tsp00_ErrTextc VAR_ARRAY_REF   pErrText )
{
  return ( commErrNotOk_esp01 );
}

externC tsp00_Uint
eo40NiAccept    ( void                          *NiListenHandle,
                  void                         **NiCommHandle,
                  char                          *ServerNode,
                  int                            MaxServerNodeLen,
                  tsp00_ErrTextc VAR_ARRAY_REF   pErrText )
{
  return ( commErrNotOk_esp01 );
}

externC tsp00_Uint
eo40NiSend              ( void                         *SendHandle,
                          char                         *pData,
                          int                           Len,
                          tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  return ( commErrNotOk_esp01 );
}

tsp00_Uint
eo40NiReceive ( void                         *RecvHandle,
                char                         *pData,
                tsp00_Uint                    ulMaxDataLen,
                tsp00_Uint                   *BytesReceived,
                tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  return ( commErrNotOk_esp01 );
}

tsp00_Uint
eo40NiConnectToServer   ( teo40_NiConnectInfoRecord    *pNIConnInfo,
                          tsp00_ErrTextc VAR_ARRAY_REF  ErrText )
{
  return ( commErrNotOk_esp01 );
}

/*===========================================================================*/
#endif /* DUMMY_MODULE */

#ifdef STUB_MODULE
/*===========================================================================*/

/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#include <string.h>

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#define SAPNI_FILENAME "sapni.dll"

/*===========================================================================*
 *  GLOBAL VARIABLES                                                         *
 *===========================================================================*/


/*===========================================================================*
 *  LOCAL VARIABLES                                                          *
 *===========================================================================*/

static HANDLE hSAPNI = 0;

#if 0
typedef int (*eo40NiIsSaprouterSring_t) ( char * );
static eo40NiIsSaprouterSring_t fpeo40NiIsSaprouterSring;

typedef int (*eo40NiExtractDBNodeFromSaprouterSring_t) ( char *, tsp00_NodeIdc VAR_ARRAY_REF );
static eo40NiExtractDBNodeFromSaprouterSring_t fpeo40NiExtractDBNodeFromSaprouterSring;

typedef int (*eo40NiExtractServiceFromSaprouterSring_t) ( char *, unsigned short * );
static eo40NiExtractServiceFromSaprouterSring_t fpeo40NiExtractServiceFromSaprouterSring;
#endif

typedef int (*eo40NiIsAvailable_t)();;
static eo40NiIsAvailable_t fpeo40NiIsAvailable = 0;

typedef tsp00_Uint (*eo40NiInit_t)( tsp00_Pathc VAR_ARRAY_REF, int, tsp00_ErrTextc VAR_ARRAY_REF );
static eo40NiInit_t fpeo40NiInit = 0;

typedef tsp00_Uint (*eo40NiHandleToSocket_t) ( void *, int *, tsp00_ErrTextc VAR_ARRAY_REF );
static  eo40NiHandleToSocket_t fpeo40NiHandleToSocket = 0;

typedef tsp00_Uint (*eo40NiDataAvailable_t) ( void *, tsp00_ErrTextc VAR_ARRAY_REF );
static eo40NiDataAvailable_t fpeo40NiDataAvailable = 0;

typedef int (*eo40NiIsValidHandle_t) ( void * );
static eo40NiIsValidHandle_t fpeo40NiIsValidHandle;

typedef tsp00_Uint (*eo40NiClose_t) ( void ** );
static eo40NiClose_t fpeo40NiClose;

typedef tsp00_Uint (*eo40NiFinish_t) (tsp00_ErrTextc VAR_ARRAY_REF);
static eo40NiFinish_t fpeo40NiFinish;

typedef tsp00_Uint (*eo40NiListen_t) ( void **, unsigned short *, tsp00_ErrTextc VAR_ARRAY_REF );
static eo40NiListen_t fpeo40NiListen;

typedef tsp00_Uint (*eo40NiAccept_t) ( void *, void **, char *, int, tsp00_ErrTextc VAR_ARRAY_REF );
static eo40NiAccept_t fpeo40NiAccept;

typedef tsp00_Uint (*eo40NiSend_t) ( void *, char *, int, tsp00_ErrTextc VAR_ARRAY_REF );
static eo40NiSend_t fpeo40NiSend;

typedef tsp00_Uint (*eo40NiReceive_t) ( void *, char *, tsp00_Uint, tsp00_Uint *, tsp00_ErrTextc VAR_ARRAY_REF );
static eo40NiReceive_t fpeo40NiReceive;

typedef tsp00_Uint (*eo40NiConnectToServer_t) ( teo40_NiConnectInfoRecord *, tsp00_ErrTextc VAR_ARRAY_REF );
static eo40NiConnectToServer_t fpeo40NiConnectToServer;


/*===========================================================================*
 *  STATIC/INLINE FUNCTIONS (PROTOTYPES)                                     *
 *===========================================================================*/

static HANDLE
eo40NiLoadLib ()
{
  tsp00_Pathc      szDllPath;
  DWORD            dwLen;
  int              bLoadSymbols;

  bLoadSymbols = ( hSAPNI == 0 ) ? 1 : 0;

  /* first try path of executable */
  if ( hSAPNI == 0 )
  {
    dwLen = GetModuleFileName( 0, szDllPath, sizeof( szDllPath ) - 1 );
    if (dwLen >= 0) {
	  char *Ptr;

	  Ptr = strrchr ((char *) szDllPath, '\\');
	  if (Ptr != 0) {
        Ptr++;
		*Ptr = '\0';
		strcat( szDllPath, SAPNI_FILENAME );

		hSAPNI = LoadLibraryEx ( szDllPath, 0, 0 );
      }
    }
  }

  /* now try sapdb program path */
  if ( hSAPNI == 0 )
  {
    tsp01_RteError          RteError ;

    if ( sqlGetIndependentPgmPath ( szDllPath, TERM_WITH_DELIMITER_EO01, &RteError ) )
    {
      strcat( szDllPath, SAPNI_FILENAME );

      hSAPNI = LoadLibraryEx ( szDllPath, 0, 0 );
    }
  }

  if ( hSAPNI == 0 )
    return 0;

  if ( bLoadSymbols == 0 )
    return ( hSAPNI );

#if 0
  fpeo40NiIsSaprouterSring = (eo40NiIsSaprouterSring_t) GetProcAddress (hSAPNI, TEXT ("eo40NiIsSaprouterSring"));
  if ( fpeo40NiIsSaprouterSring == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiExtractDBNodeFromSaprouterSring = (eo40NiExtractDBNodeFromSaprouterSring_t) GetProcAddress (hSAPNI, TEXT ("eo40NiExtractDBNodeFromSaprouterSring"));
  if ( fpeo40NiExtractDBNodeFromSaprouterSring == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiExtractServiceFromSaprouterSring = (eo40NiExtractServiceFromSaprouterSring_t) GetProcAddress (hSAPNI, TEXT ("eo40NiExtractServiceFromSaprouterSring"));
  if ( fpeo40NiExtractServiceFromSaprouterSring == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }
#endif

  fpeo40NiIsAvailable = (eo40NiIsAvailable_t) GetProcAddress (hSAPNI, TEXT ("eo40NiIsAvailable"));
  if ( fpeo40NiIsAvailable == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiInit = (eo40NiInit_t) GetProcAddress (hSAPNI, TEXT ("eo40NiInit"));
  if ( fpeo40NiInit == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiHandleToSocket = (eo40NiHandleToSocket_t) GetProcAddress (hSAPNI, TEXT ("eo40NiHandleToSocket"));
  if ( fpeo40NiHandleToSocket == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiDataAvailable = (eo40NiDataAvailable_t) GetProcAddress (hSAPNI, TEXT ("eo40NiDataAvailable"));
  if ( fpeo40NiDataAvailable == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiIsValidHandle = (eo40NiIsValidHandle_t) GetProcAddress (hSAPNI, TEXT ("eo40NiIsValidHandle"));
  if ( fpeo40NiIsValidHandle == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiClose = (eo40NiClose_t) GetProcAddress (hSAPNI, TEXT ("eo40NiClose"));
  if ( fpeo40NiClose == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiFinish = (eo40NiFinish_t) GetProcAddress (hSAPNI, TEXT ("eo40NiFinish"));
  if ( fpeo40NiFinish == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiListen = (eo40NiListen_t) GetProcAddress (hSAPNI, TEXT ("eo40NiListen"));
  if ( fpeo40NiListen == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiAccept = ( eo40NiAccept_t ) GetProcAddress (hSAPNI, TEXT ("eo40NiAccept"));
  if (fpeo40NiAccept == 0) {
    FreeLibrary (hSAPNI);
	return 0;
  }

  fpeo40NiSend = ( eo40NiSend_t ) GetProcAddress (hSAPNI, TEXT ("eo40NiSend"));
  if ( fpeo40NiSend == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiReceive = ( eo40NiReceive_t ) GetProcAddress (hSAPNI, TEXT ("eo40NiReceive"));
  if ( fpeo40NiReceive == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  fpeo40NiConnectToServer = (eo40NiConnectToServer_t) GetProcAddress (hSAPNI, TEXT ("eo40NiConnectToServer"));
  if ( fpeo40NiConnectToServer == 0 ) {
    FreeLibrary ( hSAPNI );
	return 0;
  }

  return ( hSAPNI );
}

/*===========================================================================*
 *  PUBLIC FUNCTIONS (CODE)                                                  *
 *===========================================================================*/
#if 0
externC int
eo40NiIsSaprouterSring   (  char                  *StrToCheck )
{
  return ( fpeo40NiIsSaprouterSring ( StrToCheck ) );
}

externC int
eo40NiExtractDBNodeFromSaprouterSring ( char                         *SaprouterString,
                                        tsp00_NodeIdc  VAR_ARRAY_REF  ServerNode  )
{
  return ( fpeo40NiExtractDBNodeFromSaprouterSring ( SaprouterString, ServerNode ) );
}

externC int
eo40NiExtractServiceFromSaprouterSring ( char                        *SaprouterString,
                                         unsigned short              *Service )
{
  return ( fpeo40NiExtractServiceFromSaprouterSring ( SaprouterString, Service ) );
}
#endif

externC int
eo40NiIsAvailable()
{
  HANDLE hLib;

  hLib = eo40NiLoadLib ();
  if (hLib == 0)
    return 0;

  return( fpeo40NiIsAvailable () );
}

externC tsp00_Uint
eo40NiInit        ( tsp00_Pathc     VAR_ARRAY_REF  TraceFile,
                    int                            TraceLevel,
                    tsp00_ErrTextc  VAR_ARRAY_REF  ErrText )
{
  HANDLE hLib;

  hLib = eo40NiLoadLib ();
  if (hLib == 0) {
    strcpy ( ErrText, "cannot load sapni.dll" );
    return ( commErrNotOk_esp01 );
  }

  return ( fpeo40NiInit ( TraceFile, TraceLevel, ErrText ) );
}

externC tsp00_Uint
eo40NiHandleToSocket        ( void                         *NiHandle ,
                              int                          *Sd,
                              tsp00_ErrTextc  VAR_ARRAY_REF  ErrText )
{
  return ( fpeo40NiHandleToSocket ( NiHandle, Sd, ErrText ));
}

externC tsp00_Uint
eo40NiDataAvailable   ( void                         *NiHandle ,
                        tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  return ( fpeo40NiDataAvailable ( NiHandle, pErrText ) );
}

externC int
eo40NiIsValidHandle      ( void                   *NiHandle )
{
  return ( fpeo40NiIsValidHandle ( NiHandle ) );
}

externC tsp00_Uint
eo40NiClose     ( void                         **NiHandle)
{
  return ( fpeo40NiClose (NiHandle) );
}

externC tsp00_Uint
eo40NiFinish(tsp00_ErrTextc VAR_ARRAY_REF   pErrText)
{
  return ( fpeo40NiFinish ( pErrText ) );
}

externC tsp00_Uint
eo40NiListen    ( void                         **NiHandle,
                  unsigned short                *Service,
                  tsp00_ErrTextc VAR_ARRAY_REF   pErrText )
{
  return ( fpeo40NiListen ( NiHandle, Service, pErrText ) );
}

externC tsp00_Uint
eo40NiAccept    ( void                          *NiListenHandle,
                  void                         **NiCommHandle,
                  char                          *ServerNode,
                  int                            MaxServerNodeLen,
                  tsp00_ErrTextc VAR_ARRAY_REF   pErrText )
{
  return ( fpeo40NiAccept ( NiListenHandle, NiCommHandle, ServerNode, MaxServerNodeLen, pErrText ) );
}

externC tsp00_Uint
eo40NiSend              ( void                         *SendHandle,
                          char                         *pData,
                          int                           Len,
                          tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  return ( fpeo40NiSend ( SendHandle, pData, Len, pErrText ) );
}

externC tsp00_Uint
eo40NiReceive ( void                         *RecvHandle,
                char                         *pData,
                tsp00_Uint                    ulMaxDataLen,
                tsp00_Uint                   *BytesReceived,
                tsp00_ErrTextc VAR_ARRAY_REF  pErrText )
{
  return ( fpeo40NiReceive ( RecvHandle, pData, ulMaxDataLen,  BytesReceived, pErrText) );
}

externC tsp00_Uint
eo40NiConnectToServer   ( teo40_NiConnectInfoRecord    *pNIConnInfo,
                          tsp00_ErrTextc VAR_ARRAY_REF  ErrText )
{
  return ( fpeo40NiConnectToServer ( pNIConnInfo, ErrText ) );
}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
#endif /* STUB_MODULE */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/
