/* static char sccsid[] = "@(#)srfcserv       20.27.1.1     SAP     96/06/26 "; */

/*====================================================================*/
/*                                                                    */
/*     PROGRAM     :   srfcserv.c (running on Windows, Windows_NT,    */
/*                                 Windows_95, OS/2 and R/3-Platforms)*/
/*                                                                    */
/*                                                                    */
/*     DESCRIPTION :   Server-Program for RFC Test                    */
/*                                                                    */
/*                     Following functions are available:             */
/*                                                                    */
/*                       - STFC_CONNECTION                            */
/*                                                                    */
/*                       - STFC_PERFORMANCE                           */
/*                                                                    */
/*                     and can be called from R/2 or R/3              */
/*                                                                    */
/*                                                                    */
/*     SAP AG Walldorf                                                */
/*     Systeme, Anwendungen und Produkte in der Datenverarbeitung     */
/*                                                                    */
/*     Copyright (C) SAP AG 1994                                      */
/*                                                                    */
/*====================================================================*/

/*--------------------------------------------------------------------*/
/* Set up includes                                                    */
/*--------------------------------------------------------------------*/

#include "srfcserv.h"


/*====================================================================*/
/*  Function:  main                                                   */
/*                                                                    */
/*    Accept RFC-Connection                                           */
/*    Install all offering functions                                  */
/*    Loop in waiting for Remote Function Call                        */
/*      do function                                                   */
/*    until client disconnects the RFC-Connection                     */
/*                                                                    */
/*====================================================================*/

main(int argc, char **argv)
{
  setbuf(stderr, NULL);

  if (argc == 1)
  {
    help();
    return 0;
  }

  /*------------------------------------------------------------------*/
  /* Output argument list                                             */
  /*------------------------------------------------------------------*/

  fprintf(stderr, "\nargc    = %d", argc);
  for (i=0; i<argc; i++)
    fprintf(stderr, "\nargv[%d] = '%s'", i, argv[i]);

  /*------------------------------------------------------------------*/
  /* Accept RFC-Connection                                            */
  /*------------------------------------------------------------------*/

  fprintf(stderr, "\n<==  RfcAccept                rfc_handle = ");
  rfc_handle = RfcAccept(argv);
  fprintf(stderr, "%d", rfc_handle);

  if (rfc_handle == RFC_HANDLE_NULL)
    rfc_error("RfcAccept");

  /*------------------------------------------------------------------*/
  /* Install offering functions                                       */
  /*------------------------------------------------------------------*/

  rfc_rc = install();
  if( rfc_rc != RFC_OK )
    return 1;

#ifdef SAP_RFC_GETNAME

  /*------------------------------------------------------------------*/
  /* Get function name directly and and start it                      */
  /*------------------------------------------------------------------*/

  for (;;)
  {
    fprintf(stderr, "\n\nWait for next RFC call with RfcGetName");

    fprintf(stderr, "\n<==  RfcGetName               rfc_rc = ");
    rfc_rc = RfcGetName(rfc_handle, function_name);
    fprintf(stderr, "%d", rfc_rc);

    if (rfc_rc == RFC_OK)
    {
      fprintf(stderr, "   Function Name: '%s'", function_name);
      if ((strcmp(function_name, name_connection_test)) &&
          (strcmp(function_name, name_performance_test)))
      {
        sprintf(abort_text,
          "RFC function %s is not implemented in this server program",
          function_name);
        function_abort(abort_text);
      }
      else
      {
        if (strcmp(function_name, name_connection_test) == 0)
          rfc_rc = connection_test(rfc_handle);
        else
          rfc_rc = performance_test(rfc_handle);

        if (rfc_rc != RFC_OK)
          break;
      }
    }
    else
    {
      rfc_error("RfcGetName");
      break;
    }
  }

#else

  /*------------------------------------------------------------------*/
  /* Wait for RFC call                                                */
  /*------------------------------------------------------------------*/

  do
  {
    fprintf(stderr, "\n\nWait for next RFC call with or without RfcListen/RfcWaitForRequest");

#if defined(SAP_RFC_WAIT) || defined(SAP_RFC_LISTEN)
    for (rfc_rc = RFC_RETRY; rfc_rc == RFC_RETRY;)
    {
#ifdef SAP_RFC_WAIT
      RFC_INT wtime = 60;     /* 60 sec. */
      fprintf(stderr, "\n<==  RfcWaitForRequest        rfc_rc = ");
      rfc_rc = RfcWaitForRequest(rfc_handle, wtime);
#else
      fprintf(stderr, "\n<==  RfcListen                rfc_rc = ");
      rfc_rc = RfcListen(rfc_handle);
#endif

      fprintf(stderr, "%d", rfc_rc);
      if (rfc_rc == RFC_RETRY)
      {
        /* do something else while waiting for the next RFC call */

#ifdef SAPonUNIX
	sleep(2);
#elif defined(SAPonNT)
	Sleep(2000);
#else
#error "Error Message > Please update this function for your OS"
#endif

      }
    }
    if (rfc_rc != RFC_OK)
      rfc_error("RfcListen");
#endif

    fprintf(stderr, "\n<==  RfcDispatch .....");
    rfc_rc = RfcDispatch(rfc_handle);
    fprintf(stderr, "\n<==  RfcDispatch              rfc_rc = %d", rfc_rc);

  } while (rfc_rc == RFC_OK);

  rfc_error("RfcDispatch");

#endif

  fprintf(stderr, "\n<==  RfcClose");

  RfcClose(RFC_HANDLE_NULL);

  return 0;
}


/*====================================================================*/
/*                                                                    */
/* Install the RFC-functions offered in this program                  */
/*                                                                    */
/*====================================================================*/
static RFC_RC install(void)
{
  /* Install STFC_CONNECTION */
#ifdef SAPonWINDOWS
  fprintf(stderr, "\n<==  RfcInstallFunctionExt (%s)      rfc_rc = ",
	  name_connection_test);

#ifdef SAP_RFC_GETNAME
  /* Necessary for access docu_function by sm59 (system information) */
  rfc_rc = RfcInstallFunctionExt(rfc_handle,
                                 name_connection_test,
                                 (RFC_ONCALL) NULL,
                                 connection_test_docu());
#else
  rfc_rc = RfcInstallFunctionExt(rfc_handle,
                                 name_connection_test,
                                 (RFC_ONCALL) connection_test,
                                 connection_test_docu());
#endif

#else
  fprintf(stderr, "\n<==  RfcInstallFunction (%s)      rfc_rc = ",
	  name_connection_test);

#ifdef SAP_RFC_GETNAME
  /* Necessary for access docu_function by sm59 (system information) */
  rfc_rc = RfcInstallFunction(name_connection_test,
                              (RFC_ONCALL) NULL,
                              connection_test_docu());
#else
  rfc_rc = RfcInstallFunction(name_connection_test,
                              (RFC_ONCALL) connection_test,
                              connection_test_docu());
#endif

#endif
  fprintf(stderr, "%d", rfc_rc);

  if( rfc_rc != RFC_OK )
  {
    sprintf(abort_text, "\nERROR: Install (%s)      rfc_rc = %d",
	    name_connection_test, rfc_rc);
    function_abort(abort_text);
  }

  /* Install STFC_PERFORMANCE */
#ifdef SAPonWINDOWS
  fprintf(stderr, "\n<==  RfcInstallFunctionExt (%s)     rfc_rc = ",
	  name_performance_test);

#ifdef SAP_RFC_GETNAME
  /* Necessary for access docu_function by sm59 (system information) */
  rfc_rc = RfcInstallFunctionExt(rfc_handle,
                                 name_performance_test,
                                 (RFC_ONCALL) NULL,
                                 performance_test_docu());
#else
  rfc_rc = RfcInstallFunctionExt(rfc_handle,
                                 name_performance_test,
                                 (RFC_ONCALL) performance_test,
                                 performance_test_docu());
#endif

#else
  fprintf(stderr, "\n<==  RfcInstallFunction (%s)     rfc_rc = ",
	  name_performance_test);

#ifdef SAP_RFC_GETNAME
  /* Necessary for access docu_function by sm59 (system information) */
  rfc_rc = RfcInstallFunction(name_performance_test,
                              (RFC_ONCALL) NULL,
                              performance_test_docu());
#else
  rfc_rc = RfcInstallFunction(name_performance_test,
                              (RFC_ONCALL) performance_test,
                              performance_test_docu());
#endif

#endif
  fprintf(stderr, "%d", rfc_rc);

  if( rfc_rc != RFC_OK )
  {
    sprintf(abort_text, "\nERROR: Install (%s)     rfc_rc = %d",
	    name_performance_test, rfc_rc);
    function_abort(abort_text);
  }

  return RFC_OK;
}


/*====================================================================*/
/*                                                                    */
/* RFC-FUNCTION:  STFC_CONNECTION                                     */
/*                                                                    */
/* Send an echo and a response message to the RFC client program      */
/*                                                                    */
/* The prototype of this function must be defined with _loadds on     */
/* Windows because it will run as a QuickWin application and work     */
/* with fprintf.                                                      */
/*                                                                    */
/*====================================================================*/
#ifdef SAPonWINDOWS
static RFC_RC DLL_CALL_BACK_FUNCTION _loadds connection_test(RFC_HANDLE rfc_handle)
#else
static RFC_RC DLL_CALL_BACK_FUNCTION connection_test(RFC_HANDLE rfc_handle)
#endif
{
  fprintf(stderr, "\n\nStart Function '%s'", name_connection_test);

  memset(&parameters[0], 0, sizeof(parameters));

  /* parameters */
  rfc_param(&parameters[0], "REQUTEXT", TYPC, requtext, 255);

  /* no table ---> terminate array */
  tables[0].name = NULL;

  /* receive data */
  fprintf(stderr, "\n<==  RfcGetData               rfc_rc = ");
  rfc_rc = RfcGetData(rfc_handle,
                      parameters,
                      tables);
  fprintf(stderr, "%d", rfc_rc);

  if (rfc_rc != RFC_OK)
    rfc_error("RfcGetData");

  fprintf(stderr, "\n<==  RfcGetAttributes         rc = ");
  rc = RfcGetAttributes(rfc_handle, &rfc_attributes);
  fprintf(stderr, "%d", rc);
  if (rc)
    rfc_error("RfcGetAttributes");

  fprintf(stderr, "\n\nAttributes of this RFC connection");
  fprintf(stderr, "\n---------------------------------");
  fprintf(stderr, "\nDestination :   %s", rfc_attributes.dest);
  fprintf(stderr, "\nOwn Host    :   %s", rfc_attributes.own_host);
  fprintf(stderr, "\nPartner Host:   %s", rfc_attributes.partner_host);
  fprintf(stderr, "\nSystem No.  :   %s", rfc_attributes.systnr);
  fprintf(stderr, "\nClient      :   %s", rfc_attributes.client);
  fprintf(stderr, "\nUser        :   %s", rfc_attributes.user);
  fprintf(stderr, "\nLanguage    :   %s\n", rfc_attributes.language);

  /* Echo text */
  strcpy(echotext, requtext);

  /* Info text */
  memset(resptext, BLANK, 255);
  memcpy(resptext, "Sysid:", 6);
  ptr = getenv("HOSTNAME");
  if (ptr == NULL)
    ptr = getenv("USER");
  if (ptr == NULL)
    ptr = getenv("LOGNAME");
  if (ptr != NULL)
    strcpy(resptext+7, ptr);
  else
    strcpy(resptext+7, "????????");
  resptext[strlen(resptext)] = ' ';

  memcpy(resptext+18, "Date & Time:", 12);
  actutime = time(NULL);
  time_ptr = localtime(&actutime);
  memcpy(&resptext[31], asctime(time_ptr), 24);

#ifdef SAP_RFC_CALLBACK

  /*------------------------------------------------------------------*/
  /* Call back test                                                   */
  /*------------------------------------------------------------------*/

  function = "RFC_PING";

  fprintf(stderr, "\n\nCall Back Test (using the same RFC connection!) .....");
  fprintf(stderr, "\n<==  RfcCallReceive (%s)     rfc_rc = ", function);
  rfc_rc = RfcCallReceive(rfc_handle,
                          function,
                          NULL,
                          NULL,
                          NULL,
                          &exception);
  fprintf(stderr, "%d\n", rfc_rc);

  /* check return code */
  switch(rfc_rc)
  {
    case RFC_OK:
      break;
    case RFC_EXCEPTION :
    case RFC_SYS_EXCEPTION :
      rfc_error(exception);
      break;
    default :
      rfc_error("RfcCallReceive");
      break;
  }

#endif

  /*------------------------------------------------------------------*/
  /* Return parameters and tables                                     */
  /*------------------------------------------------------------------*/

  memset(&parameters[0], 0, sizeof(parameters));

  /* parameters */
  rfc_param(&parameters[0], "ECHOTEXT", TYPC, echotext, 255);
  rfc_param(&parameters[1], "RESPTEXT", TYPC, resptext, 255);

  /* no table ---> terminate array */
  tables[0].name = NULL;

  /* return to the caller */
  fprintf(stderr, "\n<==  RfcSendData              rfc_rc = ");
  rfc_rc = RfcSendData(rfc_handle,
                       parameters,
                       tables);
  fprintf(stderr, "%d", rfc_rc);

  if (rfc_rc != RFC_OK)
    rfc_error("RfcSendData");

  return rfc_rc;
}


/*====================================================================*/
/*                                                                    */
/* RFC-FUNCTION:  STFC_PERFORMANCE                                    */
/*                                                                    */
/* Send and Receive internal tables as required                       */
/*                                                                    */
/* The prototype of this function must be defined with _loadds on     */
/* Windows because it will run as a QuickWin application and work     */
/* with fprintf.                                                      */
/*                                                                    */
/*====================================================================*/
#ifdef SAPonWINDOWS
static RFC_RC DLL_CALL_BACK_FUNCTION _loadds performance_test(RFC_HANDLE rfc_handle)
#else
static RFC_RC DLL_CALL_BACK_FUNCTION performance_test(RFC_HANDLE rfc_handle)
#endif
{
  fprintf(stderr, "\n\nStart Function '%s'", name_performance_test);

  memset(&parameters[0], 0, sizeof(parameters));

  /* parameter */
  rfc_param(&parameters[0], "CHECKTAB", TYPC, checktab, 1);
  rfc_param(&parameters[1], "LGIT0332", TYPC, lgit0332_field, 5);
  rfc_param(&parameters[2], "LGIT1000", TYPC, lgit1000_field, 5);

  rfc_param(&parameters[3], "LGET0332", TYPC, lget0332_field, 5);
  rfc_param(&parameters[4], "LGET1000", TYPC, lget1000_field, 5);

  /* Prepare internal table ITAB0332 */
  tables[0].name     = "ITAB0332";
  tables[0].nlen     = 8;
  tables[0].type     = TYPC;
  tables[0].leng     = ITAB0332_ENTRY_SIZE;
  tables[0].itmode   = RFC_ITMODE_BYREFERENCE;

  /* Prepare internal table ITAB1000 */
  tables[1].name     = "ITAB1000";
  tables[1].nlen     = 8;
  tables[1].type     = TYPC;
  tables[1].leng     = ITAB1000_ENTRY_SIZE;
  tables[1].itmode   = RFC_ITMODE_BYREFERENCE;

  /* Prepare internal table ETAB0332 */
  tables[2].name     = "ETAB0332";
  tables[2].nlen     = 8;
  tables[2].type     = TYPC;
  tables[2].leng     = ETAB0332_ENTRY_SIZE;
  tables[2].itmode   = RFC_ITMODE_BYREFERENCE;

  /* Prepare internal table ETAB1000 */
  tables[3].name     = "ETAB1000";
  tables[3].nlen     = 8;
  tables[3].type     = TYPC;
  tables[3].leng     = ETAB1000_ENTRY_SIZE;
  tables[3].itmode   = RFC_ITMODE_BYREFERENCE;

  /* terminate array */
  tables[4].name = NULL;

  /* receive data */
  fprintf(stderr, "\n<==  RfcGetData               rfc_rc = ");
  rfc_rc = RfcGetData(rfc_handle,
                      parameters,
                      tables);
  fprintf(stderr, "%d", rfc_rc);

  if (rfc_rc != RFC_OK)
    rfc_error("RfcGetData");

  fprintf(stderr, "\n<==  RfcGetAttributes         rc = ");
  rc = RfcGetAttributes(rfc_handle, &rfc_attributes);
  fprintf(stderr, "%d", rc);
  if (rc)
    rfc_error("RfcGetAttributes");

  fprintf(stderr, "\n\nAttributes of this RFC connection");
  fprintf(stderr, "\n---------------------------------");
  fprintf(stderr, "\nDestination :   %s", rfc_attributes.dest);
  fprintf(stderr, "\nOwn Host    :   %s", rfc_attributes.own_host);
  fprintf(stderr, "\nPartner Host:   %s", rfc_attributes.partner_host);
  fprintf(stderr, "\nSystem No.  :   %s", rfc_attributes.systnr);
  fprintf(stderr, "\nClient      :   %s", rfc_attributes.client);
  fprintf(stderr, "\nUser        :   %s", rfc_attributes.user);
  fprintf(stderr, "\nLanguage    :   %s\n", rfc_attributes.language);

  /* Receive length of all ITABnnnn and ETABnnnn */
  lgit0332 = atol(lgit0332_field);
  lgit1000 = atol(lgit1000_field);
  lget0332 = atol(lget0332_field);
  lget1000 = atol(lget1000_field);

  /* Check receive length and real length of ITAB0332 */
  check_table(tables[0].ithandle, "ITAB0332", lgit0332, checktab, text0332, retcode);
  exitcode[0] = retcode[0];

  /* Check receive length and real length of ITAB1000 */
  check_table(tables[1].ithandle, "ITAB1000", lgit1000, checktab, text1000, retcode);
  if (exitcode[0] == 'O')
    exitcode[0] = retcode[0];

  if (exitcode[0] == 'O')
  {
    /* Fill table ETAB0332 as required */
    if (fill_table(tables[2].ithandle, lget0332))
    {
      fprintf(stderr, "\nERROR: Fill table etab0332\n");
      exitcode[0] = 'E';
    }
    else
    {
      /* Fill table ETAB1000 as required */
      if (fill_table(tables[3].ithandle, lget1000))
      {
        fprintf(stderr, "\nERROR: Fill table itab1000\n");
        exitcode[0] = 'E';
      }
    }
  }

  /*------------------------------------------------------------------*/
  /* Return parameters and tables                                     */
  /*------------------------------------------------------------------*/

  memset(&parameters[0], 0, sizeof(parameters));

  /* parameters */
  rfc_param(&parameters[0], "EXITCODE", TYPC, exitcode, 1);
  rfc_param(&parameters[1], "TEXT0332", TYPC, text0332, 72);
  rfc_param(&parameters[2], "TEXT1000", TYPC, text1000, 72);

  /* return to the caller */
  fprintf(stderr, "\n<==  RfcSendData              rfc_rc = ");
  rfc_rc = RfcSendData(rfc_handle,
                       parameters,
                       tables);
  fprintf(stderr, "%d", rfc_rc);

  if (rfc_rc != RFC_OK)
    rfc_error("RfcSendData");

  return rfc_rc;
}


/*====================================================================*/
/*                                                                    */
/* Documentation for functions STFC_CONNECTION                        */
/*                                                                    */
/*====================================================================*/
#undef  NL
#define NL "\n"
static char *connection_test_docu(void)
{
  static char docu[] =
  "RFC-Client has to send a message to this function and wait   "     NL
  "for the echo and a response message (max. 255 B).            "     NL
  ""                                                                  NL
  "IMPORTING"                                                         NL
  "  REQUTEXT        C(255)"                                          NL
  "EXPORTING"                                                         NL
  "  ECHOTEXT        C(255)"                                          NL
  "  RESPTEXT        C(255)"                                          NL
   ;
  return docu;
}


/*====================================================================*/
/*                                                                    */
/* Documentation for functions STFC_PERFORMANCE                       */
/*                                                                    */
/*====================================================================*/
static char *performance_test_docu(void)
{
  static char docu[] =
  "RFC-Client can send data in max. 2 different tables and then "     NL
  "wait for response (data in max. 2 different tables).         "     NL
  ""                                                                  NL
  "RFC-Client must define:                                      "     NL
  "     - the number of lines in 4 tables as importing parameter"     NL
  "     - the parameter checktab (Y/N) for checking the contents"     NL
  "       of the 2 importing tables (ITAB0332 and ITAB1000)     "     NL
  ""                                                                  NL
  "IMPORTING"                                                         NL
  "  CHECKTAB        C(1)"                                            NL
  "  LGIT0332        C(5)"                                            NL
  "  LGIT1000        C(5)"                                            NL
  "  LGET0332        C(5)"                                            NL
  "  LGET1000        C(5)"                                            NL
  "EXPORTING"                                                         NL
  "  EXITCODE        C(1)"                                            NL
  "  TEXT0332        C(72)"                                           NL
  "  TEXT1000        C(72)"                                           NL
  "TABLES"                                                            NL
  "  ITAB0332        C(0332)"                                         NL
  "  ITAB1000        C(1000)"                                         NL
  "  ETAB0332        C(0332)"                                         NL
  "  ETAB1000        C(1000)"                                         NL
   ;
  return docu;
}


/*--------------------------------------------------------------------*/
/* set up RFC parameters                                              */
/*--------------------------------------------------------------------*/
void rfc_param(RFC_PARAMETER *rfc_param,
               char          *abap_field_name,
               unsigned      data_type,
               void          *data_addr,
               unsigned      data_len)
{
  RFC_PARAMETER *p = rfc_param;

  p->name = (void *)abap_field_name;
  p->nlen = abap_field_name == NULL ? 0 : strlen(abap_field_name);
  p->type = data_type;
  p->addr = data_addr;
  p->leng = data_len;

  /* init next parameter for no more parameter */

  p++;
  p->name = NULL;
  p->nlen = 0;
  p->type = 0;
  p->addr = NULL;
  p->leng = 0;

  return;
}


/*--------------------------------------------------------------------*/
/* Error Cleanup because of an RFC-Error                              */
/* Because of Windows DLL function must not be defined as static      */
/*--------------------------------------------------------------------*/
void DLL_CALL_BACK_FUNCTION rfc_error(char *operation )
{
  memset(&error_info, 0, sizeof(error_info));

  fprintf(stderr, "\n<==  RfcLastError\n");

  RfcLastError(&error_info);

  if (function != NULL)
    fprintf(stderr, "\nFUNCTION: %s", function);

  if (exception != NULL)
    fprintf(stderr, "\nEXCEPTION: %s", exception);

  fprintf(stderr, "\nRFC operation/code %s\n", operation);

  fprintf(stderr, "ERROR/EXCEPTION\n");
  fprintf(stderr, "key     : %s\n", error_info.key);
  fprintf(stderr, "status  : %s\n", error_info.status);
  fprintf(stderr, "message : %s\n", error_info.message);
  fprintf(stderr, "internal: %s\n", error_info.intstat);

  fprintf(stderr, "\n<==  RfcClose\n");
  RfcClose(RFC_HANDLE_NULL);

  exit(1);
}


/*--------------------------------------------------------------------*/
/* Issue RfcAbort with Abort Text because of an Application Error     */
/*--------------------------------------------------------------------*/
void function_abort(char *atext)
{
  fprintf(stderr, "\n<==  RfcAbort       %s", atext);

  RfcAbort(rfc_handle, atext);
  exit(1);
}


/*--------------------------------------------------------------------*/
/* Fill internal table as required                                    */
/*--------------------------------------------------------------------*/
int fill_table(ITAB_H itab_h,
               long   leng)
{
  long	position,
        linenr;
  char  etext[1001];

  if (leng == 0)
    return 0;

  lineleng = ulen = ItLeng(itab_h);

  memset(etext, BLANK, 1000);

  for (position=40; position<lineleng; position++)
    sprintf(etext+position, "%01d", position % 10);

  sprintf(etext, "Line Length: %04d   Line No.: ", lineleng);

  for (linenr=1; linenr<=leng; linenr++)
  {
    sprintf(etext+30, "%05d", linenr);
    etext[35] = ' ';

    ptr = (char *) ItAppLine(itab_h);
    if (ptr == NULL) break;
    memcpy(ptr, etext, ulen);
  }

  if (linenr <= leng)
    return 1;
  else
    return 0;
}


/*--------------------------------------------------------------------*/
/* Check ETABnnnn                                                     */
/*--------------------------------------------------------------------*/
int check_table(ITAB_H itab_h,
                char   *itabname,
                long   recvleng,
                char   *checktab,
                char   *rtext,
                char   *retcode)
{
  long  position;

  char  value[2],
        tbuff[1001],
        etext[73]= " ",
        errline[40]="ERROR:  #Lines = nnnnn  Expected: nnnnn",
        errcont[40]="ERROR at line nnnnn position nnnn:  n/n",
        mtext[73]  ="Import table (length nnnn):  #Lines = nnnnn: OK,  Contents: OK";

  memset(etext, ' ', 72);

  itableng = ItFill(itab_h);
  lineleng = ulen = ItLeng(itab_h);

  strcpy(etext, mtext);
  etext[strlen(etext)] = ' ';

  if (itabname[0] == 'I')
    memcpy(etext, "Ex", 2);

  memcpy(etext+21, itabname+4, 4);

  if (itableng != recvleng)
  {
    memcpy(etext+28, errline, 39);
    sprintf(etext+45, "%05d", itableng);
    etext[50] = ' ';
    sprintf(etext+62, "%05d", recvleng);
    etext[67] = ' ';
    retcode[0] = 'E';
  }
  else
  {
    sprintf(etext+38, "%05d", itableng);
    etext[43] = ':';
    retcode[0] = 'O';

    if (checktab[0] != 'Y')
      memcpy(etext+60, "NO CHECK", 8);
    else
    {
      for (j = 1; ; j++)
      {
        ptr = (char *) ItGetLine(itab_h, j);
        if (ptr == NULL) break;

        memcpy(tbuff, ptr, ulen);
        tbuff[lineleng] = '\0';

        for (position=40; position<lineleng; position++)
        {
          sprintf(value, "%01d", position % 10);
          if (value[0] != tbuff[position])
          {
            retcode[0] = 'E';
            break;
          }
          position = position + 1;
        }
        if (retcode[0] == 'E')
        {
          memcpy(etext+28, errcont, 39);
          sprintf(etext+42, "%05d", j);
          etext[47] = ' ';
          sprintf(etext+57, "%05d", position);
          etext[62] = ' ';
          etext[64] = tbuff[position];
          etext[66] = value[0];
          break;
        }
      }
    }
  }

  strcpy(rtext, etext);
  return 0;
}


/*--------------------------------------------------------------------*/
/* Output help for starting program                                   */
/*--------------------------------------------------------------------*/
static void help(void)
{
#define NL "\n"
  printf( NL                                                             );
  printf( "Syntax for start and run in register mode:"                NL );
  printf( " "                                                         NL );
  printf( "  srfcserv [options]"                                      NL );
  printf( " "                                                         NL );
  printf( "  with"                                                    NL );
  printf( "  options = -D<destination with type 'R' in saprfc.ini>"   NL );
  printf( "          = -t             RFC-Trace on"                   NL );
  printf( "  or"                                                      NL );
  printf( "  options = -a<program ID> e.g. <own host name>.srfcserv"  NL );
  printf( "          = -g<SAP gateway host name>        e.g.  hs0311" NL );
  printf( "          = -x<SAP gateway service>          e.g. sapgw53" NL );
  printf( "          = -t             RFC-Trace on"                   NL );
  printf( " "                                                         NL );
  return;
}

