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

  module: vcn40.cpp

  -----------------------------------------------------------------------------

  responsible:  BerndV

  special area: DBMServer

  description:  DBMServer start-stop / system / registry access

  -----------------------------------------------------------------------------



    ========== 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




*/

/*
  -----------------------------------------------------------------------------
  includes
  -----------------------------------------------------------------------------
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h> 
#include <sys/stat.h>

#include "SAPDBCommon/SAPDB_string.h"

#include "vsp001.h"
#include "hsp77.h"
#include "gsp09.h"
#include "geo28.h"
#include "geo43.h"

#include "gip00.h"
#include "heo02.h"
#include "heo03.h"
#include "heo06.h"
#include "heo11.h"
#include "hsp100.h"
#include "RunTime/RTE_Types.h"
#include "RunTime/Diagnose/RTEDiag_ClientCrashHist.h"

#ifndef _WIN32
  #include "RunTime/RTE_UNIXAuthenticate.hpp"           // nocheck
#endif

//#include "hin101.h"
#include "hin110.h"

#include "ToolsCommon/Tools_System.hpp"
#include "SAPDB/DBM/Srv/HSS/DBMSrvHSS_Nodes.hpp"
#include "SAPDB/DBM/Srv/Process/DBMSrvProc_ServerProcess.hpp"

#include "hcn20.h"
#include "hcn30.h"
#include "hcn31.h"
#include "hcn42.h"
#include "hcn44.h"
#include "hcn46.h"
#include "hcn50.h"
#include "hcn51.h"
#include "hcn80.h"
#include "hcn82.h"
#include "hcn84.h"
#include "hcn90.h"

#include "hcn40.h"

#include "SAPDB/DBM/Srv/KernelAccess/DBMSrvKnl_Session.hpp"

#include "KernelCommon/ParameterNames/KernelParam_IOManager.hpp"
#include "ToolsCommon/Tools_PipeCall.hpp"

#include "RunTime/RTE_ActiveDatabase.hpp"
#include "RunTime/RTE_DBRegister.hpp"
#include "SAPDB/DBM/Srv/Process/DBMSrvProc_EnvironmentVariable.hpp"

extern "C" int chdir(const char * szDir);

/*
  -----------------------------------------------------------------------------
  specification private macros
  -----------------------------------------------------------------------------
*/
#define SYS_SYSTEM_ERR        -1
#define SYS_MKDIR_ERR         -1
#define SYS_MKDIR_OK          0
#define CHAR_SLASH            '/'
#define CHAR_BACKSLASH        '\\'
#define CHAR_DRIVE            ':'
#define TMP_ENV               "TMP"
#define TMP_LOCDIR            "."
#define TMP_EXT               "cst"
#define REPMAN_PRT            "loader.log"
#define UTIL_PRT              "util.prt"

#define OPT_OPT_AUTO          "-auto"
#define OPTS_OPT_AUTO         "-a"

#define OPT_OPT_GROUP         "-group"
#define OPTS_OPT_GROUP        "-g"

#define OPT_OPT_USER          "-user"
#define OPTS_OPT_USER         "-u"

#define OPT_VAL_ON            "on"
#define OPT_VAL_OFF           "off"

#define OPT_SPEED_FAST        "-fast"
#define OPTS_SPEED_FAST       "-f"

#define OPT_SPEED_QUICK       "-quick"
#define OPTS_SPEED_QUICK      "-q"

#define OPT_SPEED_SLOW        "-slow"
#define OPTS_SPEED_SLOW       "-s"

#define OPT_SPEED_TEST        "-test"
#define OPTS_SPEED_TEST       "-t"

#define OPT_REGIST_ROOT       "-Root"
#define OPTS_REGIST_ROOT      "-R"

#define OPTS_STOP_DUMP        "-d"
#define OPT_STOP_DUMP         "-dump"

#define OPTS_STOP_NOCLUSTER   "-nc"
#define OPT_STOP_NOCLUSTER    "-nocluster"

#define OPT_RESTART_UNTIL     "-until"
#define OPTS_RESTART_UNTIL    "-u"

#define TXT_TAKEOVER          "TAKEOVER"
#define TXT_RESTART           "RESTART"
#define TXT_RESTART_UNTIL     "RESTART UNTIL '%s' '%s'"

#define OPT_LOAD_DBA          "-u"
#define OPT_LOAD_DOM          "-ud"
#define OPT_LOAD_MIGRATE      "-m"
#define LOAD_FILE             "lsystab.ins"
#define PYTHON_FILE           "lsystab.py"
#define LOAD_OPT              "en ENG"
#define R3_FILE               "CNR3DATA.ins"
#define PYR3_FILE             "CNR3DATA.py"
#define LCAPPS_FILE           "lapps.py"
#define TUTORIAL_FILE         "../demo/ltutorial.py"

#define LOAD_INIT             "INIT AFTER LOAD"

#define TXT_CMD_SHOW          "SHOW"
#ifdef _WIN32
  #define TXT_CMD_XCONS         _T("\"pgm\\cons.exe\"")
#else
  #define TXT_CMD_XCONS         _T("pgm/cons")
#endif
#define TXT_CMD_HELP          "help"

#define TXT_CMD_STATE         "State"

#define TXT_CMD_SPEED         "Speed"

#define TXTU_SPEED_FAST       "FAST"
#define TXTL_SPEED_FAST       "fast"

#define TXTU_SPEED_QUICK      "QUICK"
#define TXTL_SPEED_QUICK      "quick"

#define TXTU_SPEED_SLOW       "SLOW"
#define TXTL_SPEED_SLOW       "slow"

#define TXTU_SPEED_TEST       "TEST"
#define TXTL_SPEED_TEST       "test"

#define TXTU_SPEED_UNKNOWN    "UNKNOWN"
#define TXTL_SPEED_UNKNOWN    "unknown"

#define TXT_CMD_LCINITSAP     "sap%clcinit %s %s -uDBM %s,%s -uDBA %s,%s -uSQL %s,%s -ud %s"
#define TXT_CMD_LCINIT        "sap%clcinit %s %s -uDBM %s,%s -uDBA %s,%s -ud %s"
#define TXT_CMD_XPU           "xpu %s"
#ifdef _WIN32
  #define TXT_CMD_NIPINGTEST  "sap\\niping -t"
  #define TXT_PRT_NIPINGTEST  "sap\\niping -t"
  #define TXT_CMD_NIPING      "start /B sap\\niping -s -I %d"
  #define TXT_PRT_NIPING      "sap\\niping -s -I %d"
#else
  #define TXT_CMD_NIPINGTEST  "sap/niping -t"
  #define TXT_PRT_NIPINGTEST  "sap/niping -t"
  #define TXT_CMD_NIPING      "sap/niping -s -I %d &"
  #define TXT_PRT_NIPING      "sap/niping -s -I %d"
#endif
#define TXT_CMD_SDBINFO       "sdbinfo"
#define TXT_CMD_SDBINST       "SDBINST"

#define KEYDROP_WITHOUTFILES  "WITHOUTFILES"

#define RTE_INDPROG           "IndepProgPath"
#define RTE_INDDATA           "IndepDataPath"

#define OPTS_INST_VERSION     "-v"
#define OPTS_INST_KEY         "-k"
#define OPTS_INST_CLIENT      "-c"
#define OPTS_ENUM_SRV         "-s"

#define TEST_OPT_WAIT         "-w"

#define SQL_CHECKSYSDBA           "SELECT * FROM SYSDD.VERSION WHERE SYSDBA=USER"

#define SQL_DBANLOCK_CHECKTABLE    "EXISTS TABLE SYSDBANA.DBANLOCK"
#define SQL_DBANLOCK_CREATESCHEMA  "CREATE USER SYSDBANA PASSWORD %s RESOURCE NOT EXCLUSIVE"
#define SQL_DBANLOCK_GRANTSCHEMA   "ALTER PASSWORD SYSDBANA %s"
#define SQL_DBANLOCK_CREATETABLE   "CREATE TABLE DBANLOCK (FIELD1 INT)"
#define SQL_DBANLOCK_CREATEGRANT   "GRANT INSERT ON DBANLOCK TO PUBLIC"
#define SQL_DBANLOCK_LOCK          "LOCK (WAIT) TABLE SYSDBANA.DBANLOCK IN EXCLUSIVE MODE"

#define TXT_SQLOPT            "SQLOPT=-d %s -u %s,%s"

#define MAX_DBNAME            8

#ifdef _WIN32
  #define TXT_CMD_DBMEXT        "bin\\dbmevtdisp -d %s -u %s,%s"
#else
  #define TXT_CMD_DBMEXT        "bin/dbmevtdisp -d %s -u %s,%s"
#endif
/*
  -----------------------------------------------------------------------------
  specification private functions
  -----------------------------------------------------------------------------
*/

static tcn00_Error cn40_DBDrop
      (       tsp00_DbNamec   szDbName,
        const tsp00_Pathc     szDbRoot,
        const bool            bWithFiles,
        const bool            bDeleteLog,
        char                * replyData,
        int                 * replyLen,
        const int             replyLenMax);

static tcn00_Error cn40_ExecPythonLoad
      ( VControlDataT * vcontrol,
        const char    * szLoadFile,
        const char    * szUser,
        const char    * szPassword,
        const char    * szOptions,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax);

static tcn00_Error cn40_OfflineToCold
      ( VControlDataT       * vcontrol,
        const tsp9_pgm_kind   pgmKind,
        char                * replyData,
        int                 * replyLen);

static tcn00_Error cn40_ColdOrStandbyToWarm
      ( VControlDataT       * vcontrol,
        const char          * pRestart,
        char                * replyData,
        int                 * replyLen);

static tcn00_Error cn40_OnlineToOffline
      ( VControlDataT       * vcontrol,
        bool                  bCluster,
        char                * replyData,
        int                 * replyLen);

static tcn00_Error cn40_ColdOrStandbyToOffline
      ( VControlDataT       * vcontrol,
        const bool            bDump,
        char                * replyData,
        int                 * replyLen);

static tcn00_Error cn40_CheckVersion
      ( const tsp00_DbNamec   szDBName);

static tcn00_Error cn40_StartStopOptions
      ( const char    * szParameters,
        tsp9_pgm_kind & pgmKind,
        bool          & bDump,
        char          * pRestart,
        bool          & bCluster );

static tcn00_Error cn40_ChangeDBState
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax,
        tcn00_DBState   targetState,
        bool            bStop = false);

static bool cn40_CheckInstKey
      ( const tsp09_RteInstallationInfoNew  & relInfoIn );

static bool cn40_RegisterServiceDB
      ( const tsp09_RteInstallationInfoNew  & relInfoIn); 

static tcn00_Error cn40_StartEventDispatcher
      ( VControlDataT * vcontrol );
/*
  -----------------------------------------------------------------------------
  implementation of public functions
  -----------------------------------------------------------------------------
*/

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBMNext
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBMNext
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40AutoNext");

  if (vcontrol->szNextCommand.length() > 0) {
    // print answer
    sp77sprintf(replyData, replyLenMax, "%s%s%s%s%d%s",
                ANSWER_OK_CN00,
                LINE_SEPSTRING_CN00,
                vcontrol->szNextCommand.asCharp(),
                LINE_SEPSTRING_CN00,
                vcontrol->nNextCommandSkip,
                LINE_SEPSTRING_CN00);
    *replyLen = (int) strlen(replyData);
    // clear next command
    vcontrol->szNextCommand.rawAssign("");
    vcontrol->nNextCommandSkip = 0;
  } else {
    // print only a OK (no error!!!)
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if

  return OK_CN00;
} /* end cn40DBMNext */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40ExecLcInit
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ExecLcInit
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40ExecLcInit");

  tcn00_Error     nFuncReturn = OK_CN00;
  char            szCommand      [PARAMETER_MAXLEN_CN90] = "";
  char            szPrCommand    [PARAMETER_MAXLEN_CN90] = "";
  bool            bSAPExists  = true;

  // collect the users
  cn50DBMUser oSAPUser   (vcontrol->dbname, cn50DBMUser::getSAPUser (vcontrol->dbname));
  if (oSAPUser.lastEvent()) {
    bSAPExists  = false;
  } // end if
  
  cn50DBMUser oDBMUser   (vcontrol->dbname, cn50DBMUser::getColdUser(vcontrol->dbname));
  if (oDBMUser.lastEvent()) {
    teo200_EventList aEvent(oDBMUser.lastEvent(), FUNCTION_NAME_MCN00_1, ERR_USRREAD_CN00_1);
    nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    return nFuncReturn;
  } // end if
  
  cn50DBMUser oDBAUser   (vcontrol->dbname, cn50DBMUser::getSYSDBA  (vcontrol->dbname));
  if (oDBAUser.lastEvent()) {
    teo200_EventList aEvent(oDBAUser.lastEvent(), FUNCTION_NAME_MCN00_1, ERR_DBAUNKNOWN_CN00_1);
    nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    return nFuncReturn;
  } // end if

  cn50DBMUser oDOMAINUser(vcontrol->dbname, cn50DBMUser::getDOMAIN  (vcontrol->dbname));
  if (oDOMAINUser.lastEvent()) {
    teo200_EventList aEvent(oDOMAINUser.lastEvent(), FUNCTION_NAME_MCN00_1, ERR_DOMPUNKNOWN_CN00_1);
    nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    return nFuncReturn;
  } // end if


  if (bSAPExists) {
    //#define TXT_CMD_LCINITSAP     "sap%clcinit %s %s -uDBM %s,%s -uDBA %s,%s -uSQL %s,%s -ud %s"
    sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, TXT_CMD_LCINITSAP, PATH_DELIMITER_CN90, 
                                                                     vcontrol->dbname.asCharp(), 
                                                                     command->args,
                                                                     oDBMUser.getUserName().asCharp(),
                                                                     oDBMUser.getClearMasterPwd().asCharp(),
                                                                     oDBAUser.getUserName().asCharp(),
                                                                     oDBAUser.getClearMasterPwd().asCharp(),
                                                                     oSAPUser.getUserName().asCharp(),
                                                                     oSAPUser.getClearMasterPwd().asCharp(),
                                                                     oDOMAINUser.getClearMasterPwd().asCharp()
                                                                     );

    sp77sprintf(szPrCommand, PARAMETER_MAXLEN_CN90, TXT_CMD_LCINITSAP, PATH_DELIMITER_CN90, 
                                                                     vcontrol->dbname.asCharp(), 
                                                                     command->args,
                                                                     "*",
                                                                     "*",
                                                                     "*",
                                                                     "*",
                                                                     "*",
                                                                     "*",
                                                                     "*"
                                                                     );
  } else {
    //#define TXT_CMD_LCINIT     "sap%clcinit %s %s -uDBM %s,%s -uDBA %s,%s -ud %s"
    sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, TXT_CMD_LCINIT, PATH_DELIMITER_CN90, 
                                                                  vcontrol->dbname.asCharp(), 
                                                                  command->args,
                                                                  oDBMUser.getUserName().asCharp(),
                                                                  oDBMUser.getClearMasterPwd().asCharp(),
                                                                  oDBAUser.getUserName().asCharp(),
                                                                  oDBAUser.getClearMasterPwd().asCharp(),
                                                                  oDOMAINUser.getClearMasterPwd().asCharp()
                                                                  );

    sp77sprintf(szPrCommand, PARAMETER_MAXLEN_CN90, TXT_CMD_LCINIT, PATH_DELIMITER_CN90, 
                                                                  vcontrol->dbname.asCharp(), 
                                                                  command->args,
                                                                  "*",
                                                                  "*",
                                                                  "*",
                                                                  "*",
                                                                  "*"
                                                                  );
  } // end if

  nFuncReturn = cn40ExecCommand(replyData, replyLen, replyLenMax, szCommand, szPrCommand, false, true);

  if (nFuncReturn == OK_CN00) {
    // check the lcinit output
    char * pTemp  = new char[*replyLen + 10];
    char * pData  = NULL;

    if (pTemp != NULL) {
      SAPDB_strcpy(pTemp, replyData);

      // find Nutzlast
      pData = strchr (pTemp, '\n');
      if (pData != NULL) {
        ++pData;
        pData = strchr (pData, '\n');
      } // end if
      if (pData != NULL) {
        ++pData;
        if (strstr(pData, "\nERROR") != NULL) {
          // fake answer
          nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_EXECUTE_CN00);
          pTemp = replyData + strlen(replyData);
          SAPDB_strcpy(pTemp, pData);
          *replyLen = (int) strlen(replyData);
        } // end if

      } // end if

      delete [] pTemp;
    } // end if

  } // end if

  return nFuncReturn;

} /* end cn40ExecLcInit */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40ExecLcInit1
 * ------------------------------------------------------------------
 */
#define LCINIT_MOD_INIT             "INIT"
#define LCINIT_MOD_REGISTER         "REGISTER"
#define LCINIT_MOD_RESTART          "RESTART"
#define LCINIT_MOD_SLOW             "SLOW"
#define LCINIT_MOD_STOP             "STOP"
#define LCINIT_MOD_SHUTDOWN         "SHUTDOWN"

#define LCINIT_OPT_ENCODING         "-e"
#define LCINIT_OPT_DEBUG            "debug"

tcn00_Error cn40ExecLcInit1
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40ExecLcInit1");

  tcn00_Error     nFuncReturn = OK_CN00;
  int             nToken      = 1;
  char            szCommand[PARAMETER_MAXLEN_CN90];
  char            szParameter[PARAMETER_MAXLEN_CN90];


  // read command
  if (!cn90GetToken(command->args, szCommand, nToken, PARAMETER_MAXLEN_CN90)) {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
  } // end if

  ++nToken;
  
  while ((nFuncReturn == OK_CN00) && cn90GetToken(command->args, szParameter, nToken, PARAMETER_MAXLEN_CN90)) {
    if (stricmp(szParameter,LCINIT_OPT_DEBUG) == 0) {
    } // end if

  } // end if


  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if
  

  return nFuncReturn;

} /* end cn40ExecLcInit1 */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40ExecSDBInfo
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ExecSDBInfo
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error     nFuncReturn = OK_CN00;
  char            szCommand [PARAMETER_MAXLEN_CN90];

  /* read the parameters */
  if (nFuncReturn == OK_CN00) {
    sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90-1, "%s %s", TXT_CMD_SDBINFO, command->args);
    nFuncReturn = cn40ExecCommand(replyData, replyLen, replyLenMax, szCommand, szCommand, false, true);
  } /* end if */

  return nFuncReturn;
} /* end cn40ExecSDBInfo */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40ExecSDBInst
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ExecSDBInst
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error     nFuncReturn = OK_CN00;

  char            szDirectory[PARAMETER_MAXLEN_CN90];
  char         *  pCurrent;
  /**/

  // read parameters 
  cn90GetToken(command->args, szDirectory, 1, PARAMETER_MAXLEN_CN90);

  // init OK
  cn90AnswerOK (replyData, replyLen, NULL);
  pCurrent = replyData + strlen(replyData);

  // readpacket info
  if (!cn44_PackageInfo(szDirectory, pCurrent, replyLenMax - (int)(pCurrent - replyData))) {
    char * pError = new char[strlen(pCurrent) + 1];
    if (pError != NULL) {
      SAPDB_strcpy(pError, pCurrent);
      nFuncReturn = cn90AnswerRTEError(replyData, replyLen, ERR_RTE_CN00, pError, (int) strlen(pError), -1);
    } else {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_MEM_CN00);
    } // end if
  } // end if

  *replyLen = (int) strlen(replyData);

  return nFuncReturn;
} /* end cn40ExecSDBInst */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40ExecNiPingSrv
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ExecNiPingSrv
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error     nFuncReturn = OK_CN00;
  char            szIdleTime  [PARAMETER_MAXLEN_CN90] = "";
  int             nIdleTime   = 300;
  char            szCommand [PARAMETER_MAXLEN_CN90];
  char            szProtocol [PARAMETER_MAXLEN_CN90];

  if (cn90GetToken(command->args, szIdleTime,  1, PARAMETER_MAXLEN_CN90) ) {
    nIdleTime = atoi(szIdleTime);
    if (nIdleTime == 0) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if
  
  // get indepprogpath and add lib
  tsp00_Pathc     szDir;
  szDir.Init();
  tsp01_RteError  aRteError;
  sqlGetDbrootPath(szDir, TERM_WITH_DELIMITER_EO01, &aRteError);
  strcat(szDir, "lib");

  // change process environment
  DBMSrvMsg_Error oError;
  DBMSrvProc_EnvironmentVariable oLibpath(LDLIBPATH_IP00);
  if (oLibpath.Manipulate(szDir.asCharp(), ENVSEP_IP00, DBMSrvProc_EnvironmentVariable::ManipulatePrependOrAdd,oError) == DBMSrvProc_EnvironmentVariable::ManipulateError) {
     SAPDBErr_MessageList aDBM(DBMSrv_DBMError(EXECUTE), 0);
     aDBM.AppendNewMessage(oError);
     nFuncReturn = DBMSrv_Reply(replyData, replyLen, replyLenMax).startWithMessageList(oError);
  } // end if

  if (nFuncReturn == OK_CN00) {
    sprintf(szCommand, TXT_CMD_NIPINGTEST);
    sprintf(szProtocol, TXT_PRT_NIPINGTEST);
    nFuncReturn = cn40ExecCommand(replyData, replyLen, replyLenMax, szCommand, szProtocol, false, true);
  } // end if

  if (nFuncReturn == OK_CN00) {
    sprintf(szCommand, TXT_CMD_NIPING, nIdleTime);
    sprintf(szProtocol, TXT_PRT_NIPING, nIdleTime);
    nFuncReturn = cn40ExecCommand(replyData, replyLen, replyLenMax, szCommand, szProtocol, false, true);
  } // end if

  // reset process environment
  DBMSrvMsg_Error oDummy;
  oLibpath.Reset(oDummy);

  return nFuncReturn;
} /* end cn40ExecNiPingSrv */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40ExecXPU
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ExecXPU
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error   nFuncReturn = OK_CN00;
  const char  * pCommand    = command->args;
  const char  * pValue;
  char          szParameter[PARAMETER_MAXLEN_CN90];
  int           nUser       = DOMAIN_CN50;

  // read parameters 
  if (nFuncReturn == OK_CN00) {
    cn90GetToken(command->args, szParameter, 1, PARAMETER_MAXLEN_CN90);
    if (strncmp(szParameter, USER_TYPE_CN50, strlen(USER_TYPE_CN50)) == 0) {
      pValue = strchr(szParameter, ASSIGN_CHAR_CN50);
      if (pValue != NULL) {
        pValue++;
        pCommand = pCommand + strlen(szParameter);
        if (strcmp(pValue, USERTYPE_DBM_CN50) == 0) {
          nUser = FIRSTDBM_CN50;
        } else if (strcmp(pValue, USERTYPE_DBA_CN50) == 0) {
          nUser = SYSDBA_CN50;
        } else if (strcmp(pValue, USERTYPE_SAP_CN50) == 0) {
          nUser = SAPUSR_CN50;
        } else if (strcmp(pValue, USERTYPE_DOM_CN50) == 0) {
          nUser = DOMAIN_CN50;
        } else {
          nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "unknown usertype");
        } // end if
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "missing usertype");
      } // end if
    } // end if
  } // end if

  cn50DBMUser usrUser (vcontrol->dbname, cn50DBMUser::getUser(vcontrol->dbname, nUser));

  if (usrUser.existsOnDisk()) {
    char szTemp [PARAMETER_MAXLEN_CN90] = "";

    // build SQLOPT
    sp77sprintf(szTemp, PARAMETER_MAXLEN_CN90, TXT_SQLOPT, vcontrol->dbname.asCharp(), 
                                                           usrUser.getUserName().asCharp(),
                                                           usrUser.getClearMasterPwd().asCharp());
    // set SQLOPT
    putenv(szTemp);

    // build command
    sp77sprintf(szTemp, PARAMETER_MAXLEN_CN90, TXT_CMD_XPU, pCommand);

    // execute command
    nFuncReturn = cn40ExecCommand(replyData, replyLen, replyLenMax, szTemp, szTemp, false, true);

  } else {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_NOUSER_CN00);
  } // end if

  return nFuncReturn;

} /* end cn40ExecXPU */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40LoadSysTab
 * ------------------------------------------------------------------
 */
tcn00_Error cn40LoadSysTab
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40LoadSysTab");

  tcn00_Error          nFuncReturn = OK_CN00;
  char                 szToken   [PARAMETER_MAXLEN_CN90];
  char                 szOptions [PARAMETER_MAXLEN_CN90];
  int                  nToken = 1;
  tcn00_UserNamec      szUsername;
  tsp00_Namec          szPassword;
  tsp00_Namec          szDomPwd;
  char               * pPassword;
  bool                 bMigrate = false;
  tsp00_KnlIdentifierc szTmp;
  szTmp.rawAssign(vcontrol->pCurrentUser->getUserName());

  if (cn90DBState(vcontrol->dbname) != STATE_ONLINE_CN00) {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_DBNORUN_CN00);
  } // end if

  szUsername.Init();
  szPassword.Init();
  szDomPwd.Init();

  while (cn90GetToken(command->args, szToken, nToken, PARAMETER_MAXLEN_CN90) && nFuncReturn == OK_CN00) {

    if (strcmp(szToken, OPT_LOAD_DBA) == 0) {
      // DBA found
      nToken++;
      if (cn90GetToken(command->args, szToken, nToken, PARAMETER_MAXLEN_CN90)) {
        /* search for password */
        pPassword = strchr (szToken, PWD_SEPARATOR_CN00);
        if (pPassword != NULL) {
          *pPassword = CHAR_STRINGTERM_CN90;
          ++pPassword;
          cn90Uncrypt(pPassword, false);
          szPassword.rawAssign(pPassword);
        } /* end if */
        szUsername.rawAssign(szToken);
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
      } // end if

    } else if (strcmp(szToken, OPT_LOAD_DOM) == 0) {

      // DOMAIN pwd found
      nToken++;
      if (cn90GetToken(command->args, szToken, nToken, PARAMETER_MAXLEN_CN90)) {
        cn90Uncrypt(szToken, false);
        szDomPwd.rawAssign(szToken);
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
      } // end if

    } else if (strcmp(szToken, OPT_LOAD_MIGRATE) == 0) {
      bMigrate = true;
    } else {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if

    nToken++;
  } // end while

  // dba management
  if (nFuncReturn == OK_CN00) {
    if (szUsername.length() == 0) {
      // load dba user
      cn50DBMUser         usrDBA    (vcontrol->dbname, cn50DBMUser::getSYSDBA(vcontrol->dbname) );

      szUsername = usrDBA.getUserName();
      szPassword = usrDBA.getClearMasterPwd();

      // check sysdba property
      nFuncReturn = ERR_DBAUNKNOWN_CN00;
      tin01_sql_session aSession;
      if (cn80ConnectSQL  (usrDBA, &aSession, replyData, replyLen) == OK_CN00) {
        tin110_SQLResultTable aTable(&aSession, SQL_CHECKSYSDBA);
        if (aTable.sqlRc() == cin01_db_ok) {
          nFuncReturn = OK_CN00;
        } // end if
        cn80ReleaseSQL  ( &aSession, false);
      } // end if
      nFuncReturn = cn90AnswerIError(replyData, replyLen, nFuncReturn);

    } else {
      cn50DBMUser  usrTempDBA(vcontrol->dbname);
      
      usrTempDBA.setUserName (szUsername)
                .setMasterPwd(szPassword);

      // check sysdba property
      nFuncReturn = ERR_DBAWRONG_CN00;
      tin01_sql_session aSession;
      if (cn80ConnectSQL  (usrTempDBA, &aSession, replyData, replyLen) == OK_CN00) {
        tin110_SQLResultTable aTable(&aSession, SQL_CHECKSYSDBA);
        if (aTable.sqlRc() == cin01_db_ok) {
          nFuncReturn = OK_CN00;
        } // end if
        cn80ReleaseSQL  ( &aSession, false);
      } // end if
      nFuncReturn = cn90AnswerIError(replyData, replyLen, nFuncReturn);

      if (nFuncReturn == OK_CN00) {
        // create dba user
        cn50DBMUser         usrOldDBA(vcontrol->dbname, cn50DBMUser::getSYSDBA(vcontrol->dbname));
        cn50DBMUser         usrNewDBA(vcontrol->dbname);

        usrNewDBA.setUserName ( szUsername)
                 .setSDBAUser ( )
                 .setMasterPwd( szPassword)
                 .setServerRights ( DBMMaskAll_CN50, DBMUserDefault_CN50 )
                 .setGUIRights    ( DBMMaskAll_CN50, DBMUserDefault_CN50 );

        if (usrOldDBA.existsOnDisk()) {
         usrNewDBA.setServerRights ( DBMMaskAll_CN50, usrOldDBA.getServerRights() )
                  .setGUIRights    ( DBMMaskAll_CN50, usrOldDBA.getGUIRights() );
        } // end if

        // delete old dba user
        usrOldDBA.setSDBAUser (false);
        usrOldDBA.deleteUsr();

        // save new dba user
        nFuncReturn = usrNewDBA.save();

        if (nFuncReturn != OK_CN00) {
          cn90AnswerIError(replyData, replyLen, nFuncReturn);
        } // end if
      } // end if
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00 && szUsername.length() == 0) {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_DBAUNKNOWN_CN00);
  } // end if

  // domain management
  cn50DBMUser       usrDom( vcontrol->dbname, USERNAME_DOMAIN_CN50);
  tin01_sql_session aSession;

  if (nFuncReturn == OK_CN00) {

    // set new password
    if (szDomPwd.length() != 0) {
      usrDom.setMasterPwd( szDomPwd);
    } else {
      if (usrDom.existsOnDisk()) {
        szDomPwd = usrDom.getClearMasterPwd();
      } else {
        teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_DOMPUNKNOWN_CN00_1);
        nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
      } // end if
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    // check user
    if (cn80ConnectSQL  (usrDom, &aSession, replyData, replyLen) != OK_CN00) {
      teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_DOMPWRONG_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
      // try to create user
      cn50DBMUser  usrDBA(vcontrol->dbname, cn50DBMUser::getSYSDBA(vcontrol->dbname));
      char         szCommand[200];
      sprintf(szCommand, "CREATE USER %s PASSWORD %s DBA NOT EXCLUSIVE", usrDom.getUserName().asCharp(), usrDom.getMasterPwd(true).asCharp() );
      if (OK_CN00 == cn80ExecuteSQL(usrDBA, szCommand)) {
        nFuncReturn = OK_CN00;
      } // end if
    } else {
      cn80ReleaseSQL  ( &aSession, false);
    } // end if

    // save user
    if (nFuncReturn == OK_CN00) {
      usrDom.setDOMAINUser();
      nFuncReturn = usrDom.save();
      if (nFuncReturn != OK_CN00) {
        cn90AnswerIError(replyData, replyLen, nFuncReturn);
      } // end if
    } // end if

  } // end if

  // lock the system tables
  DBMSrvKnl_Session oLockSession;
  if (nFuncReturn == OK_CN00) {
      // connect the lock session with the sysdba
      if (!oLockSession.NormalConnect(vcontrol->dbname.asCharp(),
                                      szUsername.asCharp(),
                                      szPassword.asCharp())) {
        nFuncReturn = cn90AnswerMessage(replyData, replyLen, oLockSession.LastMessage());
      } else {
          // check for lock table
          if (!oLockSession.Execute(SQL_DBANLOCK_CHECKTABLE)) {
              char szCommand[200];
              // create the "schema"
              // this may fail with error "-6006, duplicate name" -> ignore this error
              sprintf(szCommand, SQL_DBANLOCK_CREATESCHEMA, usrDom.getMasterPwd(true).asCharp() );
              oLockSession.Execute(szCommand);
              // reset the password maybe changed 
              sprintf(szCommand, SQL_DBANLOCK_GRANTSCHEMA, usrDom.getMasterPwd(true).asCharp() );
              if (!oLockSession.Execute(szCommand)) {
                  nFuncReturn = cn90AnswerMessage(replyData, replyLen, replyLenMax, oLockSession.LastMessage());
              } // end if

              // relase SYSDBA session  
              oLockSession.Release();

              // connect as sysdbana
              if ((nFuncReturn == OK_CN00) && !oLockSession.NormalConnect(vcontrol->dbname.asCharp(), "SYSDBANA", usrDom.getMasterPwd(true).asCharp())) {
                  nFuncReturn = cn90AnswerMessage(replyData, replyLen, oLockSession.LastMessage());
              } // end if
              // create table
              if ((nFuncReturn == OK_CN00) && !oLockSession.Execute(SQL_DBANLOCK_CREATETABLE)) {
                  nFuncReturn = cn90AnswerMessage(replyData, replyLen, replyLenMax, oLockSession.LastMessage());
              } // end if
              // grant rights
              if ((nFuncReturn == OK_CN00) && !oLockSession.Execute(SQL_DBANLOCK_CREATEGRANT)) {
                  nFuncReturn = cn90AnswerMessage(replyData, replyLen, replyLenMax, oLockSession.LastMessage());
              } // end if

              // relase SYSDBANA session  
              oLockSession.Release();

              // restore sysdba session
              if ((nFuncReturn == OK_CN00) && !oLockSession.NormalConnect(vcontrol->dbname.asCharp(), szUsername.asCharp(), szPassword.asCharp())) {
                nFuncReturn = cn90AnswerMessage(replyData, replyLen, oLockSession.LastMessage());
              } // end if
          } // end if
          // lock the table
          if ((nFuncReturn == OK_CN00) && !oLockSession.ExecuteWithoutCommit(SQL_DBANLOCK_LOCK)) {
              nFuncReturn = cn90AnswerMessage(replyData, replyLen, replyLenMax, oLockSession.LastMessage());
          } // end if
      } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {

    sp77sprintf(szOptions, PARAMETER_MAXLEN_CN90, "-dompwd %s %s %s", (char   *) szDomPwd, (bMigrate?OPT_LOAD_MIGRATE:""), LOAD_OPT);
    nFuncReturn = cn40_ExecPythonLoad(vcontrol,
                                      PYTHON_FILE,
                                      (char   *) szUsername,
                                      (char   *) szPassword,
                                      (char   *) szOptions,
                                      replyData,
                                      replyLen,
                                      replyLenMax);

    if (nFuncReturn == OK_CN00 || nFuncReturn == ERR_EXECUTE_CN00) {
      cn42BackupFile(vcontrol->dbname, FGET_REPMAN_CN42);

      cn80ExecuteUtil(vcontrol->dbname, LOAD_INIT);
      cn20SaveParamsInfoToDB(vcontrol->dbname);
    } // end if

  } // end if

  // unlock the system tables
  oLockSession.Release();

  return nFuncReturn;
} // end cn40LoadSysTab

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40LoadR3Tab
 * ------------------------------------------------------------------
 */
tcn00_Error cn40LoadR3Tab
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error          nFuncReturn = OK_CN00;
  char                 szUsername [PARAMETER_MAXLEN_CN90] = "";
  char                 szPassword [PARAMETER_MAXLEN_CN90] = "";
  tcn002_XpValueString szValue;
  char                 szOptions [PARAMETER_MAXLEN_CN90];

  // dba management
  cn50DBMUser         usrDBA    ( vcontrol->dbname, cn50DBMUser::getSYSDBA(vcontrol->dbname));

  if (!usrDBA.existsOnDisk()) {
    nFuncReturn = ERR_USRREAD_CN00;
  } else {
    SAPDB_strcpy(szUsername, usrDBA.getUserName());
    cn90CalculateUncrypt(usrDBA.getMasterPwd(), szPassword, false);
  } // end if

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn20XParamGetValue(vcontrol->dbname,
                                     PAN_RUNDIR,
                                     szValue);
  } // end if

  if (nFuncReturn == OK_CN00) {
      sp77sprintf(szOptions, PARAMETER_MAXLEN_CN90, "-fdir %s", szValue.asCharp());
      nFuncReturn = cn40_ExecPythonLoad(vcontrol,
                                        PYR3_FILE,
                                        (char   *) szUsername,
                                        (char   *) szPassword,
                                        (char   *) szOptions,
                                        replyData,
                                        replyLen,
                                        replyLenMax);

    cn20SaveParamsInfoToDB(vcontrol->dbname);
  } else {
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } // end if

  return nFuncReturn;
} // end cn40LoadR3Tab

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40LoadLcApps
 * ------------------------------------------------------------------
 */
tcn00_Error cn40LoadLcApps
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40LoadLcApps");

  tcn00_Error          nFuncReturn = OK_CN00;
  char                 szSAPUsername [PARAMETER_MAXLEN_CN90] = "";

  cn50DBMUser oDBAUser   (vcontrol->dbname, cn50DBMUser::getSYSDBA  (vcontrol->dbname));
  if (nFuncReturn == OK_CN00) {
    if (oDBAUser.lastEvent()) {
      teo200_EventList aEvent(oDBAUser.lastEvent(), FUNCTION_NAME_MCN00_1, ERR_DBAUNKNOWN_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    } // end if
  } // end if

  char szOptions[PARAMETER_MAXLEN_CN90];

  if (nFuncReturn == OK_CN00) {
    if (cn90GetToken(command->args, szSAPUsername, 1, PARAMETER_MAXLEN_CN90)) {
      char              * pPassword   = NULL; 
      tcn00_UserNamec     szUser;
      tsp00_Namec         szPassword;

      pPassword = strchr(szSAPUsername, PWD_SEPARATOR_CN00);
      if (pPassword != NULL) {
        *pPassword = CHAR_STRINGTERM_CN90;
        pPassword++;
        cn90Uncrypt(pPassword, false);
        szUser.rawAssign(szSAPUsername);
        szPassword.rawAssign(pPassword);
        
        sp77sprintf(szOptions, PARAMETER_MAXLEN_CN90, "-usap %s,%s", szUser.asCharp(), szPassword.asCharp());
          
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "invalid user specification");
      } // end if
    } else {
      cn50DBMUser oldSapUser(vcontrol->dbname, cn50DBMUser::getSAPUser(vcontrol->dbname));
      if (!oldSapUser.lastEvent().IsEmpty()) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 0, "SAP user not found");
      } else {
        sp77sprintf(szOptions, PARAMETER_MAXLEN_CN90, "-usap %s,%s", oldSapUser.getUserName().asCharp(), oldSapUser.getClearMasterPwd().asCharp());
      } // end if
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn40_ExecPythonLoad(vcontrol,
                                      LCAPPS_FILE,
                                      oDBAUser.getUserName(),
                                      oDBAUser.getClearMasterPwd(),
                                      szOptions,
                                      replyData,
                                      replyLen,
                                      replyLenMax);
  } // end if

  return nFuncReturn;
} // end cn40LoadLcApps

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40LoadTutorial
 * ------------------------------------------------------------------
 */
tcn00_Error cn40LoadTutorial
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40LoadTutotial");

  tcn00_Error          nFuncReturn = OK_CN00;

  cn50DBMUser oDBAUser   (vcontrol->dbname, cn50DBMUser::getSYSDBA  (vcontrol->dbname));
  if (nFuncReturn == OK_CN00) {
    if (oDBAUser.lastEvent()) {
      teo200_EventList aEvent(oDBAUser.lastEvent(), FUNCTION_NAME_MCN00_1, ERR_DBAUNKNOWN_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn40_ExecPythonLoad(vcontrol,
                                      TUTORIAL_FILE,
                                      oDBAUser.getUserName(),
                                      oDBAUser.getClearMasterPwd(),
                                      "",
                                      replyData,
                                      replyLen,
                                      replyLenMax);
  } // end if

  return nFuncReturn;
} // end cn40LoadTutorial

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40ExecXKernprot
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ExecXKernprot
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error     nFuncReturn = OK_CN00;
  tsp00_C256      szDir;
  char            szOptions   [PARAMETER_MAXLEN_CN90] = "";
  char            szCommand   [PARAMETER_MAXLEN_CN90] = "";

  if (!cn90GetToken(command->args, szOptions, 1, PARAMETER_MAXLEN_CN90)) {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
  }

  if (nFuncReturn == OK_CN00) {

    cn90GetVersionBinPath(szDir);

#ifdef _WIN32
    sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, "\"\"%sxkernprot\" -d %s %s\"", (char *) szDir, &vcontrol->dbname[0], szOptions);
#else
    sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, "%sxkernprot -d %s %s", (char *) szDir, &vcontrol->dbname[0], szOptions);
#endif

    // change to rundir
    tcn002_XpValueString szRunDir;
    tsp01_RteError  rteError;

    nFuncReturn = cn20XParamGetValue(vcontrol->dbname, PAN_RUNDIR, szRunDir);
    if (nFuncReturn == OK_CN00) {
      if (sqlchdirc(szRunDir.asCharp(), &rteError)) {

        nFuncReturn = cn40ExecCommand(replyData, replyLen, replyLenMax, szCommand, szCommand, false, true);

        sqlchdirc(vcontrol->dbroot.asCharp(), &rteError);
      } else {
        nFuncReturn = cn90AnswerNewRTEError(replyData, replyLen, ERR_RTEEXT_CN00, &rteError);
      } // end if
    } else {
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } // end if

  } // end if

  return nFuncReturn;
} /* end cn40ExecXKernprot */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40GetVersion
 * ------------------------------------------------------------------
 */
tcn00_Error cn40GetVersion
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Os              osNumber;
  char                osString [100];
  char                vsString [100];
  int                 nSwap;
  union
  {
    tsp00_Int4                      i4 ;
    tsp00_C4                        c4 ;
  } uMap;

  uMap.i4 = 65536;
  for ( nSwap = 0 ; nSwap < 4 ; nSwap ++ ) {
    if ( uMap.c4[nSwap] == 1 ) {
      break;
    } /* end if */
  } /* end for */

  tsp100_VersionID0   VersionID0;

  sp100_GetVersionID ( VersionIDType0_esp100, s100buildnumberEx, &VersionID0 );

  sp77sprintf(vsString, 100, "%d.%d.%d",
                    (int) VersionID0.MajorVersion_sp100,
                    (int) VersionID0.MinorVersion_sp100,
                    (int) VersionID0.CorrLevel_sp100);

  sqlos (&osNumber);

  switch (osNumber) {
    case os_unix:
      SAPDB_strcpy (osString, "UNIX");
      break;
    case os_vms:
      SAPDB_strcpy (osString, "VMS");
      break;
    case os_windows:
      SAPDB_strcpy (osString, "WINDOWS");
      break;
    case os_win32:
      SAPDB_strcpy (osString, "WIN32");
      break;
    case os_os2:
      SAPDB_strcpy (osString, "OS2");
      break;
    default:
      sp77sprintf (osString, 100, "<Unknown OS %d>", (int) osNumber);
      break;
  } /* end switch */

  sp77sprintf(replyData, replyLenMax, "%s%s%s%s\"%s\",\"%s\",\"%s\",%s,%s,%d%s",
                     ANSWER_OK_CN00,
                     LINE_SEPSTRING_CN00,
                     "version,os,dbroot,logon,code,swap",
                     LINE_SEPSTRING_CN00,
                     vsString,
                     osString,
                     (char *) vcontrol->dbroot,
                     BOOLSTR_CN00(vcontrol->bIsSAPDBAdmi),
                     (' ' == 32) ? "ASCII" : "EBCDIC",
                     nSwap,
                     LINE_SEPSTRING_CN00);

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* end cn40GetVersion */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBMGetPath
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBMGetPath
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szMode[PARAMETER_MAXLEN_CN90];
  tsp00_Pathc         szPath;
  tsp01_RteError      RteError;
  tsp00_Bool          bDBRootWarning = false;

  cn90GetToken(command->args, szMode, 1, PARAMETER_MAXLEN_CN90);

  if (stricmp(szMode, RTE_INDPROG) == 0) {
    if (!sqlGetIndependentProgramsPath ( szPath, 0, &RteError)) {
      nFuncReturn = cn90AnswerNewRTEError(replyData, replyLen, ERR_RTEEXT_CN00, &RteError);
    } // end if
    bDBRootWarning = !sqlIsIndependentProgramsPathInRegistry();
  } else if (stricmp(szMode, RTE_INDDATA) == 0) {
    if (!sqlGetIndependentDataPath ( szPath, 0, &RteError)) {
      nFuncReturn = cn90AnswerNewRTEError(replyData, replyLen, ERR_RTEEXT_CN00, &RteError);
    } // end if
    bDBRootWarning = !sqlIsIndependentDataPathInRegistry();
  } else {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
  } // end if

  if (nFuncReturn == OK_CN00) {
    sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s", 
                        ANSWER_OK_CN00, 
                        LINE_SEPSTRING_CN00,
                        szPath.asCharp(),
                        LINE_SEPSTRING_CN00,
                        bDBRootWarning ? "INFO: Path extracted from $DBROOT" : "",
                        bDBRootWarning ? LINE_SEPSTRING_CN00 : "");

    *replyLen = (int)strlen(replyData);
  } /* end if */

  return nFuncReturn;
} /* end cn40DBMGetPath */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBMSetPath
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBMSetPath
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szMode[PARAMETER_MAXLEN_CN90];
  tsp00_Pathc         szPath;
  tsp01_RteError      RteError;

  cn90GetToken(command->args, szMode, 1, PARAMETER_MAXLEN_CN90);
  cn90GetToken(command->args, szPath, 2, szPath.size()+1);
  cn90StripQuotes(szPath);

  if (stricmp(szMode, RTE_INDPROG) == 0) {
    if (!sqlSetIndependentProgramsPath ( szPath, &RteError)) {
      nFuncReturn = cn90AnswerNewRTEError(replyData, replyLen, ERR_RTEEXT_CN00, &RteError);
    } // end if
  } else if (stricmp(szMode, RTE_INDDATA) == 0) {
    if (!sqlSetIndependentDataPath ( szPath, &RteError)) {
      nFuncReturn = cn90AnswerNewRTEError(replyData, replyLen, ERR_RTEEXT_CN00, &RteError);
    } // end if
  } else {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } /* end if */

  return nFuncReturn;
} /* end cn40DBMSetPath */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBCreate
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBCreate
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40DBCreate");

  tcn00_Error         nFuncReturn = OK_CN00;
  char                szToken    [PARAMETER_MAXLEN_CN90] = "";
  int                 nIndex      = 1;

  SAPDB_Bool          bRegistered  = false;

  SAPDB_Bool          bAutostart  = false;
  SAPDB_Bool          bAddUser    = false;
  SAPDB_Bool          bAddGroup   = false;
  SAPDB_Bool          bOsLogin    = false;

  tsp00_DbNamec       szDBName;

  tcn00_UserNamec     szUser;
  tsp00_Namec         szPassword;

  tcn00_UserNamec     szOsUser;
  tsp00_Namec         szOsPassword;

  tsp00_Namec         szGroup;

  // read parameters, option and values
  while (nFuncReturn == OK_CN00) {
    if (!cn90GetToken(command->args, szToken, nIndex, PARAMETER_MAXLEN_CN90)) {
      break;
    } // end if
    // autostart option    
    if (strcmp(szToken, OPT_OPT_AUTO) == 0 || strcmp(szToken, OPTS_OPT_AUTO) == 0) {
#ifdef _WIN32
      bAutostart = true;
#endif
    // group service user    
    } else if (strcmp(szToken, OPT_OPT_USER) == 0 || strcmp(szToken, OPTS_OPT_USER) == 0) {
#ifdef _WIN32
      bAddUser = true;
#endif
    // group option    
    } else if (strcmp(szToken, OPT_OPT_GROUP) == 0 || strcmp(szToken, OPTS_OPT_GROUP) == 0) {
      if (!cn90GetToken(command->args, szToken, ++nIndex, PARAMETER_MAXLEN_CN90)) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 1, "Missing group name");
      } else {
        bAddGroup = true;
        szGroup.rawAssign(szToken);
      } // end if
    } else {
      // database name
      szDBName.rawAssign(szToken);
      cn90StrUpperCopy(szDBName, szDBName, false);
      break;
    } // end if
    ++nIndex;
  } // end while    

  // first database manager operator
  if (nFuncReturn == OK_CN00) {
    if (!cn90GetToken(command->args, szToken, ++nIndex, PARAMETER_MAXLEN_CN90)) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 1, "Missing first Database Manager Operator");
    } else {
      char * pPassword = strchr(szToken, PWD_SEPARATOR_CN00);
      if (pPassword != NULL) {
        *pPassword = CHAR_STRINGTERM_CN90;
        pPassword++;
        szUser.rawAssign(szToken);
        szPassword.rawAssign(pPassword);
        cn90Uncrypt(szPassword, false);
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 1 , "Invalid first Database Manager Operator");
      } // end if
    } // end if
  } // end if

  // operating system user
  if (nFuncReturn == OK_CN00) {
    if (cn90GetToken(command->args, szToken, ++nIndex, PARAMETER_MAXLEN_CN90)) {
      char * pPassword = strchr(szToken, PWD_SEPARATOR_CN00);
      if (pPassword != NULL) {
        *pPassword = CHAR_STRINGTERM_CN90;
        pPassword++;
        szOsUser.rawAssign(szToken);
        szOsPassword.rawAssign(pPassword);
        cn90Uncrypt(szOsPassword, false);
        bOsLogin = true;
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 1 , "Invalid operating system user");
      } // end if
    } // end if
    if (bAddUser && !bOsLogin && (nFuncReturn == OK_CN00)) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00, 1 , "Missing operating system user");
    } // end if
  } // end if

  // check dbname
  if (nFuncReturn == OK_CN00) {
    if ((strncmp(szDBName, SERVICE_PARAMFILE_ID_OLD_CN90, strlen(SERVICE_PARAMFILE_ID_OLD_CN90)) == 0) ||
        (strncmp(szDBName, SERVICE_PARAMFILE_ID_CN90,     strlen(SERVICE_PARAMFILE_ID_CN90    )) == 0) ||
        (strncmp(szDBName, "-",                           strlen("-"                          )) == 0) ||
        (strlen(szDBName) > MAX_DBNAME                                                               )    ) {
      teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_INVDBNAME_CN00_1, szDBName.asCharp());
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    } else {
      for (nIndex = 0; szDBName[nIndex] != 0; ++nIndex) {
        nFuncReturn = (((unsigned char) szDBName[nIndex]) < 128) ?  nFuncReturn : cn90AnswerIError(replyData, replyLen, ERR_ASCII_CN00, 1, "Invalid database name");
      } // end for
    } // end if
  } // end if

  // check existence of database
  if (nFuncReturn == OK_CN00) {
    if (cn90DBExists(szDBName)) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_DBEXIST_CN00);
    } // end if
  } // end if

  // check first dbm operator
  if (nFuncReturn == OK_CN00) {
    if (strnicmp(szUser, INVALID_USER_CN50, strlen(INVALID_USER_CN50)) == 0) {
      teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_INVUSRNAME_CN00_1, szUser.asCharp());
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    } else {
      // check 7-Bit ASCII
      for (nIndex = 0; szUser[nIndex] != 0; ++nIndex) {
        nFuncReturn = (((unsigned char) szUser[nIndex]) < 128) ?  nFuncReturn : cn90AnswerIError(replyData, replyLen, ERR_ASCII_CN00, 1, "Invalid First Database Manager Operator");
      } // end for
      // check 7-Bit ASCII
      for (nIndex = 0; szPassword[nIndex] != 0; ++nIndex) {
        nFuncReturn = (((unsigned char) szUser[nIndex]) < 128) ?  nFuncReturn : cn90AnswerIError(replyData, replyLen, ERR_ASCII_CN00, 1, "Invalid First Database Manager Operator");
      } // end for
    } // end if
  } // end if

  // os logon
  if ((nFuncReturn == OK_CN00) && bOsLogin && !vcontrol->bIsSAPDBAdmi) {
#ifndef _WIN32      
    SAPDBErr_MessageList oMsg;
    oMsg.ClearMessageList();
    if (RTE_VerifyUserPasswordCombination(szOsUser, szOsPassword, oMsg)) {
      vcontrol->bIsSAPDBAdmi = RTE_VerifyUserAsSapdbAdministrator (szOsUser, oMsg);
    } else {
      nFuncReturn = cn90AnswerMessage(replyData, replyLen, ERR_NEEDADMI_CN00, oMsg);
    } // end if
#else
    tsp9_rte_xerror     xError;
    sqlxlogon (szOsUser, szOsPassword, &xError);
    if (xError.xe_result != 0) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_SYSLOGON_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
    } else {
      vcontrol->bIsSAPDBAdmi = true;
    } // end if
#endif
  } // end if

  // check logon state
  if (nFuncReturn == OK_CN00 && !vcontrol->bIsSAPDBAdmi) {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_NEEDADMI_CN00);
  } // end if

  // register database
  if (nFuncReturn == OK_CN00) {

    SAPDBErr_MessageList err;        

    RTE_ActiveInstallation * activeInstallation = (RTE_DBRegister::Instance()).GetActiveInstallationByDBRoot(vcontrol->dbroot,err);
    if (!bAddUser) {
      activeInstallation->RegisterDatabase(szDBName, bAutostart, NULL, NULL, err);
    } else {
      activeInstallation->RegisterDatabase(szDBName, bAutostart, szOsUser, szOsPassword, err);
    } // end if
    delete activeInstallation;

    if (SAPDBErr_MessageList::Error == err.Type()) {
      nFuncReturn = cn90AnswerMessage(replyData, replyLen, ERR_RTE_CN00, err);
    } else {
      bRegistered = true;
    } // end if
  } // end if

  // create DBM-User
  if (nFuncReturn == OK_CN00) {
    vcontrol->pCurrentUser->clear();
    vcontrol->pCurrentUser->setDBName       ( szDBName    )
                           .setUserName     ( szUser      )
                           .setMasterPwd    ( szPassword  )
                           .setServerRights ( DBMMaskAll_CN50, DBMUserDefault_CN50 )
                           .setGUIRights    ( DBMMaskAll_CN50, DBMUserDefaultGUI_CN50 )
                           .setColdUser     ( );

    nFuncReturn = vcontrol->pCurrentUser->save(true);
    if ((nFuncReturn == OK_CN00) && bAddGroup) {
      vcontrol->pCurrentUser->setSupportGroup(szGroup);
    } // end if
    if (nFuncReturn == OK_CN00) {
      vcontrol->pCurrentUser->checkMasterPwd(szPassword);
    } else {
      cn90AnswerEvent(replyData, replyLen, vcontrol->pCurrentUser->lastEvent());
    } // end if
  } // end if

  // generate answer
  if (nFuncReturn == OK_CN00) {
    vcontrol->dbname = szDBName;
    vcontrol->pHSSNodes->SetConnectionData(szDBName.asCharp(), szUser.asCharp(), szPassword.asCharp());
    cn90AnswerOK (replyData, replyLen, NULL);
  } else {
    if (bRegistered) {
      SAPDBErr_MessageList err;        
      RTE_ActiveInstallation * activeInstallation = (RTE_DBRegister::Instance()).GetActiveInstallationByDBName(szDBName,err);
      activeInstallation->UnregisterDatabase(szDBName,err);
      delete activeInstallation;
    } // end if
    vcontrol->pCurrentUser->clear();
  } // end if

  return nFuncReturn;
} /* end cn40DBCreate */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBDrop
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBDrop
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error          nFuncReturn = OK_CN00;
  char                 szToken    [PARAMETER_MAXLEN_CN90];
  bool                 bWithFiles = true;

  if (cn90GetToken(command->args, szToken, 1, PARAMETER_MAXLEN_CN90)) {
    if (stricmp(szToken, KEYDROP_WITHOUTFILES) == 0) {
      bWithFiles = false;
    } else {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn40_DBDrop(vcontrol->dbname, vcontrol->dbroot, bWithFiles, !vcontrol->pHSSNodes->Exists(RTE_ISystem::Instance().GetLocalNodeName()), replyData, replyLen, replyLenMax);
  } // end if

  return nFuncReturn;
} // end cn40DBDrop

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_StartEventDispatcher
 * ------------------------------------------------------------------
 */
tcn00_Error cn40_StartEventDispatcher
      ( VControlDataT * vcontrol )
{
  tcn00_Error nFuncReturn = OK_CN00;
  cn50DBMUser oDBMUser   (vcontrol->dbname, cn50DBMUser::getColdUser(vcontrol->dbname));

  DBMSrvProc_ArgumentList theArgList;
  char upwdBuffer[256];

  // build command line
  theArgList.AddArgument("-d");
  theArgList.AddArgument(vcontrol->dbname.asCharp());
  theArgList.AddArgument("-u");
  sprintf(upwdBuffer, "%s,%s", oDBMUser.getUserName().asCharp(), oDBMUser.getClearMasterPwd().asCharp());
  theArgList.AddArgument(upwdBuffer);

  DBMSrvProc_ServerProcess oProcess(
    DBMSrvProc_ServerProcessCommandLineConverter::KeyEventDispatcherProgram,
    theArgList);
  if(!oProcess.started() ) {
    nFuncReturn = ERR_EXECUTE_CN00;
  } // end if

//  // start event dispatcher
//  char            szCommand [PARAMETER_MAXLEN_CN90];
//  sprintf(szCommand, TXT_CMD_DBMEXT, vcontrol->dbname.asCharp(), oDBMUser.getUserName().asCharp(), oDBMUser.getClearMasterPwd().asCharp());
//  nFuncReturn = cn40ExecCommand(replyData, &replyLen, 1000, szCommand, szCommand, true, false);

  return nFuncReturn;
} /* end cn40_StartEventDispatcher */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_DBDrop
 * ------------------------------------------------------------------
 */
static tcn00_Error cn40_DBDrop
      (       tsp00_DbNamec   szDbName,
        const tsp00_Pathc     szDbRoot,
        const bool            bWithFiles,
        const bool            bDeleteLog,
        char                * replyData,
        int                 * replyLen,
        const int             replyLenMax)
{
  tcn00_Error          nFuncReturn = OK_CN00;
  tcn00_Error          nTmpState = OK_CN00;
  tsp9_rte_xerror      xError;
  tcn00_DevspaceParams aParamTable[] = XP_DEVSPACE_PARAMS_CN00;
  int                  nParam     = 0;
  int                  nNumber    = 0;
  tsp00_XpKeyTypec     szParameter;
  tcn002_XpValueString szDevFile;
  tcn002_XpValueString szDevType;
  tcn002_XpValueString szRunDir;
  tsp05_RteFileError   fileErr;
  tsp01_RteError       rteError;
  tcn00_DBState        aState;

  if (nFuncReturn == OK_CN00) {

    aState = cn90DBState(szDbName);
    if (aState == STATE_ERROR_CN00) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_STATE_CN00);
    } else if (aState != STATE_OFFLINE_CN00) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_DBRUN_CN00);
    } else {
      sqlxclear( szDbName, szDbRoot, &xError );

//      sqlxunregisterdb (szDbName, csp9_any_pgm, &xError);

      SAPDBErr_MessageList err;        
      RTE_ActiveInstallation * activeInstallation = (RTE_DBRegister::Instance()).GetActiveInstallationByDBName(szDbName,err);

      if(!activeInstallation->UnregisterDatabase(szDbName,err))
      {
//        error!
      }
      delete activeInstallation;
      if(SAPDBErr_MessageList::Error == err.Type()){
        nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, (char *)err.Message(), sizeof((char *)err.Message()), csp9_xrte_notok);
      } else if (bWithFiles) {

        // -- devspaces
        // change to rundir
        nTmpState = cn20XParamGetValue(szDbName, PAN_RUNDIR, szRunDir);
        if (sqlchdirc((char *) szRunDir, &rteError)) {

          // iterate trough devspacetypes
          nParam = 0;
          while (aParamTable[nParam].nDevSpace != XPDevSpaceUnknown_ecn00) {
            nNumber = 0;

            if (bDeleteLog || (aParamTable[nParam].nDevSpace != XPDevSpaceLog_ecn00)) {
    
              // iterate to devspaces of one type
              do {
                nNumber++;

                // look for devicename
                sp77sprintf(szParameter, szParameter.size(), aParamTable[nParam].szName, nNumber);
                nTmpState = cn20XParamGetValue(szDbName, szParameter, szDevFile);

                if (nTmpState == OK_CN00) {
                  // look for devicetype
                  sp77sprintf(szParameter, szParameter.size(), aParamTable[nParam].szType, nNumber);
                  nTmpState = cn20XParamGetValue(szDbName, szParameter, szDevType);

                  // delete device
                  if (nTmpState == OK_CN00) {
                    if (szDevType[0] == 'F') {
                      sqlferasec(szDevFile, &fileErr);
                    } // end if
                  } // end if
                } // end if

              } while (nTmpState == OK_CN00);

            } // end if

            nParam++;
          } // end while

          sqlchdirc(szDbRoot.asCharp(), &rteError);
        } // end if

        // -- all other file
        cn42RemoveFiles(szDbName);

        // -- remove all Crash-Histories
        tcn002_XpValueString  szTmp;

        nTmpState = cn20XParamGetValue(szDbName, PAN_CRASH_HISTORY_PATH, szTmp);
        if (nTmpState == OK_CN00) {
            tsp00_Pathc szCrashHistoryPath;
            szCrashHistoryPath.rawAssign(szTmp.asCharp());
            RTEDiag_DropAllCrashHist (szDbName.asCharp(), szCrashHistoryPath.asCharp());
        } //end if

        // -- xparam
        sqlXParamRemoveAll(szDbName, &rteError);

        // -- user profile
        teo200_EventList        EventList;
        teo28_ProfileContainer  Profile(szDbName, &EventList);
        if (!EventList) {
          Profile.eo28_DeleteProfileContainer(&EventList);
        } // end if

        // -- rundir
        if (sqlchdirc((char *) szRunDir, &rteError)) {
          sqlremove_empty_dirc( "dbahist", &rteError);
          sqlremove_empty_dirc( "rtedump_dir", &rteError);
          sqlchdirc(szDbRoot.asCharp(), &rteError);
        } // end if
        sqlremove_empty_dirc(szRunDir, &rteError);

      } // end if
    } // end if
  } // end if

  // generate answer
  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if

  return nFuncReturn;
} /* end cn40_DBDrop */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBEnum
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBEnum
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp9_rte_xerror     xError;
  void              * hEnum;
  tsp9_rte_dbinfo     dbInfo;
  char              * pCurrPos;
  const char        * szMode;
  char                szState[20];
  char                szOption[PARAMETER_MAXLEN_CN90];
  bool                bService = false;

  if (cn90GetToken(command->args, szOption, 1, PARAMETER_MAXLEN_CN90)) {
    if (stricmp(szOption, OPTS_ENUM_SRV) == 0) {
      bService = true;
    } else {
      nFuncReturn = cn90AnswerIError (replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  sqlxopen_db_enum (&hEnum, true, &xError);

  if (xError.xe_result == csp9_xrte_ok) {
    /* Init Output */
    sp77sprintf(replyData, replyLenMax, "%s%s", ANSWER_OK_CN00, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen (replyData);

    while (xError.xe_result == csp9_xrte_ok) {
      sqlxnext_db (hEnum, &dbInfo, &xError);
      if (xError.xe_result == csp9_xrte_ok) {

        switch (dbInfo.pgmKind) {
          case csp9_fast_pgm:
            szMode = TXTL_SPEED_FAST;
            break;
          case csp9_slow_pgm:
            szMode = TXTL_SPEED_SLOW;
            break;
          case csp9_quick_pgm:
            szMode = TXTL_SPEED_QUICK;
            break;
          case csp9_test_pgm:
            szMode = TXTL_SPEED_TEST;
            break;
          default:
            szMode = "";
            break;
        } /* end switch */

        switch (dbInfo.state) {
          case csp9_state_off:
            SAPDB_strcpy(szState, TXT_STATE_OFFLINE_CN00);
            break;
          case csp9_state_running:
            SAPDB_strcpy(szState, TXT_STATE_RUNNING_CN00);
            break;
          case csp9_state_ruin:
            SAPDB_strcpy(szState, TXT_STATE_RUIN_CN00);
            break;
          default:
            SAPDB_strcpy(szState, TXT_STATE_UNKNOWN_CN00);
            break;
        } /* end switch */

        char * pState = &szState[0];
        while (*pState != 0) {
          *pState = tolower(*pState);
          ++pState;
        } // end if

        if ( (strncmp(dbInfo.dbname, SERVICE_PARAMFILE_ID_OLD_CN90, strlen(SERVICE_PARAMFILE_ID_OLD_CN90)) == 0 && bService) ||
             (strncmp(dbInfo.dbname, SERVICE_PARAMFILE_ID_CN90,     strlen(SERVICE_PARAMFILE_ID_CN90    )) == 0 && bService) ||
             ( (strncmp(dbInfo.dbname, SERVICE_PARAMFILE_ID_OLD_CN90, strlen(SERVICE_PARAMFILE_ID_OLD_CN90)) != 0     ) &&
               (strncmp(dbInfo.dbname, SERVICE_PARAMFILE_ID_CN90,     strlen(SERVICE_PARAMFILE_ID_CN90    )) != 0     )    )    ) {
          sp77sprintf (pCurrPos, replyLenMax - (int)(pCurrPos - replyData), "%s%s%s%s%d.%d.%d.%d%s%s%s%s%s",
                             (char *) dbInfo.dbname,
                             VALUE_SEPSTRING_CN00,
                             (char *) dbInfo.dbroot,
                             VALUE_SEPSTRING_CN00,
                             (dbInfo.version.no[0] != csp9_invalid_version) ? dbInfo.version.no[0] : 0,
                             (dbInfo.version.no[1] != csp9_invalid_version) ? dbInfo.version.no[1] : 0,
                             (dbInfo.version.no[2] != csp9_invalid_version) ? dbInfo.version.no[2] : 0,
                             (dbInfo.version.no[3] != csp9_invalid_version) ? dbInfo.version.no[3] : 0,
                             VALUE_SEPSTRING_CN00,
                             szMode,
                             VALUE_SEPSTRING_CN00,
                             szState,
                             LINE_SEPSTRING_CN00);
        } // end if

        pCurrPos = pCurrPos + strlen (pCurrPos);
      } /* end if */
    } /* end while */

    if (xError.xe_result != csp9_xrte_atend) {
      nFuncReturn = ERR_RTE_CN00;
      cn90AnswerRTEError (replyData, replyLen, nFuncReturn, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
    } /* end if */

    sqlxclose_db_enum (hEnum);
  } else {
    nFuncReturn = ERR_RTE_CN00;
    cn90AnswerRTEError (replyData, replyLen, nFuncReturn, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
  } /* end if */

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* end cn40DBEnum */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBClear
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBClear
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp9_rte_xerror     xError;

  sqlxclear( vcontrol->dbname, vcontrol->dbroot, &xError );

  if (xError.xe_result != csp9_xrte_ok) {
    nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
  } else {
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if

  return nFuncReturn;

} /* end cn40DBClear */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBStart
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBStart
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn40_ChangeDBState ( vcontrol,
                              command,
                              replyData,
                              replyLen,
                              replyLenMax,
                              STATE_ADMIN_CN00);
} /* end cn40DBStart */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBStop
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBStop
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn40_ChangeDBState ( vcontrol,
                              command,
                              replyData,
                              replyLen,
                              replyLenMax,
                              STATE_OFFLINE_CN00,
                              true);

} /* end cn40DBStop */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBWarm
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBWarm
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn40_ChangeDBState ( vcontrol,
                              command,
                              replyData,
                              replyLen,
                              replyLenMax,
                              STATE_ONLINE_CN00);

} /* end cn40DBWarm */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBOffline
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBOffline
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn40_ChangeDBState ( vcontrol,
                              command,
                              replyData,
                              replyLen,
                              replyLenMax,
                              STATE_OFFLINE_CN00);

} /* end cn40DBOffline */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBCold
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBCold
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error     nFuncReturn = OK_CN00;
  tsp9_pgm_kind   pgmKind;
  bool            bDump;
  bool            bCluster = false;
  char            szNewArgs [PARAMETER_MAXLEN_CN90] = "";
  char            szRestart [PARAMETER_MAXLEN_CN90] = "";

  // check current and requested speed
  if (cn40_StartStopOptions(command->args, pgmKind, bDump, szRestart, bCluster) == OK_CN00) {
    if (pgmKind == csp9_any_pgm) {
      pgmKind = cn90DBSpeed(vcontrol->dbname);

      switch (pgmKind) {
        case csp9_slow_pgm:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s %s", (char   *) command->args, (char   *) OPT_SPEED_SLOW);
          break;
        case csp9_quick_pgm:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s %s", (char   *) command->args, (char   *) OPT_SPEED_QUICK);
          break;
        case csp9_fast_pgm:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s %s", (char   *) command->args, (char   *) OPT_SPEED_FAST);
          break;
        case csp9_test_pgm:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s %s", (char   *) command->args, (char   *) OPT_SPEED_TEST);
          break;
        default:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s", (char   *) command->args);
          break;
      } // end switch

      command->args = &szNewArgs[0];
    } // end if
  }

  return cn40_ChangeDBState ( vcontrol,
                              command,
                              replyData,
                              replyLen,
                              replyLenMax,
                              STATE_ADMIN_CN00);
} /* end cn40DBCold */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBRestart
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBRestart
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error     nFuncReturn = OK_CN00;
  tsp9_pgm_kind   pgmKind;
  bool            bDump;
  bool            bCluster = false;
  char            szNewArgs [PARAMETER_MAXLEN_CN90] = "";
  char            szRestart [PARAMETER_MAXLEN_CN90] = "";

  // check current and requested speed
  if (cn40_StartStopOptions(command->args, pgmKind, bDump, szRestart, bCluster) == OK_CN00) {
    if (pgmKind == csp9_any_pgm) {
      pgmKind = cn90DBSpeed(vcontrol->dbname);

      switch (pgmKind) {
        case csp9_slow_pgm:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s %s", (char   *) command->args, (char   *) OPT_SPEED_SLOW);
          break;
        case csp9_quick_pgm:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s %s", (char   *) command->args, (char   *) OPT_SPEED_QUICK);
          break;
        case csp9_fast_pgm:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s %s", (char   *) command->args, (char   *) OPT_SPEED_FAST);
          break;
        default:
          sp77sprintf (szNewArgs, PARAMETER_MAXLEN_CN90, "%s", (char   *) command->args);
          break;
      } // end switch

      command->args = &szNewArgs[0];
    } // end if
  }

  nFuncReturn = cn40_ChangeDBState ( vcontrol,
                                     command,
                                     replyData,
                                     replyLen,
                                     replyLenMax,
                                     STATE_OFFLINE_CN00);
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn40_ChangeDBState ( vcontrol,
                                       command,
                                       replyData,
                                       replyLen,
                                       replyLenMax,
                                       STATE_ONLINE_CN00);
  } // end if

  return nFuncReturn;
} /* end cn40DBRestart */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40ShowSomething
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ShowSomething
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
FUNCTION_DBG_MCN00_1("cn40ShowSomething");
  tcn00_Error    nFuncReturn = OK_CN00;

  char         * pCurrent  = replyData;
  char         * pContinue = NULL;
  bool           bNoNewLine;
  tsp00_Bool     bOk;
  tsp00_Int4     nExitCode;
  tsp00_Int4     nSize;
  ceo43_xshow  * pObjShow = NULL;
  ceo43_xshow  * pObjTmp  = NULL;

  pObjShow = new ceo43_xshow(command->args, vcontrol->dbname, bOk);

  // Init OK Message
  if (bOk && pObjShow != NULL) {

    sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), "%s%s", ANSWER_OK_CN00,  LINE_SEPSTRING_CN00);
    pCurrent = pCurrent    + strlen(pCurrent);
    sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), "%*s%s", (int) strlen(KEY_DIRCONTINUE_CN00), " ", LINE_SEPSTRING_CN00);
    pContinue = pCurrent;
    pCurrent = pCurrent    + strlen(pCurrent);

    nSize    = (tsp00_Int4)(replyLenMax - strlen(replyData));

    while (pObjShow->eo43NextLine(pCurrent, nSize, bNoNewLine, nExitCode) > 0 && nSize > 200) {
      pCurrent = pCurrent + strlen(pCurrent);
      nSize = (tsp00_Int4)(replyLenMax - strlen(replyData));
      if (bNoNewLine && nSize > 0) {
        sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), LINE_SEPSTRING_CN00);
        pCurrent = pCurrent + strlen(pCurrent);
      } // end if
      nSize = (tsp00_Int4)(replyLenMax - strlen(replyData));
    } // end while

    if (nSize <= 200) {
      cn40FreeCommandObj(vcontrol);
      vcontrol->pCommandObj = (void *) pObjShow;
      strncpy(pContinue, KEY_DIRCONTINUE_CN00, strlen(KEY_DIRCONTINUE_CN00));
      vcontrol->szNextCommand.rawAssign("show_next");
      vcontrol->nNextCommandSkip = 1;
    } else {
      if (bNoNewLine) {
        sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), LINE_SEPSTRING_CN00);
        pCurrent = pCurrent + strlen(pCurrent);
      } // end if
      delete pObjShow;
    } // end if

    *replyLen = (int)strlen(replyData);

    if (strstr(replyData, "usage: x_cons") != NULL) {
      char            szShowCommand  [PARAMETER_MAXLEN_CN90] = "";
      cn90GetToken(command->args, szShowCommand,  1, PARAMETER_MAXLEN_CN90);
      teo200_EventList aPARAM(FUNCTION_NAME_MCN00_1, 1, TERR_CN00_1, "DBM", "Parameter '%s' is not allowed.", szShowCommand);
      teo200_EventList aDBM(aPARAM, FUNCTION_NAME_MCN00_1, ERR_PARAM_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBM);
    } // end if

  } else {
    nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_EXECUTE_CN00);
  } // end if

  return nFuncReturn;
} /* end cn40ShowSomething */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40ShowList
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ShowList
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error    nFuncReturn = OK_CN00;
  char         * pCurrent = replyData;
  char         * pShowCmd = NULL;
  char           szLine[PARAMETER_MAXLEN_CN90];
  char           szToken[PARAMETER_MAXLEN_CN90];
  bool           bNoNewLine;
  tsp00_Bool     bOk;
  tsp00_Int4     nExitCode;
  tsp00_Int4     nSize;
  ceo43_CmdPipe  pObjXCons;

  sp77sprintf(szLine, PARAMETER_MAXLEN_CN90, "%s %s %s", TXT_CMD_XCONS, (char   *) vcontrol->dbname, TXT_CMD_HELP);
  pObjXCons.eo43OpenCommand(szLine, bOk);

  // Init OK Message
  if (bOk) {

    sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), "%s%s", ANSWER_OK_CN00,  LINE_SEPSTRING_CN00);
    pCurrent = pCurrent    + strlen(pCurrent);
    nSize    = (tsp00_Int4)(replyLenMax - strlen(replyData));

    while (pObjXCons.eo43NextLine(szLine, PARAMETER_MAXLEN_CN90, bNoNewLine, nExitCode) > 0) {
      pShowCmd = strstr(szLine, TXT_CMD_SHOW);
      if (pShowCmd != NULL) {
        cn90GetToken(pShowCmd, szToken, 2, PARAMETER_MAXLEN_CN90);
        sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), "%s%s", szToken,  LINE_SEPSTRING_CN00);
        pCurrent = pCurrent + strlen(pCurrent);
      } // end if
    } // end while

      *replyLen = (int)strlen(replyData);

  } else {
    nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_EXECUTE_CN00);
  } // end if

  return nFuncReturn;
} /* end cn40ShowList */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40ShowNext
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ShowNext
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error    nFuncReturn = OK_CN00;
  char         * pCurrent  = replyData;
  char         * pContinue = NULL;
  bool           bNoNewLine;
  tsp00_Int4     nExitCode;
  tsp00_Int4     nSize;
  ceo43_xshow  * pObjShow = NULL;
  ceo43_xshow  * pObjTmp  = NULL;

  pObjShow = (ceo43_xshow *) vcontrol->pCommandObj;

  // Init OK Message
  if (pObjShow != NULL) {

  sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), "%s%s", ANSWER_OK_CN00,  LINE_SEPSTRING_CN00);
  pCurrent = pCurrent    + strlen(pCurrent);
  sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), "%*s%s", (int) strlen(KEY_DIRCONTINUE_CN00), " ", LINE_SEPSTRING_CN00);
  pContinue = pCurrent;
  pCurrent = pCurrent    + strlen(pCurrent);

  nSize    = (tsp00_Int4)(replyLenMax - strlen(replyData));

  while (pObjShow->eo43NextLine(pCurrent, nSize, bNoNewLine, nExitCode) > 0 && nSize > 200) {
    pCurrent = pCurrent + strlen(pCurrent);
    nSize = (tsp00_Int4)(replyLenMax - strlen(replyData));
    if (bNoNewLine && nSize > 0) {
      sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), LINE_SEPSTRING_CN00);
      pCurrent = pCurrent + strlen(pCurrent);
    } // end if
    nSize = (tsp00_Int4)(replyLenMax - strlen(replyData));
  } // end while

  if (nSize <= 200) {
    vcontrol->pCommandObj = (void *) pObjShow;
    strncpy(pContinue, KEY_DIRCONTINUE_CN00, strlen(KEY_DIRCONTINUE_CN00));
    vcontrol->szNextCommand.rawAssign("show_next");
    vcontrol->nNextCommandSkip = 1;
  } else {
    if (bNoNewLine) {
      sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), LINE_SEPSTRING_CN00);
      pCurrent = pCurrent + strlen(pCurrent);
    } // end if
    cn40FreeCommandObj(vcontrol);
  } // end if

  *replyLen = (int)strlen(replyData);

  } else {
    nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_EXECUTE_CN00);
  } // end if

  return nFuncReturn;
} /* end cn40ShowNext */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBConsole
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBConsole
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error    nFuncReturn = OK_CN00;
  char         * pCurrent = replyData;
  char           szLine[PARAMETER_MAXLEN_CN90];
  bool           bNoNewLine;
  tsp00_Bool     bOk;
  tsp00_Int4     nExitCode;
  tsp00_Int4     nSize;
  ceo43_CmdPipe  pObjXCons;

  cn90GetToken(command->args, szLine, 1, PARAMETER_MAXLEN_CN90);

    sp77sprintf(szLine, PARAMETER_MAXLEN_CN90, "%s %s %s", TXT_CMD_XCONS, (char   *) vcontrol->dbname, command->args);

    pObjXCons.eo43OpenCommand(szLine, bOk);

    if (bOk) {

      // init message
      sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), "%70s%s", " ",  LINE_SEPSTRING_CN00);
      pCurrent = pCurrent    + strlen(pCurrent);

      nSize    = (tsp00_Int4)(replyLenMax - strlen(replyData));

      while (pObjXCons.eo43NextLine(pCurrent, nSize, bNoNewLine, nExitCode) > 0 && nSize > 100) {
        pCurrent = pCurrent + strlen(pCurrent);
        nSize = (tsp00_Int4)(replyLenMax - strlen(replyData));
        if (bNoNewLine && nSize > 0) {
          sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), LINE_SEPSTRING_CN00);
          pCurrent = pCurrent + strlen(pCurrent);
        } // end if
        nSize = (tsp00_Int4)(replyLenMax - strlen(replyData));
      } // end while

      if (bNoNewLine) {
        sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent - replyData), LINE_SEPSTRING_CN00);
        pCurrent = pCurrent + strlen(pCurrent);
      } // end if

      if (nExitCode != 0) {
        nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_EXECUTE_CN00);
      } else {
        cn90AnswerOK (replyData, replyLen, NULL);
      } // end if
      replyData[strlen(replyData) - 1] = ' ';
      replyData[strlen(replyData)] = ' ';

      *replyLen = (int)strlen(replyData);

    } else {
      nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_EXECUTE_CN00);
    } // end if

  return nFuncReturn;
} /* end cn40DBConsole */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40FreeCommandObj
 * ------------------------------------------------------------------
 */
void cn40FreeCommandObj
      ( VControlDataT * vcontrol )
{
  ceo43_xshow  * pObjShow = NULL;

  if (vcontrol != NULL) {
    pObjShow = (ceo43_xshow *) vcontrol->pCommandObj;
    if (pObjShow != NULL) {
      delete pObjShow;
    } // end if
    vcontrol->pCommandObj = NULL;
  } // end if

} // end cn40FreeCommandObj

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBState
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBState
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error    nFuncReturn = OK_CN00;
  tcn00_DBState  DBState = STATE_UNKNOWN_CN00;
  tsp00_C256c    szErrText;
  
  DBState = cn90DBState(vcontrol->dbname, szErrText);

  switch (DBState) {
    case STATE_ERROR_CN00:    
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_ERROR_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_OFFLINE_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_OFFLINE_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_STARTING_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_STARTING_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_ADMIN_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_ADMIN_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_STANDBY_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_STANDBY_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_ONLINE_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_ONLINE_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_SHUTDOWN_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_SHUTDOWN_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_SHUTDOWNREINIT_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_SHUTDOWNREINIT_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_SHUTDOWNKILL_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_SHUTDOWNKILL_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_STOP_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_STOP_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_KILL_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_KILL_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_ABORT_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_ABORT_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_STOPPED_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_STOPPED_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_UNDEFINED_CN00:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_UNDEFINED_CN00,      LINE_SEPSTRING_CN00);
      break;
    case STATE_UNKNOWN_CN00:
    default:
      sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                           ANSWER_OK_CN00,              LINE_SEPSTRING_CN00,
                           TXT_CMD_STATE,               LINE_SEPSTRING_CN00,
                           TXT_STATE_UNKNOWN_CN00,      LINE_SEPSTRING_CN00);
      break;
  } // end switch

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* end cn40DBState */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DBSpeed
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DBSpeed
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error    nFuncReturn = OK_CN00;
  tsp9_pgm_kind  pgmKind = csp9_any_pgm;
  tcn00_DBState  DBState = STATE_UNKNOWN_CN00;

  pgmKind = cn90DBSpeed(vcontrol->dbname);
  DBState = cn90DBState(vcontrol->dbname);

  if (DBState == STATE_ONLINE_CN00 || DBState == STATE_ADMIN_CN00 || DBState == STATE_STANDBY_CN00) {
    switch (pgmKind) {
      case csp9_fast_pgm:
        sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                             ANSWER_OK_CN00,    LINE_SEPSTRING_CN00,
                             TXT_CMD_SPEED,     LINE_SEPSTRING_CN00,
                             TXTU_SPEED_FAST,   LINE_SEPSTRING_CN00);
        break;
      case csp9_quick_pgm:
        sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                             ANSWER_OK_CN00,    LINE_SEPSTRING_CN00,
                             TXT_CMD_SPEED,     LINE_SEPSTRING_CN00,
                             TXTU_SPEED_QUICK,  LINE_SEPSTRING_CN00);
        break;
      case csp9_slow_pgm:
        sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                             ANSWER_OK_CN00,    LINE_SEPSTRING_CN00,
                             TXT_CMD_SPEED,     LINE_SEPSTRING_CN00,
                             TXTU_SPEED_SLOW,   LINE_SEPSTRING_CN00);
        break;
      case csp9_test_pgm:
        sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                             ANSWER_OK_CN00,    LINE_SEPSTRING_CN00,
                             TXT_CMD_SPEED,     LINE_SEPSTRING_CN00,
                             TXTU_SPEED_TEST,   LINE_SEPSTRING_CN00);
        break;
      default:
        sp77sprintf(replyData, replyLenMax, "%s%s%s%s%s%s",
                             ANSWER_OK_CN00,    LINE_SEPSTRING_CN00,
                             TXT_CMD_SPEED,     LINE_SEPSTRING_CN00,
                             TXTU_SPEED_UNKNOWN,LINE_SEPSTRING_CN00);
        break;
    } // end if

    *replyLen = (int)strlen(replyData);
  } else {
    nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_DBNORUN_CN00);
  } // end if

  return nFuncReturn;
} /* end cn40DBSpeed */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40_RegisterServiceDB
 * ------------------------------------------------------------------
 */
#define DBNAME_LENGTH 8
// 65 bis 90

static bool cn40_RegisterServiceDB
      ( const tsp09_RteInstallationInfoNew  & relInfoIn)
{
  FUNCTION_DBG_MCN00_1("cn40_RegisterServiceDB");

  bool             bReturn = false;
  char             szTemp[PARAMETER_MAXLEN_CN90];
  char           * pTemp = NULL;
  tsp00_DbNamec    szDBName;
  int              nPostfix = 1;

  cn90ServiceDB(szDBName, relInfoIn.dbroot);

  if (szDBName.length() == 0) {
    sprintf(szTemp,
            "%sM%01d%01d%02d%02d", 
            SERVICE_PARAMFILE_ID_CN90,
            relInfoIn.version.no[0],
            relInfoIn.version.no[1],
            relInfoIn.version.no[2],
            relInfoIn.version.no[3]);
    szTemp[DBNAME_LENGTH] = CHAR_STRINGTERM_CN90;
    pTemp     = &szTemp[(strlen(szTemp) > (DBNAME_LENGTH - 2)) ? (DBNAME_LENGTH - 2) : strlen(szTemp)];
    szDBName.rawAssign(szTemp);

    while (cn90DBExists(szDBName) && nPostfix < 100) {
      sp77sprintf(pTemp, PARAMETER_MAXLEN_CN90, "%02d", nPostfix);
      ++nPostfix;
      szDBName.rawAssign(szTemp);
    } // end while
  } // end if  

  if (nPostfix < 100) {
//    sqlxregisterdb (szDBName, relInfoIn.dbroot, csp9_any_pgm, csp9_no_options, &xError);

    SAPDBErr_MessageList err;        
    RTE_ActiveInstallation * activeInstallation = (RTE_DBRegister::Instance()).GetActiveInstallationByDBRoot(relInfoIn.dbroot,err);

    SAPDB_Bool autoStart = (csp9_no_options & csp9_start_automatic) != 0;

    if(!activeInstallation->RegisterDatabase(szDBName,autoStart,NULL, NULL,err))
    {
//        error!
    }
    delete activeInstallation;
    if(SAPDBErr_MessageList::Error != err.Type()){
      if (cn20CreateSrvParam( szDBName ) == OK_CN00) {
        cn50DBMUser     oUser;
        tcn00_UserNamec szUser;
        tsp00_Namec     szPassword;
        szUser.rawAssign("SERVICE");
        szPassword.rawAssign("SERVICE");
        oUser.clear();
        oUser.setDBName      ( szDBName  )
             .setColdUser    (           )
             .setUserName    ( szUser    )
             .setMasterPwd   ( szPassword)
             .setServerRights( DBMMaskAll_CN50, DBMUserDefault_CN50   )
             .setGUIRights   ( DBMMaskAll_CN50, DBMUserDefaultGUI_CN50);

        if (oUser.save() == OK_CN00) {
          bReturn = true;
        } else {
//          sqlxunregisterdb (szDBName, csp9_any_pgm, &xError);

          SAPDBErr_MessageList err;        
          RTE_ActiveInstallation * activeInstallation = (RTE_DBRegister::Instance()).GetActiveInstallationByDBName(szDBName,err);

          if(!activeInstallation->UnregisterDatabase(szDBName,err))
          {
//            error!
          }
          delete activeInstallation;
        } // end if
      } else {
//        sqlxunregisterdb (szDBName, csp9_any_pgm, &xError);

        SAPDBErr_MessageList err;        
        RTE_ActiveInstallation * activeInstallation = (RTE_DBRegister::Instance()).GetActiveInstallationByDBName(szDBName,err);

        if(!activeInstallation->UnregisterDatabase(szDBName,err))
        {
//          error!
        }
        delete activeInstallation;
      } // end if
    } else {
      teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, csp9_xrte_notok,  TERR_CN00_1, "DBM", (char *)err.Message());
      tin100_GlobalLog::writeEntry (aEvent);
    } // end if
  } else {
    teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_SERVICEDB_CN00_1, szDBName.asCharp());
    tin100_GlobalLog::writeEntry (aEvent);
  } // end if
  
   return bReturn;
} // end cn40_RegisterServiceDB

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40_CheckInstKey
 * ------------------------------------------------------------------
 */
static bool cn40_CheckInstKey
      ( const tsp09_RteInstallationInfoNew  & relInfoIn )
{
  bool                           bFound = false;
  tsp9_rte_xerror                xError;
  void                         * pHandle;
  tsp09_RteInstallationInfoNew   relInfo;

  // open enum
  sqlxopen_installation_enum (&pHandle, &xError);

  if (xError.xe_result == csp9_xrte_ok) {
    // iterate trough installations
    while (xError.xe_result == csp9_xrte_ok && !bFound) {
      relInfo.RecordVersion = INSTALLATION_RECORD_VERSION_V721;
      relInfo.RecordLength  = sizeof(relInfo);
      sqlxnext_installationNew (pHandle, relInfo, &xError);
      if (xError.xe_result == csp9_xrte_ok) {
        bFound = ( strcmp ( relInfo.key,     relInfoIn.key                               ) == 0 &&
                   memcmp  ( &relInfo.version, &relInfoIn.version, sizeof(relInfo.version)) == 0 &&
#ifdef _WIN32
                   stricmp( relInfo.dbroot,  relInfoIn.dbroot                            ) != 0    );
#else
                   strcmp ( relInfo.dbroot,  relInfoIn.dbroot                            ) != 0    );
#endif
      } // end if
    } // end while

    // close enum
    sqlxclose_installation_enum(pHandle);
  } // end if

  return bFound;
} // end cn40_CheckInstKey

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40InstEnum
 * ------------------------------------------------------------------
 */
tcn00_Error cn40InstEnum
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error                    nFuncReturn = OK_CN00;
  tsp9_rte_xerror                xError;
  void                      *    pHandle;
  tsp09_RteInstallationInfoNew   relInfo;
  char                         * pCurrent    = replyData;
  char                           szMode[PARAMETER_MAXLEN_CN90];
  bool                           bKey = false;
  int                            nLength;

  if (cn90GetToken(command->args, szMode, 1, PARAMETER_MAXLEN_CN90)) {
    if (stricmp(szMode, OPTS_INST_KEY) == 0) {
      bKey = true;
    } else {
      nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    // init message
    sp77sprintf(pCurrent, replyLenMax - (int)(pCurrent -replyData), "%s%s", ANSWER_OK_CN00,  LINE_SEPSTRING_CN00);
    pCurrent = pCurrent + strlen(pCurrent);

    // open enum
    sqlxopen_installation_enum (&pHandle, &xError);
    
    if (xError.xe_result == csp9_xrte_ok) {
      // iterate trough installations
      while (xError.xe_result == csp9_xrte_ok) {
        relInfo.RecordVersion = INSTALLATION_RECORD_VERSION_V721;
        relInfo.RecordLength  = sizeof(relInfo);
        sqlxnext_installationNew (pHandle, relInfo, &xError);
        if (xError.xe_result == csp9_xrte_ok) {
          sp77sprintf (pCurrent, replyLenMax - (int)(pCurrent -replyData), "%d.%d.%d.%d",
                     relInfo.version.no [0],
                     relInfo.version.no [1],
                     relInfo.version.no [2],
                     relInfo.version.no [3]);
          nLength  = (int)strlen(pCurrent);
          pCurrent = pCurrent + nLength;
          sp77sprintf (pCurrent, replyLenMax - (int)(pCurrent -replyData), "%*s", 13 - ((nLength >= 13) ? 12 : nLength), " ");
          pCurrent = pCurrent + strlen(pCurrent);

          if (bKey) {
            sp77sprintf (pCurrent, replyLenMax - (int)(pCurrent -replyData), "%-*s ",
                       18,
                       relInfo.key.asCharp());
            pCurrent = pCurrent + strlen(pCurrent);
          } // end if
          sp77sprintf (pCurrent, replyLenMax - (int)(pCurrent -replyData), "%s%s",
                     relInfo.dbroot.asCharp(),
                     LINE_SEPSTRING_CN00);
          pCurrent = pCurrent + strlen(pCurrent);
        } // end if

      } // end while

      sqlxclose_installation_enum(pHandle);

    } // end if

    if (xError.xe_result != csp9_xrte_ok && xError.xe_result != csp9_xrte_atend) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
    } else {
      *replyLen = (int)strlen(replyData);
    } // end if

  } // end if


  return nFuncReturn;
} /* end cn40InstEnum */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40InstReg
 * ------------------------------------------------------------------
 */
tcn00_Error cn40InstReg
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40InstReg");

  tcn00_Error                    nFuncReturn                      = OK_CN00;
  tsp09_RteInstallationInfoNew   relInfo;
  char                           szToken[PARAMETER_MAXLEN_CN90]   = "";
  char                           szVersion[PARAMETER_MAXLEN_CN90] = "";
  char                         * pToken;
  int                            nIndex;
  int                            nToken                           = 1;
  tsp9_rte_xerror                xError;
  tsp100_VersionID1              VersionID1;
  bool                           bClient = false;
  
  relInfo.key.Init();
  relInfo.dbroot.Init();

  // read parameters is Version or switch
  while (cn90GetToken(command->args, szToken, nToken, PARAMETER_MAXLEN_CN90)) {
    if (stricmp(szToken, OPTS_INST_VERSION) == 0) {
      ++nToken;
      if (!cn90GetToken(command->args, szVersion, nToken, PARAMETER_MAXLEN_CN90)) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
      } // end if
    } else if (stricmp(szToken, OPTS_INST_KEY) == 0) {
      ++nToken;
      if (!cn90GetToken(command->args, szToken, nToken, PARAMETER_MAXLEN_CN90)) {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
      } else {
        relInfo.key.rawAssign(szToken);
      } // end if
    } else if (stricmp(szToken, OPTS_INST_CLIENT) == 0) {
      bClient = true;
    } else {
      if (nToken == 1) {
        relInfo.dbroot.rawAssign(szToken);
      } else if (nToken == 2) {
        SAPDB_strcpy(szVersion , szToken);
      } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
      } // end if
    } // end if
 
    ++nToken;    
  } // end while

  // check dbroot
  if (nFuncReturn == OK_CN00) {

    if (relInfo.dbroot.length() == 0) {
      relInfo.dbroot = vcontrol->dbroot;
    } else {
      if (relInfo.dbroot[relInfo.dbroot.length() - 1] == PATH_DELIMITER_CN90) {
        relInfo.dbroot[relInfo.dbroot.length() - 1] = 0;
      } // end if
        
      if (
#ifndef _WIN32
        strcmp( relInfo.dbroot, vcontrol->dbroot )  != 0
#else
        stricmp(relInfo.dbroot, vcontrol->dbroot ) != 0
#endif
         ) {
        teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_WRONGINST_CN00_1, relInfo.dbroot.asCharp(), vcontrol->dbroot.asCharp());
        nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);

      } // end if
    } // end if

  } // end if

  // checking parameters
  if (nFuncReturn == OK_CN00) {
    for (nIndex = 0; nIndex < csp9_version_digits; nIndex++) {
      relInfo.version.no [nIndex] = STATIC_CAST(signed char, 0);
    } // end for
    // reading verison
    if (strlen(szVersion) == 0) {
      sp100_GetVersionID ( VersionIDType1_esp100, s100buildnumberEx, &VersionID1 );

      relInfo.version.no [0] = STATIC_CAST(signed char, VersionID1.MajorVersion_sp100);
      relInfo.version.no [1] = STATIC_CAST(signed char, VersionID1.MinorVersion_sp100);
      relInfo.version.no [2] = STATIC_CAST(signed char, VersionID1.CorrLevel_sp100);
      relInfo.version.no [3] = STATIC_CAST(signed char, VersionID1.BuildNumberPrefix_sp100);
    } else {
      // Read Version from arguments
      pToken = strtok(szVersion, ".");
      nIndex = 0;
      while (pToken && nIndex < csp9_version_digits) {
        relInfo.version.no [nIndex] = STATIC_CAST(signed char, atoi(pToken));
        nIndex++;
        pToken = strtok(NULL, ".");
      } // end while
    } // end if

    // checking key
    if (cn40_CheckInstKey(relInfo)) {
      teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, 
                              ERR_KEYEXISTS_CN00_1,
                              (relInfo.key.length() == 0) ? "(empty)" : relInfo.key.asCharp()); 
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
    } // end if
  } // end if

  // register version
  if (nFuncReturn == OK_CN00) {
    relInfo.RecordVersion = INSTALLATION_RECORD_VERSION_V721;
    relInfo.RecordLength  = sizeof(relInfo);

    // remove trailing (back)slashes from inst path
    nIndex = relInfo.dbroot.length() - 1;
    while (nIndex > 0) {
      if ((relInfo.dbroot[nIndex] != CHAR_SLASH) && (relInfo.dbroot[nIndex] != CHAR_BACKSLASH)) {
        relInfo.dbroot[nIndex + 1] = CHAR_STRINGTERM_CN90;
        break;
      } // end if
      --nIndex;
    } // end while

    sqlxregisterinstNew (relInfo, &xError);

    if (xError.xe_result != csp9_xrte_ok) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
    } else {
      if (!bClient) {
        if (!cn40_RegisterServiceDB(relInfo)) {
          teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, 
                                  ERR_SERVICEDB_CN00_1,
                                  relInfo.dbroot.asCharp());
          nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
        } else {
          cn90AnswerOK (replyData, replyLen, NULL);
        } // end if
      } else {
        cn90AnswerOK (replyData, replyLen, NULL);
      } // end if
    } // end if

  } // end if

  return nFuncReturn;

} /* end cn40InstReg */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40InstUnreg
 * ------------------------------------------------------------------
 */
tcn00_Error cn40InstUnreg
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40InstUnreg");

  tcn00_Error          nFuncReturn = OK_CN00;
  char                 szToken[PARAMETER_MAXLEN_CN90];
  tsp00_Pathc          szDbRoot;
  tsp00_DbNamec        szDbName;
  tsp9_rte_xerror      xError;

  cn90GetToken(command->args, szToken, 1, PARAMETER_MAXLEN_CN90);
  cn90StripQuotes(szToken);
  szDbRoot.rawAssign(szToken);

  // check dbroot

  if (szDbRoot.length() == 0) {
    szDbRoot = vcontrol->dbroot;
//  } else {
//    if (
//#ifndef _WIN32
//      strcmp( szDbRoot, vcontrol->dbroot )  != 0
//#else
//      stricmp(szDbRoot, vcontrol->dbroot ) != 0
//#endif
//       ) {
//      teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_WRONGINST_CN00_1, szDbRoot.asCharp(), vcontrol->dbroot.asCharp());
//      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
//
//    } // end if
  } // end if

  if (szDbRoot[szDbRoot.length()  - 1] == PATH_DELIMITER_CN90) {
    szDbRoot[szDbRoot.length() - 1] = 0;
  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90ServiceDB(szDbName, szDbRoot);
    if (szDbName.length() > 0) {
      cn40_DBDrop(szDbName, szDbRoot, true, true, replyData, replyLen, replyLenMax);
    } // end if
  
    sqlxunregisterinst (szDbRoot, &xError);

    if (xError.xe_result != csp9_xrte_ok) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
    } else {
      cn90AnswerOK (replyData, replyLen, NULL);
    } /* end if */

  } // end if

  return nFuncReturn;

} /* end cn40InstUnreg */

/*
 * IMPLEMENTATION PRIVATE FUNCTION cn40_ComputeEsc
 * ------------------------------------------------------------------
 */
#define ESC_MARK '#'

static void cn40_ComputeEsc
      ( tsp00_Pathc & szFile )
{
  tsp00_Int4 nLength = 0;
  tsp00_Int4 nSource = 0;
  tsp00_Int4 nTarget = 0;
  unsigned char nDig1   = 0;
  unsigned char nDig2   = 0;
  unsigned char nChar   = 0;

  nLength = szFile.length();
  while (nSource < nLength) {

    nDig1   = 0;
    nDig2   = 0;
    nChar   = 0;

    if (szFile[nSource] == ESC_MARK) {
      ++nSource;
      nDig1 = szFile[nSource];
      if (nDig1 == ESC_MARK) {
        nChar = nDig1;
      } else {
        ++nSource;
        nDig2 = szFile[nSource];

        // Konverting to upper
        nDig1 = toupper(nDig1);
        nDig2 = toupper(nDig2);
        // checking hexdigit
        nDig1 = (nDig1 >= '0' && nDig1 <= '9' ||
                 nDig1 >= 'A' && nDig1 <= 'F'    ) ? nDig1 : 0;
        nDig2 = (nDig2 >= '0' && nDig2 <= '9' ||
                 nDig2 >= 'A' && nDig2 <= 'F'    ) ? nDig2 : 0;
        // checking second digit
        nDig1 = (nDig2 == 0) ? 0 : nDig1;
        nDig2 = (nDig1 == 0) ? 0 : nDig2;

        if (nDig1 > 0 && nDig2 > 0) {
          nDig1 = (nDig1 <= '9') ? nDig1 - 0x30 : nDig1 - 0x41;
          nDig2 = (nDig2 <= '9') ? nDig2 - 0x30 : nDig2 - 0x41;

          nChar = (nDig1 * 0x10) + nDig2;
        } else {
          --nSource;
          --nSource;
          nChar = ESC_MARK;
        } // end if

      } // end if
    } else {
      nChar = szFile[nSource];
    } // end if

    if (nChar != 0) {
      szFile[nTarget] = nChar;
      ++nTarget;
    } // end if

    ++nSource;
  } // end while

   szFile[nTarget] = 0;

} // end cn40_ComputeEsc

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40DbAddDevice
 * ------------------------------------------------------------------
 */
tcn00_Error cn40DbAddDevice
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40DbAddDevice");

  tcn00_Error            nFuncReturn    = OK_CN00;
  bool                   bMirror     = false;
  char                   szMode  [PARAMETER_MAXLEN_CN90];
  char                   szType  [PARAMETER_MAXLEN_CN90];
  char                   szMType [PARAMETER_MAXLEN_CN90];
  char                   szSize  [PARAMETER_MAXLEN_CN90];
  tsp00_Pathc            szName;
  tsp00_Pathc            szMName;
  tcn00_DBState          aState;
  char                   szCommand [PARAMETER_MAXLEN_CN90];
  int                    nNumber;
  tcn00_DevspaceKeywords aKeyTable  [] = XP_DEVSPACE_KEYWORDS_CN00;
  tcn00_DevspaceParams   aParamTable[] = XP_DEVSPACE_PARAMS_CN00;
  tsp00_Int4             nKey          = 0;
  tsp00_Int4             nParam        = 0;
  tsp00_Int4             nMaxSize      = 0;
  tsp00_Int4             nSize         = 0;
  long                   nReturnSize   = 0;
  tcn002_XpValueName     szParam;
  tcn002_XpValueString   szValue;
  tsp00_Int4             nValue;
  bool                   bParamWritten = false;
  tin01_sql_session    * pSession;
  tin01_sql_session      aSQLSession;
  bool                   bConnect      = false;
  bool                   bHSS          = false;
  const char           * pArgs         = command->args;

  cn90GetToken(command->args, szMode,   1, PARAMETER_MAXLEN_CN90);
  cn90GetToken(command->args, szName,   2, szName.size()+1);
  cn90StripQuotes(szName);
  cn90GetToken(command->args, szType,   3, PARAMETER_MAXLEN_CN90);
  cn90GetToken(command->args, szSize,   4, PARAMETER_MAXLEN_CN90);
  cn90GetToken(command->args, szMName,  5, szMName.size()+1);
  cn90StripQuotes(szMName);
  cn90GetToken(command->args, szMType,  6, PARAMETER_MAXLEN_CN90);

  // checking mode
  if (nFuncReturn == OK_CN00) {
    if (stricmp(szMode, XP_DEV_DAT_CN00) != 0 &&
        stricmp(szMode, XP_DEV_LOG_CN00) != 0    ) {
      nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  // checking type
  if (nFuncReturn == OK_CN00) {
    if (stricmp(szType, "A") == 0 ) {
      nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  // checking dbstate
  if (nFuncReturn == OK_CN00) {
    aState = cn90DBState(vcontrol->dbname);
    if (aState != STATE_ADMIN_CN00 && aState != STATE_ONLINE_CN00 && aState != STATE_STANDBY_CN00) {
      nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_DBNORUN_CN00);
    } // end if
  } // end if

  // checking hss 
  if (nFuncReturn == OK_CN00) {
    bHSS = vcontrol->pHSSNodes->Exists(RTE_ISystem::Instance().GetLocalNodeName()) && cn46IsMaster(vcontrol->dbname);
  } // end if

  // computing number and size
  if (nFuncReturn == OK_CN00) {
    /* search in keywordtable */
    for (nKey = 0; (aKeyTable[nKey].nDevSpace != XPDevSpaceUnknown_ecn00) &&
                   (stricmp(aKeyTable[nKey].szText, szMode) != 0  );    nKey++);

    /* search in paramtable */
    for (nParam = 0; aKeyTable[nKey].nDevSpace != aParamTable[nParam].nDevSpace; nParam++);

    if (aKeyTable[nKey].nDevSpace == XPDevSpaceUnknown_ecn00) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } else {
      nNumber  = 0;
      nMaxSize = 0;
      do {
        nNumber++;
        sp77sprintf(szParam, szParam.size(), aParamTable[nParam].szSize, nNumber);
        cn20XParamGetValue( vcontrol->dbname, szParam, nValue);
        nMaxSize = nMaxSize + nValue;
        sp77sprintf(szParam, szParam.size(), aParamTable[nParam].szName, nNumber);
        cn20XParamGetValue( vcontrol->dbname, szParam, szValue);
      } while (strlen(szValue) > 0);
    } // end if
  } /* end if */

  // checking number
  if (nFuncReturn == OK_CN00) {
    nValue = 0;
    szParam.rawAssign(aParamTable[nParam].szMaxCount);
    cn20XParamGetValue( vcontrol->dbname, szParam, nValue);
    if (nValue < nNumber) {
      nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_MAXVOLCNT_CN00);
    } // end if
  } // end if

  // checking mirrordata
  if (nFuncReturn == OK_CN00) {
    szValue.Init();
    if (stricmp(szMode, XP_DEV_DAT_CN00) == 0) {
      szParam.rawAssign(PAN_MIRR_DATA);
    } else {
      szParam.rawAssign(PAN_LOG_MIRRORED);
    } // end if

    cn20XParamGetValue( vcontrol->dbname, szParam, szValue);

    if (stricmp(szValue, XP_VAL_DUAL_CN00) == 0 || stricmp(szValue, XP_VAL_YES_CN00) == 0) {
      bMirror = true;
      if (szMName.length() == 0) {
        nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_MISSMIRR_CN00);
      } // end if
    } // end if
  } // end if

#if defined(SAPDBR73)
  // checking size
  if (nFuncReturn == OK_CN00) {
    if (stricmp(szMode, XP_DEV_DAT_CN00) == 0) {
      szParam.rawAssign(aParamTable[nParam].szMaxSize);
      cn20XParamGetValue( vcontrol->dbname, szParam, nValue);
      if ( nMaxSize + nSize > nValue) {
        nFuncReturn =  cn90AnswerIError(replyData, replyLen, ERR_MAXDATA_CN00);
      } // end if
    } // end if
  } // end if
#endif

  // all tests passed

  // scanning names for escape sequences
  if (nFuncReturn == OK_CN00) {
    cn40_ComputeEsc(szName);
    if (bMirror) {
      cn40_ComputeEsc(szMName);
    } // end if

  } // end if

  // get utility session
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn80UtilSession(vcontrol, replyData, replyLen, &pSession);
    if (nFuncReturn == ERR_NOUTILSESSION_CN00) {
      cn90AnswerOK(replyData, replyLen, NULL);
      pSession = &aSQLSession;
      nFuncReturn = cn80ConnectUtil ( vcontrol->dbname, pSession, replyData,replyLen);
      bConnect = (nFuncReturn == OK_CN00);
    } // end if
  } // end if

  // adding params
  if (nFuncReturn == OK_CN00) {
    nSize = atol(szSize);
    sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, "%d %s \"%s\" %s %d",
                         nNumber,
                         szMode,
                         szName.asCharp(),
                         szType,
                         (int) nSize);
    command->args = szCommand;
    nFuncReturn = cn20ParamAddDevSpace(vcontrol,
                                       command,
                                       replyData,
                                       replyLen,
                                       replyLenMax,
                                       nReturnSize);
    if (nFuncReturn == OK_CN00) {
      bParamWritten = true;
      nSize = (nReturnSize != 0) ? nReturnSize : nSize;
    } // end if

    if (bMirror && nFuncReturn == OK_CN00) {
      sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, "%d M%s \"%s\" %s",
                           nNumber,
                           szMode,
                           szMName.asCharp(),
                           szMType);
      command->args = szCommand;
      nFuncReturn = cn20ParamAddDevSpace(vcontrol,
                                         command,
                                         replyData,
                                         replyLen,
                                         replyLenMax);
    } // end if
  } // end if

  // utility
  if (nFuncReturn == OK_CN00) {
    if (!bMirror) {
      sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, "ADD %s VOLUME '%s' PAGES %d DEVICE %d",
                           szMode,
                           szName.asCharp(),
                           (int) nSize,
                           nNumber);
    } else {
      sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, "ADD %s VOLUME '%s' '%s' PAGES %d DEVICE %d",
                           szMode,
                           szName.asCharp(),
                           szMName.asCharp(),
                           (int) nSize,
                           nNumber);
    } // end if
    nFuncReturn = cn80ExecuteUtil (pSession, szCommand, replyData, replyLen);
  } // end if

  // restore param
  if (bParamWritten && nFuncReturn != OK_CN00) {
    char               szSource[PARAMETER_MAXLEN_CN90];
    char               szTarget[PARAMETER_MAXLEN_CN90];
    tsp00_C256         szConfig;
    tsp01_RteError     aRteError;

    cn90GetCfgPath(szConfig);
    sp77sprintf(szTarget, PARAMETER_MAXLEN_CN90, "%s%s",  (char *) szConfig, vcontrol->dbname.asCharp());
    sp77sprintf(szSource, PARAMETER_MAXLEN_CN90, "%s.01", (char *) szTarget);
    sqlfilecopyc( szSource, szTarget, &aRteError );
  } // end if

  // release utility session
  if (bConnect) {
    cn80ReleaseUtil ( pSession );
  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if

  // hss handling
  if ((nFuncReturn == OK_CN00) && bHSS) {
    DBMSrv_Reply reply(replyData, replyLen, replyLenMax);
    reply.adaptLength(); //just to be sure we append correctly
    vcontrol->pHSSNodes->AddVolumeToCluster(pArgs, reply);
  } // end if

  return nFuncReturn;
} /* end cn40DbAddDevice */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40Test
 * ------------------------------------------------------------------
 */

/*
externPascal void s49build_pattern (
    void                  *  pat_buffer,
    pasbool                              is_ascii,
    tsp00_Int4                             start,
    tsp00_Int4                             stop,
    char                                 escape_char,
    pasbool                              escape,
    pasbool                              string,
    tsp00_SqlMode_Param                    sqlmode,
    pasbool               VAR_VALUE_REF  ok);


externPascal pasbool s49patmatch (
    void                  *  val,
    tsp00_Int4                             val_offset,
    tsp00_Int4                             val_len,
    void                  *  pat,
    tsp00_Int4                             pat_offset,
    tsp00_Int4                             pat_len,
    char                                 pat_defbyte);
*/

tcn00_Error cn40Test
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("cn40Test");

  tcn00_Error        nFuncReturn = OK_CN00;

/*
  tsp00_Pathc   szPattern;
  tsp00_Pathc   szString;
  unsigned char cPatOK;

  cn90GetToken(command->args, szPattern,  1, szPattern.size());
  cn90GetToken(command->args, szString,   2, szString.size());

  printf("Pattern:    %s\n",  szPattern.asCharp());
  printf("String:     %s\n",  szString.asCharp());
  printf("First char: %d\n", (int) szPattern[0]);
  s49build_pattern (szPattern.asCharp(), 
                    true, 
                    1, 
                    szPattern.length(),
                    '\0', 
                    false, 
                    true, 
                    sqlm_internal, 
                    cPatOK);

  printf("First char: %d\n", (int) szPattern[0]);
  printf("OK?:        %d\n", (int) cPatOK);

   if (s49patmatch (szString.asCharp(), 0, szString.length(), szPattern.asCharp(), 0, szPattern.length(), false)) {
    sprintf(replyData, "%s%s%s%s", ANSWER_OK_CN00,  LINE_SEPSTRING_CN00,
                                   "Treffer",       LINE_SEPSTRING_CN00);
   } else {
    sprintf(replyData, "%s%s%s%s", ANSWER_OK_CN00,  LINE_SEPSTRING_CN00,
                                   "KEIN Treffer",  LINE_SEPSTRING_CN00);
   } // end if

   *replyLen = (int) strlen(replyData);
*/

  cn90AnswerOK (replyData, replyLen, NULL);

  return OK_CN00;
} /* end cn40Test */

/*
 * IMPLEMENTATION PUBLIC FUNCTION cn40Crash
 * ------------------------------------------------------------------
 */

tcn00_Error cn40Crash
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{

  memset(replyData, 42, replyLenMax + 3000);
 
  cn90AnswerOK (replyData, replyLen, NULL);
  return OK_CN00;
} /* end cn40Crash */

/* ------------------------------------------------------------------
 * START OF IMPLEMENTATION PRIVATE
 * ------------------------------------------------------------------
 */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40ExecCommand
 * ------------------------------------------------------------------
 */
tcn00_Error cn40ExecCommand
      ( char          * replyData,
        int           * replyLen,
        const int       replyLenMax,
        const char    * szProgram,
        const char    * szOutput,
        bool            bPipe,
        bool            bSynchron )
{
  tcn00_Error     nFuncReturn = OK_CN00;
  int             nSysReturn  = 0;
  char        *   szTmpName   = NULL;
  char        *   szTmpDir    = NULL;
  char            szDummy[PARAMETER_MAXLEN_CN90];
  char            szTmpFile[PARAMETER_MAXLEN_CN90] = "";
  char            szCommand[PARAMETER_MAXLEN_CN90] = "";

  /* generate temp file name */
  if (nFuncReturn == OK_CN00) {
    szTmpName = tmpnam(szDummy);
    if (szTmpName == NULL) {
      nFuncReturn = cn90AnswerErrnoError(replyData, replyLen, ERR_SYSTEM_CN00, errno, szCommand);
    } else {

#ifdef _WIN32
      if ((szTmpDir = getenv(TMP_ENV)) == NULL) {
        sp77sprintf(szTmpFile, PARAMETER_MAXLEN_CN90, "%s%s%s", TMP_LOCDIR, szTmpName, TMP_EXT);
      } else {
        char  szShortTmp[PARAMETER_MAXLEN_CN90] = "";
        GetShortPathName(szTmpDir, szShortTmp, PARAMETER_MAXLEN_CN90);
        sp77sprintf(szTmpFile, PARAMETER_MAXLEN_CN90, "%s%s.%s", szShortTmp,   szTmpName, TMP_EXT);
      } /* end if */
#else
      SAPDB_strcpy(szTmpFile, szTmpName);
#endif

    } /* end if */
  } /* end if */

  /* execute command */
  if (nFuncReturn == OK_CN00) {
    if (strlen(szProgram) + strlen(szTmpFile) + 10 < PARAMETER_MAXLEN_CN90) {

      if (bPipe) {
        nSysReturn = Tools_PipeCall::CallProgram(szProgram, bSynchron ? Tools_PipeCall::CallSynchron : Tools_PipeCall::CallAsynchron, szTmpFile, szTmpFile);
      } else {
        sp77sprintf(szCommand, PARAMETER_MAXLEN_CN90, "%s 1>%s 2>&1", szProgram, szTmpFile);
        nSysReturn = system(cn90Strip(szCommand));
      } // end if

      if (nSysReturn == SYS_SYSTEM_ERR) {
        if (bPipe) {
          nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_SYSTEM_CN00, nSysReturn, Tools_PipeCall::ErrorReason());
        } else {
          nFuncReturn = cn90AnswerErrnoError(replyData, replyLen, ERR_SYSTEM_CN00, errno, szCommand);
        } // end if
      } else if (nSysReturn != 0) {
        nFuncReturn = cn90AnswerExecute(replyData, replyLen, replyLenMax, ERR_EXECUTE_CN00, nSysReturn, szOutput, szTmpFile);
      } /* end if */

    } else {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_MEM_CN00);
    } /* end if */
  } /* end if */

  /* check result */
  if (nFuncReturn == OK_CN00) {
    cn90AnswerExecute(replyData, replyLen, replyLenMax, nFuncReturn, nSysReturn, szOutput, szTmpFile);
  } /* end if */

  /* remove temporary files */
  remove(szTmpFile);

  return nFuncReturn;
} /* end cn40ExecCommand */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_ExecPythonLoad
 * ------------------------------------------------------------------
 */
static tcn00_Error cn40_ExecPythonLoad
      ( VControlDataT * vcontrol,
        const char    * szLoadFile,
        const char    * szUser,
        const char    * szPassword,
        const char    * szOptions,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error     nFuncReturn = OK_CN00;
  int             nIndex      = 0;
  FILE        *   hFile       = NULL;
  char            szCommand   [PARAMETER_MAXLEN_CN90] = "";
  char            szProtocol  [PARAMETER_MAXLEN_CN90] = "";
  char            szLine      [PARAMETER_MAXLEN_CN90] = "";
  tsp01_RteError  aRteError;
  tsp00_Pathc     szBinDir;
  tsp00_Pathc     szEnvDir;
  tsp00_Pathc     szScript;
  tsp00_Pathc     szProt;

  /* create command filename */
  szScript.rawAssign(szLoadFile);

  if (nFuncReturn == OK_CN00) {
    // remove backslashes
    for (nIndex = 0; nIndex < szScript.length(); nIndex++) {
      szScript[nIndex] = (szScript[nIndex] == CHAR_BACKSLASH) ? CHAR_SLASH : szScript[nIndex];
    } /* end for */

    // if no absolute path for scriptfile use "env" directory
    szEnvDir.Init();
    if ( !(isalpha(szScript[0]) && szScript[1] == CHAR_DRIVE && szScript[2] == CHAR_SLASH) &&
         !(szScript[0] == CHAR_SLASH) ) {
      sqlGetDbrootEnvPath(szEnvDir, TERM_WITH_DELIMITER_EO01, &aRteError);
    } /* end if */

    // look for "bin" directory
    szBinDir.Init();
    // x_python is now in the depended bin path
    // sqlGetIndependentBinPath(szBinDir, TERM_WITH_DELIMITER_EO01, &aRteError);
    sqlGetDbrootBinPath(szBinDir, TERM_WITH_DELIMITER_EO01, &aRteError);
    
#ifdef _WIN32
    char Tueddelchen[2] = "\"";
#else
    char Tueddelchen[2] = "";
#endif

    sp77sprintf(szCommand,  PARAMETER_MAXLEN_CN90, "%s%s%sx_python%s %s%s%s%s -R %s%s%s -d %s -u %s,%s %s%s", 
                                                                           Tueddelchen,
                                                                           Tueddelchen,
                                                                           szBinDir.asCharp(),
                                                                           Tueddelchen,
                                                                           Tueddelchen,
                                                                           szEnvDir.asCharp(),
                                                                           szScript.asCharp(),
                                                                           Tueddelchen,
                                                                           Tueddelchen,
                                                                           vcontrol->dbroot.asCharp(),
                                                                           Tueddelchen,
                                                                           vcontrol->dbname.asCharp(),
                                                                           szUser,
                                                                           szPassword,
                                                                           szOptions,
                                                                           Tueddelchen);
    sp77sprintf(szProtocol, PARAMETER_MAXLEN_CN90, "%s%s%sx_python%s %s%s%s%s -R %s%s%s -d %s -u %s,%s%s", Tueddelchen,
                                                                           Tueddelchen,
                                                                           szBinDir.asCharp(),
                                                                           Tueddelchen,
                                                                           Tueddelchen,
                                                                           szEnvDir.asCharp(),
                                                                           szScript.asCharp(),
                                                                           Tueddelchen,
                                                                           Tueddelchen,
                                                                           vcontrol->dbroot.asCharp(),
                                                                           Tueddelchen,
                                                                           vcontrol->dbname.asCharp(),
                                                                           szUser,
                                                                           "*",
                                                                           Tueddelchen);
    // remove old protocol
    cn42GetFileName(vcontrol->dbname, FGET_REPMAN_CN42, szProt);
    remove(szProt);

    // ... and GO!
    nFuncReturn = cn40ExecCommand(replyData, replyLen, replyLenMax, szCommand, szProtocol, false, true);

  } //

  // read protocol file
#ifdef ELCH
  if (nFuncReturn == OK_CN00 || nFuncReturn == ERR_EXECUTE_CN00) {
    hFile = NULL;
    hFile = fopen(szProt, "r");

    if (hFile) {
      while (fgets(szLine, PARAMETER_MAXLEN_CN90, hFile) != NULL && ((int) (strlen(replyData) + strlen(szLine) + 5) < replyLenMax)) {
        if (cn90CheckKeyword(szLine, "/ M") ||
            cn90CheckKeyword(szLine, "/ E")    ) {
          strcat(replyData, cn90StripTrailingChar(szLine, '\n'));
          strcat(replyData, LINE_SEPSTRING_CN00);
        } /* end if */
      } /* end while */
      fclose(hFile);
      *replyLen = strlen(replyData);
    } /* end if */
  } /* end if */
#endif

  return nFuncReturn;
} /* end cn40_ExecPythonLoad */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_OfflineToCold
 * ------------------------------------------------------------------
 */
static tcn00_Error cn40_OfflineToCold
      ( VControlDataT       * vcontrol,
        const tsp9_pgm_kind   pgmKind,
        char                * replyData,
        int                 * replyLen)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp9_rte_xerror     xError;
  tcn002_XpValueString szValue;
  tsp00_DbNamec       szDBNameL = vcontrol->dbname;

  // always try to create rundir
  if (cn20XParamGetValue(szDBNameL, PAN_RUNDIR, szValue) == OK_CN00) {
    cn90DirCreate(szValue, NULL);
  } // end if

  cn20CalcDevices( vcontrol, replyData, replyLen, 1000);

  // clear database
  sqlxclear( vcontrol->dbname, vcontrol->dbroot, &xError );

  // start database
  sqlxstart (vcontrol->dbname, pgmKind, vcontrol->dbroot, false, 0, NULL, &xError);

  if (xError.xe_result != csp9_xrte_ok) {
    // check Versions
    nFuncReturn = cn90AnswerIError(replyData, replyLen, cn40_CheckVersion(vcontrol->dbname));
    if (nFuncReturn == OK_CN00) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
    } // end if
  } else {
    nFuncReturn = cn90AnswerOK (replyData, replyLen, NULL);
  } /* end if */

  if (nFuncReturn == OK_CN00) {
    cn82RestoreEvents(vcontrol->dbname);
    cn84RestoreTrace(vcontrol->dbname);
  } // end if

  return nFuncReturn;
} // cn40_OfflineToCold

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_ColdOrStandbyToWarm
 * ------------------------------------------------------------------
 */
#undef  CN_FUNCTION
#define CN_FUNCTION "cn40_ColdOrStandbyToWarm"
static tcn00_Error cn40_ColdOrStandbyToWarm
      ( VControlDataT       * vcontrol,
        const char          * pRestart,
        char                * replyData,
        int                 * replyLen)
{
  CONSOLE_TRACE_ENTER_CN00;
  
  tcn00_Error nFuncReturn = OK_CN00;

  cn90AnswerOK (replyData, replyLen, NULL);

  nFuncReturn = cn80ExecuteUtil(vcontrol->dbname, pRestart, replyData, replyLen);

  if (nFuncReturn == OK_CN00) {
    cn51DBMConfigValue  cfgAuto    (vcontrol->dbname, CFG_AUTOSSAVE_CN51);
    cn51DBMConfigValue  cfgAutoExt (vcontrol->dbname, CFG_AUTOEXTFLAG_CN51);
    cn51DBMConfigValue  cfgRunDispatcher (vcontrol->dbname, CFG_RUNDISPATCHERFLAG_CN51);

    cn30RefreshMediaInDB(vcontrol->dbname);

    if (cfgAuto == 1) {
      cn31AutosaveOn(vcontrol);
    } // end if

    if ((stricmp(((tsp00_Namec)cfgRunDispatcher).asCharp(), "yes") == 0) ||
        (stricmp(((tsp00_Namec)cfgAutoExt).asCharp(), "yes")       == 0)) { // backw. comp.
      // start event dispatcher
      cn40_StartEventDispatcher(vcontrol);
    } // end if

  } // end if

  return nFuncReturn;

} // cn40_ColdOrStandbyToWarm

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_OnlineToOffline
 * ------------------------------------------------------------------
 */
#undef  CN_FUNCTION
#define CN_FUNCTION "cn40_OnlineToOffline"
static tcn00_Error cn40_OnlineToOffline
      ( VControlDataT       * vcontrol,
        bool                  bCluster,
        char                * replyData,
        int                 * replyLen)
{
  CONSOLE_TRACE_ENTER_CN00;

  tcn00_Error     nFuncReturn = cn90AnswerOK (replyData, replyLen, NULL);

  cn51DBMConfigValue  cfgAuto    (vcontrol->dbname, CFG_AUTOSSAVE_CN51);
  if (cfgAuto == 1) {
    cn31AutosaveEnd(vcontrol);
  } // end if

#  if defined CLUSTER_SERVER_VERSION
  if (bCluster) {
    RTE_DBName dbname;
      
    memset(&dbname[0], 0, sizeof(RTE_DBName));
    if ( vcontrol->dbname.length() < sizeof(RTE_DBName) ) {
        SAPDB_strcpy(&dbname[0], vcontrol->dbname.asCharp());

        RTE_ActiveDatabase * dbInstance;

        SAPDBErr_MessageList errList;

        dbInstance = RTE_DBRegister::Instance().GetActiveDatabase(dbname, errList);
        if ( !dbInstance ) {
            SAPDBErr_MessageList aDBM(DBMSrv_DBMError(RTE), 0);
            aDBM.AppendNewMessage(errList);
            nFuncReturn = cn90AnswerMessage(replyData, replyLen, aDBM);
        } else if ( !dbInstance->Stop(errList, 90, false, true) ) /* Stop without dump but gracefully */  {
            if ( errList.ID() == RTEERR_DBREG_SERVERDB_NOT_RESPONDING ) {
                nFuncReturn = cn00_1_ErrId(ERR_SHUTDOWN_CN00_1);
            } else {
                SAPDBErr_MessageList aDBM(DBMSrv_DBMError(RTE), 0);
                aDBM.AppendNewMessage(errList);
                nFuncReturn = cn90AnswerMessage(replyData, replyLen, aDBM);
            } // end if
        } else {
            return nFuncReturn;
        } // end if
    } else {
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_DBNAME_CN00);
    } // end if
  } else {
    nFuncReturn = cn80ExecuteUtil(vcontrol->dbname, "SHUTDOWN", replyData, replyLen);
  } // end if
#else
  nFuncReturn = cn80ExecuteUtil(vcontrol->dbname, "SHUTDOWN", replyData, replyLen);
#endif

  tcn00_DBState       DBState;

  if (nFuncReturn == cn00_1_ErrId(ERR_SHUTDOWN_CN00_1)) {
    int nTimeout = 0;
    do {
      ToolsSys_sleep(1);
      ++nTimeout;
      DBState = cn90DBState(vcontrol->dbname);
    } while ( (DBState != STATE_OFFLINE_CN00) || (nTimeout == 300) );
  } // end if

  nFuncReturn = (nFuncReturn == cn00_1_ErrId(ERR_SHUTDOWN_CN00_1)) ? OK_CN00 : nFuncReturn;

  if (DBState != STATE_OFFLINE_CN00) {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_DBRUN_CN00);
  } // end if

  return nFuncReturn;
} // cn40_OnlineToOffline

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_ColdOrStandbyToOffline
 * ------------------------------------------------------------------
 */
#undef  CN_FUNCTION
#define CN_FUNCTION "cn40_ColdOrStandbyToOffline"
static tcn00_Error cn40_ColdOrStandbyToOffline
      ( VControlDataT       * vcontrol,
        const bool            bDump,
        char                * replyData,
        int                 * replyLen)
{
  CONSOLE_TRACE_ENTER_CN00;

  tcn00_Error         nFuncReturn = OK_CN00;
  tsp9_rte_xerror     xError;

  sqlxstop (vcontrol->dbname, vcontrol->dbroot, bDump, &xError);

  if ((xError.xe_result != csp9_xrte_ok) &&  (cn90DBState(vcontrol->dbname) != STATE_OFFLINE_CN00)) {
    nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, xError.xe_text, sizeof(xError.xe_text), xError.xe_result);
  } else {
    cn90AnswerOK (replyData, replyLen, NULL);
  } /* end if */

  return nFuncReturn;
} // cn40_ColdOrStandbyToOffline

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_CheckVersion
 * ------------------------------------------------------------------
 */
#undef  CN_FUNCTION
#define CN_FUNCTION "cn40_CheckVersion"
static tcn00_Error cn40_CheckVersion
      ( const tsp00_DbNamec   szDBName)
{
  CONSOLE_TRACE_ENTER_CN00;

  tcn00_Error     nFuncReturn = OK_CN00;
  tsp00_Versionc  szMyVersion;
  tcn002_XpValueString szParamVersion;
  tsp00_DbNamec   szLocDBName = szDBName;

  if (cn20XParamGetValue(szLocDBName, PAN_PARAM_KERNELVERSION, szParamVersion) == OK_CN00) {
    sp100_GetVersionString(COMP_NAME_KERNEL_SP100, s100buildnumber, szMyVersion);

    if ((strncmp ( szParamVersion + BEG_OF_1ST_VERS_SUBSTR_SP100,
                    szMyVersion    + BEG_OF_1ST_VERS_SUBSTR_SP100,
                    END_OF_1ST_VERS_SUBSTR_SP100  - BEG_OF_1ST_VERS_SUBSTR_SP100   + 1 ) != 0 ) ||
        (strncmp ( szParamVersion + BEG_OF_2CND_VERS_SUBSTR_SP100,
                    szMyVersion    + BEG_OF_2CND_VERS_SUBSTR_SP100,
                    END_OF_2CND_VERS_SUBSTR_SP100 - BEG_OF_2CND_VERS_SUBSTR_SP100  + 1 ) != 0 )     ) {
      nFuncReturn = ERR_VERSION_CN00;
    } // end if
  } // end if

  return nFuncReturn;
} // cn40_CheckVersion

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_StartStopOptions
 * ------------------------------------------------------------------
 */
#undef  CN_FUNCTION
#define CN_FUNCTION "cn40_StartStopOptions"
static tcn00_Error cn40_StartStopOptions
      ( const char    * szParameters,
        tsp9_pgm_kind & pgmKind,
        bool          & bDump,
        char          * pRestart,
        bool          & bCluster )
{
  CONSOLE_TRACE_ENTER_CN00;

  tcn00_Error     nFuncReturn = OK_CN00;
  char            szToken   [PARAMETER_MAXLEN_CN90];
  char            szToken1  [PARAMETER_MAXLEN_CN90];
  int             nToken = 1;

  // init Options
  pgmKind    = csp9_any_pgm;
  bDump      = false;
  bCluster   = true;
  SAPDB_strcpy(pRestart, TXT_RESTART);

  while (cn90GetToken(szParameters, szToken, nToken, PARAMETER_MAXLEN_CN90) && nFuncReturn == OK_CN00) {

    if (stricmp(szToken, OPT_SPEED_FAST) == 0 || stricmp(szToken, OPTS_SPEED_FAST) == 0) {
      pgmKind = csp9_fast_pgm;
    } else if (stricmp(szToken, OPT_SPEED_QUICK) == 0 || stricmp(szToken, OPTS_SPEED_QUICK) == 0) {
      pgmKind = csp9_quick_pgm;
    } else if (stricmp(szToken, OPT_SPEED_SLOW) == 0 || stricmp(szToken, OPTS_SPEED_SLOW) == 0) {
      pgmKind = csp9_slow_pgm;
    } else if (stricmp(szToken, OPT_SPEED_TEST) == 0 || stricmp(szToken, OPTS_SPEED_TEST) == 0) {
      pgmKind = csp9_test_pgm;
    } else if (stricmp(szToken, OPT_STOP_DUMP) == 0 || stricmp(szToken, OPTS_STOP_DUMP) == 0) {
      bDump = true;
    } else if (stricmp(szToken, OPT_STOP_NOCLUSTER) == 0 || stricmp(szToken, OPTS_STOP_NOCLUSTER) == 0) {
      bCluster = false;
    } else if (stricmp(szToken, OPT_RESTART_UNTIL) == 0 || stricmp(szToken, OPTS_RESTART_UNTIL) == 0) {
      ++nToken;
      cn90GetToken(szParameters, szToken,  nToken, PARAMETER_MAXLEN_CN90);
      ++nToken;
      cn90GetToken(szParameters, szToken1, nToken, PARAMETER_MAXLEN_CN90);
      sp77sprintf(pRestart, PARAMETER_MAXLEN_CN90, TXT_RESTART_UNTIL, szToken, szToken1);
    } else {
      nFuncReturn = ERR_PARAM_CN00;
    } // end if

    ++nToken;
  } // end while

  return nFuncReturn;
} // cn40_StartStopOptions

  /* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn40_ChangeDBState
 * ------------------------------------------------------------------
 */
#undef  CN_FUNCTION
#define CN_FUNCTION "cn40_ChangeDBState"
static tcn00_Error cn40_ChangeDBState
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax,
        tcn00_DBState   targetState,
        bool            bStop)
{
  FUNCTION_DBG_MCN00_1("cn40_ChangeDBState");

  CONSOLE_TRACE_ENTER_CN00;

  tcn00_Error     nFuncReturn = OK_CN00;
  tsp9_pgm_kind   pgmKind;
  bool            bDump;
  bool            bCluster = false;
  char            szRestart [PARAMETER_MAXLEN_CN90] = "";
  tcn00_DBState   currentState;

  // read Options
  nFuncReturn = cn90AnswerIError(replyData, replyLen, cn40_StartStopOptions(command->args, pgmKind, bDump, szRestart, bCluster));

  if (nFuncReturn == OK_CN00) {
    currentState = cn90DBState(vcontrol->dbname);

    // cancel utility session
    if ( ( currentState == STATE_ONLINE_CN00 ||
           currentState == STATE_ADMIN_CN00    ) &&
         ( currentState != targetState        ) &&
         ( !bStop                             ) &&
         ( vcontrol->pUtilSession != NULL     )    ) {
         cn80UtilRelease(vcontrol, command, replyData, replyLen, replyLenMax);
    } // end if

    // cancel utility session memory
    if ( ( currentState == STATE_OFFLINE_CN00 ) &&
         ( vcontrol->pUtilSession != NULL     )    ) {
         cn80UtilRelease(vcontrol, command, replyData, replyLen, replyLenMax);
    } // end if

    currentState = bStop                              &&
//                   currentState != STATE_OFFLINE_CN00 &&
                   targetState == STATE_OFFLINE_CN00     ? STATE_ADMIN_CN00 :
                                                           currentState;

    // save the vtrace settings
    if ( ( currentState == STATE_ONLINE_CN00 ) &&
         ( currentState != targetState     )    ) {
      cn84SaveTrace(vcontrol->dbname);
    } // end if

    switch (currentState) {

      case STATE_OFFLINE_CN00:  // Ist

        switch (targetState) {
          case STATE_ADMIN_CN00:  // Soll
            nFuncReturn = cn40_OfflineToCold(vcontrol, pgmKind, replyData, replyLen);
            break;

          case STATE_ONLINE_CN00:  // Soll
            nFuncReturn = cn40_OfflineToCold(vcontrol, pgmKind, replyData, replyLen);
            if (nFuncReturn == OK_CN00) {
              nFuncReturn = cn40_ColdOrStandbyToWarm(vcontrol, szRestart, replyData, replyLen);
            } // end if
            break;

        } // end switch
        break;

      case STATE_ADMIN_CN00: // Ist

        switch (targetState) {
          case STATE_OFFLINE_CN00: // Soll
            nFuncReturn = cn40_ColdOrStandbyToOffline(vcontrol, bDump, replyData, replyLen);
            break;

          case STATE_ONLINE_CN00:    // Soll
            nFuncReturn = cn40_ColdOrStandbyToWarm(vcontrol, szRestart, replyData, replyLen);
            break;

        } // end switch
        break;

      case STATE_STANDBY_CN00: // Ist

        switch (targetState) {
          case STATE_OFFLINE_CN00: // Soll
            nFuncReturn = cn40_ColdOrStandbyToOffline(vcontrol, bDump, replyData, replyLen);
            break;

          case STATE_ONLINE_CN00:    // Soll
            nFuncReturn = cn40_ColdOrStandbyToWarm(vcontrol, TXT_TAKEOVER, replyData, replyLen);
            break;

        } // end switch
        break;

      case STATE_ONLINE_CN00: // Ist

        switch (targetState) {
          case STATE_OFFLINE_CN00: // Soll
            nFuncReturn = cn40_OnlineToOffline(vcontrol, bCluster, replyData, replyLen);
            break;

          case STATE_ADMIN_CN00:    // Soll
            nFuncReturn = cn40_OnlineToOffline(vcontrol, bCluster, replyData, replyLen);
            if (nFuncReturn == OK_CN00) {
              nFuncReturn = cn40_OfflineToCold(vcontrol, pgmKind, replyData, replyLen);
            } // end if
            break;

        } // end switch
        break;

      default:
        nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_STATE_CN00);
        break;
    } // end switch

  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if

  return nFuncReturn;
} // end cn40_ChangeDBState
