/* Client/server high level Bbuuzzb configuration API.
   Rick Smereka, Copyright (C) 1999-2004.

   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, get a copy via the Internet at
   http://gnu.org/copyleft/gpl.html or write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
   MA 02111-1307 USA

   You can contact the author via email at rsmereka@future-lab.com

   Original QNX version Feb/99, Rick Smereka

   Added session table and catalog 'get' and 'set'
   Ported to 32bit Windows under CodeWarrior V4.
   Mar/99, Rick Smereka

   Added log, session and catalog flag 'get' and 'set' functions
   Ported to HP-UX under GNU C 2.8.1.
   Apr/99, Rick Smereka

   Ported to Red Hat Linux 5.2, Jul/99, Rick Smereka

   Added functions 'db_config_get_replicate_flag' and
   'db_config_set_replicate_flag'. Jan/2002,
   Rick Smereka

   Ported to Debian Linux. Nov/2002, Rick Smereka

   Changed all logging calls from 'sys_log' to 'logman'.
   Changed function 'db_config_set_log' to send command
   'DBENG_SEND_SET_LOG' to the server.
   Mar/2004, Rick Smereka

   Added functions 'db_config_client_init', 'db_config_client_set_log',
   'db_config_client_set_log_flag', 'db_config_client_get_log' and
   'db_config_client_get_log_flag'. Added include 'appinit.h'.
   Added module globals 'dbcscfg_log_name' and 'dbcscfg_log_flag'.
   Apr/2004, Rick Smereka */

#include "stdhead.h"
#include "flsocket.h"
#include "appinit.h"
#include "dbmess.h"
#include "dbcscfg.h"

// module global data

char dbcscfg_log_name[128]; // client log name
int dbcscfg_log_flag;       // client log flag

int db_config_get_tmp_path(char *path)
{
   /* Load the value of the engine temporary file path into
      'path' which must already be allocated to sufficient
      size. Function returns 'DBENG_OK' upon success, an
      engine i/o code otherwise. */

   struct dbeng_send_message *slm;
   char mname[25];
   int size_s_mestruct;
   int ret;

   strcpy(mname, "db_config_get_tmp_path");
   logman("%s:enter", mname);

   if (path == (char *)NULL)
      return(DBENG_INVALID_FUNCTION);

   size_s_mestruct = sizeof(struct dbeng_send_message);
   path[0] = EOS;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_TMP_PATH;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_char(slm, path);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_log(char *slog)
{
   /* Load the value of the engine error log into
      'slog' which must already be allocated to sufficient
      size. Function returns 'DBENG_OK' upon success, an
      engine i/o code otherwise. */

   struct dbeng_send_message *slm;
   char mname[25];
   int size_s_mestruct;
   int ret;

   strcpy(mname, "db_config_get_log");
   logman("%s:enter", mname);

   if (slog == (char *)NULL)
      return(DBENG_INVALID_FUNCTION);

   size_s_mestruct = sizeof(struct dbeng_send_message);
   slog[0] = EOS;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_LOG;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_char(slm, slog);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_session(char *ses_table)
{
   /* Load the value of the engine session table into
      'ses_table' which must already be allocated to sufficient
      size. Function returns 'DBENG_OK' upon success, an
      engine i/o code otherwise. */

   struct dbeng_send_message *slm;
   char mname[] = "db_config_get_session";
   int size_s_mestruct;
   int ret;

   logman("%s:enter", mname);

   if (ses_table == (char *)NULL)
      return(DBENG_INVALID_FUNCTION);

   size_s_mestruct = sizeof(struct dbeng_send_message);
   ses_table[0] = EOS;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_SESSION;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_char(slm, ses_table);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_catalog(char *cat)
{
   /* Load the value of the engine catalog into 'cat'
      which must already be allocated to sufficient
      size. Function returns 'DBENG_OK' upon success, an
      engine i/o code otherwise. */

   struct dbeng_send_message *slm;
   char mname[] = "db_config_get_catalog";
   int size_s_mestruct;
   int ret;

   logman("%s:enter", mname);

   if (cat == (char *)NULL)
      return(DBENG_INVALID_FUNCTION);

   size_s_mestruct = sizeof(struct dbeng_send_message);
   cat[0] = EOS;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_CATALOG;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_char(slm, cat);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_log_flag(int *flag)
{
   /* Get the value of the current log flag.
      Function returns a 'dbeng' i/o code. */

   struct dbeng_send_message *slm;
   char mname[] = "db_config_get_log_flag";
   int size_s_mestruct;
   int ret;

   logman("%s:enter", mname);

   if (flag == (int *)NULL)
      return(DBENG_INVALID_FUNCTION);

   size_s_mestruct = sizeof(struct dbeng_send_message);
   *flag = 0;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_LOG_FLAG;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_int(slm, flag);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_session_flag(int *flag)
{
   /* Get the value of the current session flag.
      Function returns a 'dbeng' i/o code. */

   struct dbeng_send_message *slm;
   char mname[] = "db_config_get_session_flag";
   int size_s_mestruct;
   int ret;

   logman("%s:enter", mname);

   if (flag == (int *)NULL)
      return(DBENG_INVALID_FUNCTION);

   size_s_mestruct = sizeof(struct dbeng_send_message);
   *flag = 0;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_SESSION_FLAG;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_int(slm, flag);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_catalog_flag(int *flag)
{
   /* Get the value of the current catalog flag.
      Function returns a 'dbeng' i/o code. */

   struct dbeng_send_message *slm;
   char mname[] = "db_config_get_catalog_flag";
   int size_s_mestruct;
   int ret;

   logman("%s:enter", mname);

   if (flag == (int *)NULL)
      return(DBENG_INVALID_FUNCTION);

   size_s_mestruct = sizeof(struct dbeng_send_message);
   *flag = 0;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_CATALOG_FLAG;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_int(slm, flag);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_replicate_flag(int *flag)
{
   /* Get the value of the current replication flag.
      Function returns a 'dbeng' i/o code. */

   struct dbeng_send_message *slm;
   char mname[] = "db_config_get_replicate_flag";
   int size_s_mestruct;
   int ret;

   logman("%s:enter", mname);

   if (flag == (int *)NULL)
      {
      db_io_code_log(mname, "exit:null[flag]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   *flag = 0;

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_REPLICATE_FLAG;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_int(slm, flag);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_get_version(char *ver)
{
   /* Get the 'dbeng' version ID string. Function returns
      'DBENG_OK' upon success with the version string
      loaded into 'ver' which must already be allocated
      to sufficient size. Function returns a 'dbeng'
      i/o code otherwise. */
      
   struct dbeng_send_message *slm;
   char mname[] = "db_config_get_version";
   int size_s_mestruct;
   int ret;

   logman("%s:enter", mname);
   
   if (ver == (char *)NULL)
      {
      db_io_code_log(mname, "null[ver]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }
      
   size_s_mestruct = sizeof(struct dbeng_send_message);

   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_GET_DBENG_VERSION;
   strcpy(slm->dbc, "dummy");
   ret = db_cs_char(slm, ver);
   free(slm);
   logman("%s:normal exit", mname);
   return(DBENG_OK);
}

int db_config_set_tmp_path(char *path)
{
   /* Set the path for 'dbeng' temporary files to
      'path'. Function returns 'DBENG_OK' upon
      success, an engine code otherwise. */

   struct dbeng_send_message *slm;
   char mname[25];
   int size_s_mestruct;
   int ret;
   
   strcpy(mname, "db_config_set_tmp_path");
   logman("%s:enter", mname);

   if (path == NULL)
      {
      db_io_code_log(mname, "null[path]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   if (!strlen(path))
      {
      db_io_code_log(mname, "empty[path]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_TMP_PATH;
   sprintf(slm->dbc, "'%s'", path);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

int db_config_set_log(char *lname)
{
   /* Set the logging name. Function returns
      a 'dbeng' code. */
      
   struct dbeng_send_message *slm;
   char mname[] = "db_config_set_log";
   int size_s_mestruct;
   int ret;
   
   logman("%s:enter", mname);

   if (lname == NULL)
      {
      db_io_code_log(mname, "null[lname]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   if (!strlen(lname))
      {
      db_io_code_log(mname, "empty[lname]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_LOG;
   sprintf(slm->dbc, "'%s'", lname);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

int db_config_set_session(char *ses_table)
{
   /* Set the path/file for the 'dbeng' session table to
      'ses_table'. Function returns 'DBENG_OK' upon
      success, an engine code otherwise. */

   struct dbeng_send_message *slm;
   char mname[30];
   int size_s_mestruct;
   int ret;
   
   strcpy(mname, "db_config_set_session_table");
   logman("%s:enter", mname);

   if (ses_table == NULL)
      {
      db_io_code_log(mname, "null[ses_table]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   if (!strlen(ses_table))
      {
      db_io_code_log(mname, "empty[ses_table]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_SESSION;
   sprintf(slm->dbc, "'%s'", ses_table);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

int db_config_set_catalog(char *cat)
{
   /* Set the path/file for the 'dbeng' catalog to
      'cat'. Function returns 'DBENG_OK' upon
      success, an engine code otherwise. */

   struct dbeng_send_message *slm;
   char mname[25];
   int size_s_mestruct;
   int ret;
   
   strcpy(mname, "db_config_set_catalog");
   logman("%s:enter", mname);

   if (cat == NULL)
      {
      db_io_code_log(mname, "null[cat]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   if (!strlen(cat))
      {
      db_io_code_log(mname, "empty[cat]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_CATALOG;
   sprintf(slm->dbc, "'%s'", cat);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

int db_config_set_log_flag(int flag)
{
   /* Set the engine log flag. 'flag' must be zero
      or one. Function returns an engine i/o code. */
      
   struct dbeng_send_message *slm;
   char mname[] = "db_config_set_log_flag";
   int size_s_mestruct;
   int ret;
   
   logman("%s:enter", mname);

   if (flag != TRUE && flag != FALSE)
      {
      db_io_code_log(mname, "out of range[flag]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_LOG_FLAG;
   sprintf(slm->dbc, "%d", flag);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

int db_config_set_session_flag(int flag)
{
   /* Set the engine session flag. 'flag' must be zero
      or one. Function returns an engine i/o code. */
      
   struct dbeng_send_message *slm;
   char mname[] = "db_config_set_session_flag";
   int size_s_mestruct;
   int ret;
   
   logman("%s:enter", mname);

   if (flag != TRUE && flag != FALSE)
      {
      db_io_code_log(mname, "out of range[flag]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_SESSION_FLAG;
   sprintf(slm->dbc, "%d", flag);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

int db_config_set_catalog_flag(int flag)
{
   /* Set the engine catalog flag. 'flag' must be zero
      or one. Function returns an engine i/o code. */
      
   struct dbeng_send_message *slm;
   char mname[] = "db_config_set_catalog_flag";
   int size_s_mestruct;
   int ret;
   
   logman("%s:enter", mname);

   if (flag != TRUE && flag != FALSE)
      {
      db_io_code_log(mname, "out of range[flag]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_CATALOG_FLAG;
   sprintf(slm->dbc, "%d", flag);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

int db_config_set_replicate_flag(int flag)
{
   /* Set the engine replication flag. 'flag' must be zero
      or one. Function returns an engine i/o code. */
      
   struct dbeng_send_message *slm;
   char mname[] = "db_config_set_replicate_flag";
   int size_s_mestruct;
   int ret;
   
   logman("%s:enter", mname);

   if (flag != TRUE && flag != FALSE)
      {
      db_io_code_log(mname, "out of range[flag]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   size_s_mestruct = sizeof(struct dbeng_send_message);
   
   if ((slm = malloc(size_s_mestruct)) == NULL)
      {
      db_io_code_log(mname, "alloc fail[slm]", DBENG_MEMORY_FAIL);
      return(DBENG_MEMORY_FAIL);
      }

   slm->type = DBENG_SEND_SET_REPLICATE_FLAG;
   sprintf(slm->dbc, "%d", flag);
   ret = db_cs_code(slm);
   free(slm);
   db_io_code_log(mname, "normal exit", ret);
   return(ret);
}

void db_config_client_init(void)
{
   // Initialize the client logging data.

   dbcscfg_log_name[0] = EOS;
   dbcscfg_log_flag = FALSE;
}

int db_config_client_set_log(char *name)
{
   /* Set the client log name. Function returns a
      'dbeng' code. */

   char mname[] = "db_config_client_set_log";
   
   logman("%s:enter", mname);

   if (name == (char *)NULL || !strlen(name))
      {
      db_io_code_log(mname, "null[name]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   strcpy(dbcscfg_log_name, name);
   db_io_code_log(mname, "normal exit", DBENG_OK);
   return(DBENG_OK);
}

int db_config_client_set_log_flag(int flag)
{
   /* Set the client log flag. Function returns a
      'dbeng' code. */

   char mname[] = "db_config_client_set_log_flag", *ap;
   
   logman("%s:enter", mname);

   if (flag != TRUE && flag != FALSE)
      {
      db_io_code_log(mname, "out of range[flag]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   if (flag)
      {
      if ((ap = (char *)malloc(DBENG_PATH_LIMIT)) == (char *)NULL)
         {
         db_io_code_log(mname, "exit:alloc fail[ap]", DBENG_MEMORY_FAIL);
         return(DBENG_MEMORY_FAIL);
         }

      if (!appinit_get_name(ap))
         {
         free(ap);
         db_io_code_log(mname, "exit:bad rc[FALSE] from appinit_get_name",
                        DBENG_INVALID_FUNCTION);
         return(DBENG_INVALID_FUNCTION);
         }

      if (logman_start(dbcscfg_log_name, ap))
         {
         free(ap);
         db_io_code_log(mname, "exit:bad rc[TRUE] from logman start",
                        DBENG_CONFIG_INVALID_LOG);
         return(DBENG_CONFIG_INVALID_LOG);
         }

      free(ap);
      }
   else
      logman_end();

   dbcscfg_log_flag = flag;
   db_io_code_log(mname, "normal exit", DBENG_OK);
   return(DBENG_OK);
}

int db_config_client_get_log(char *name)
{
   /* Get the current client log name. Function returns the log
      name in 'name' upon success. Function returns a 'dbeng'
      code. */

   char mname[] = "db_config_client_get_log";

   logman("%s:enter", mname);

   if (name == (char *)NULL)
      {
      db_io_code_log(mname, "exit:null[name]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   name[0] = EOS;
   strcpy(name, dbcscfg_log_name);
   db_io_code_log(mname, "normal exit", DBENG_OK);
   return(DBENG_OK);
}

int db_config_client_get_log_flag(int *flag)
{
   /* Get the value of the current client log flag.
      Function returns a 'dbeng' code. */

   char mname[] = "db_config_client_get_log_flag";

   logman("%s:enter", mname);

   if (flag == (int *)NULL)
      {
      db_io_code_log(mname, "exit:null[flag]", DBENG_INVALID_FUNCTION);
      return(DBENG_INVALID_FUNCTION);
      }

   *flag = dbcscfg_log_flag;
   db_io_code_log(mname, "normal exit", DBENG_OK);
   return(DBENG_OK);
}

