/***************************************
  $Revision: 1.8 $

  Constants module (co) - this _should_ eventually get merged in with the
  config module.

  Status: NOT REVUED, NOT TESTED

  +html+ <DL COMPACT>
  +html+ <DT>Online References: 
  +html+ <DD><UL>
  +html+ </UL>
  +html+ </DL>
  +html+ <PRE>
  Instructions for use:

    To add a constant:
      0. Add a default value for the constant. (string)
      1. Add the constant declaration to the _Constants struct.
      2. Add a CO_get_function()
      3. Add initializing code to init_constants()

    To access the constant:
      use the CO_get<Constant>() function from your other code.
  +html+ </PRE>
 
  ******************/ /******************
  Filename            : constants.c
  Author              : ottrey@ripe.net
  OSs Tested          : Solaris
  Related Modules     : Used in conjunction with the properties module.
  Problems            : 
  To Do               : Merge into a "config module"
  Comments            :
  ******************/ /******************
  Copyright (c) 1999                              RIPE NCC
 
  All Rights Reserved
  
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose and without fee is hereby granted,
  provided that the above copyright notice appear in all copies and that
  both that copyright notice and this permission notice appear in
  supporting documentation, and that the name of the author not be
  used in advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.
  
  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  ***************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "properties.h"

/*+ Maximum number of constants. +*/
#define MAX_CONSTS 100

/*+ Default values for constants. +*/
#define DEFLT_MAX_THREADS     "10"
#define DEFLT_WHOIS_PORT      "0"
#define DEFLT_CONFIG_PORT     "0"
#define DEFLT_MIRROR_PORT     "0"
#define DEFLT_HOST            "mysql.database.net"
#define DEFLT_USER            "xxx"
#define DEFLT_PASSWORD        "xxx"
#define DEFLT_DATABASE_PORT   "3306"
#define DEFLT_DATABASE        "RIPE"
#define DEFLT_QUERY           "SHOW TABLES"
#define DEFLT_IN_QUERY        "SELECT * FROM inetnum"
#define DEFLT_RT_QUERY        "SELECT * FROM route"
#define DEFLT_AUTHENTICATE    "0"
#define DEFLT_WHOIS_SUSPENDED "0"
#define DEFLT_WELCOME         "Welcome to the whois R.I.P. server.\n"
#define DEFLT_PROMPT          "whois R.I.P. config> "
#define DEFLT_CLEAR_SCREEN    "0"
#define DEFLT_SLEEP_TIME      "1"
#define DEFLT_ACCOUNTING      "0"
#define DEFLT_QUERY_LOGGING   "1"
#define DEFLT_QUERY_LOGFILE   "stdout"
#define DEFLT_INSTR_LOGGING   "1"
#define DEFLT_INSTR_LOGFILE   "stdout"
#define DEFLT_COMND_LOGGING   "1"
#define DEFLT_COMND_LOGFILE   "stdout"
#define DEFLT_TESTS_LOGGING   "1"
#define DEFLT_TESTS_LOGFILE   "stdout"
#define DEFLT_THREAD_LOGGING  "1"
#define DEFLT_THREAD_LOGFILE  "stdout"
#define DEFLT_SOCKET_LOGGING  "1"
#define DEFLT_SOCKET_LOGFILE  "stdout"
#define DEFLT_CONFIG_LOGGING  "1"
#define DEFLT_CONFIG_LOGFILE  "stdout"


/*+ Each constant has a +*/
struct _constant {
  const char *token;              /*+ Token to be found in properties file. +*/
  const char *deflt;                    /*+ Default value for the constant. +*/
  int (*set_func)(void *, char *);        /*+ Function to set the constant. +*/
  void *constant_ptr;                     /*+ Pointer to the constant value +*/
  char *(*show_func)(void *);            /*+ Function to show the constant. +*/
};


/*+ The Constants array has a +*/
typedef struct _Constants {
  int  max_threads[1];             /*+ Maximum number of server threads. +*/ 
  char  whois_port[64];   /*+ Port for whois clients to rendezvous with. +*/
  char  config_port[64]; /*+ Port for config clients to rendezvous with. +*/
  char  mirror_port[64]; /*+ Port for mirror clients to rendezvous with. +*/
  char  host[64];                             /*+ Host for the database. +*/
  char  user[64];                             /*+ User for the database. +*/
  char  password[64];                     /*+ Password for the database. +*/
  int  database_port[1];                      /*+ Port for the database. +*/
  char  database[64];                                 /*+ Database name. +*/
  char  query[1024];                         /*+ Query for the database. +*/
  char  in_query[1024];     /*+ Query for the radix tree initialization. +*/
  char  rt_query[1024];     /*+ Query for the radix tree initialization. +*/
  int   authenticate[1];                         /*+ Authenticate users. +*/
  int   whois_suspended[1];                /*+ Suspend the whois server. +*/
  char  welcome[1024];                  /*+ Welcome for config protocol. +*/
  char  prompt[1024];                    /*+ Prompt for config protocol. +*/
  int   clear_screen[1];         /*+ Clear screen after config commands. +*/
  int   sleep_time[1];  /*+ Sleep time (in sec) between config commands. +*/
  int   accounting[1];          /*+ Conduct accounting on whois queries. +*/
  int   query_logging[1];                       /*+ Log the SQL queries. +*/
  char  query_logfile[1024];         /*+ Query logfile for the database. +*/
  int   instr_logging[1];                    /*+ Log the whois instrucs. +*/
  char  instr_logfile[1024];   /*+ Query logfile for the whois instrucs. +*/
  int   comnd_logging[1];                    /*+ Log the whois commands. +*/
  char  comnd_logfile[1024];   /*+ Query logfile for the whois commands. +*/
  int   tests_logging[1];                       /*+ Log the whois tests. +*/
  char  tests_logfile[1024];      /*+ Query logfile for the whois tests. +*/
  int   thread_logging[1];                    /*+ Log the whois threads. +*/
  char  thread_logfile[1024];   /*+ Query logfile for the whois threads. +*/
  int   socket_logging[1];                           /*+ Log the socket. +*/
  char  socket_logfile[1024];                /*+ Logfile for the socket. +*/
  int   config_logging[1];                           /*+ Log the config. +*/
  char  config_logfile[1024];                /*+ Logfile for the config. +*/
} *Constants;


/*
 * Global Variables
 */
/*+ The array of Global Constants. +*/
static Constants  Global_constants=NULL;

/* 
 * Set Functions
 */
static int set_string(void *constant, char *value) {

  strcpy((char *)constant, value);

  return 0;
} /* set_string() */

static int set_int(void *constant, char *value) {
  int i;
  
  i = atol(value);
  ((int *)constant)[0] = i;

  return 0;
} /* set_int() */

static int set_boolean(void *constant, char *value) {
  int result=1;
  int i;
  
  i = atol(value);

  /* If a valid boolean */
  if ( (i == 0) || (i == 1)) {
    ((int *)constant)[0] = i;
    result = 0;
  }

  return result;
} /* set_boolean() */


/* 
 * Show Functions
 */
static char *show_string(void *constant) {
  return((char *)constant);
} /* show_string() */

static char *show_int(void *constant) {
  char *tmp;

  tmp = calloc(1, 64);
  sprintf(tmp, "%d", ((int *)constant)[0]);
  return tmp;
} /* show_int() */

static char *show_boolean(void *constant) {
  char *tmp;

  tmp = calloc(1, 64);
  sprintf(tmp, "%d", ((int *)constant)[0]);
  return tmp;
} /* show_boolean() */


/* 
 * Get Functions
 */
int CO_get_max_threads() {
  return Global_constants->max_threads[0];
}

const char *CO_get_whois_port() {
  return Global_constants->whois_port;
}

const char *CO_get_config_port() {
  return Global_constants->config_port;
}

const char *CO_get_mirror_port() {
  return Global_constants->mirror_port;
}

const char *CO_get_host() {
  return Global_constants->host;
}

const char *CO_get_user() {
  return Global_constants->user;
}

const char *CO_get_password() {
  return Global_constants->password;
}

int CO_get_database_port() {
  return Global_constants->database_port[0];
}

const char *CO_get_database() {
  return Global_constants->database;
}

const char *CO_get_query() {
  return Global_constants->query;
}

const char *CO_get_in_query() {
  return Global_constants->in_query;
}

const char *CO_get_rt_query() {
  return Global_constants->rt_query;
}

int CO_get_authenticate() {
  return Global_constants->authenticate[0];
}

int CO_get_whois_suspended() {
  return Global_constants->whois_suspended[0];
}

const char *CO_get_welcome() {
  return Global_constants->welcome;
}

const char *CO_get_prompt() {
  return Global_constants->prompt;
}

int CO_get_clear_screen() {
  return Global_constants->clear_screen[0];
}

int CO_get_sleep_time() {
  return Global_constants->sleep_time[0];
}

int CO_get_accounting() {
  return Global_constants->accounting[0];
}

int CO_get_query_logging() {
  return Global_constants->query_logging[0];
}

const char *CO_get_query_logfile() {
  return Global_constants->query_logfile;
}

int CO_get_instr_logging() {
  return Global_constants->instr_logging[0];
}

const char *CO_get_instr_logfile() {
  return Global_constants->instr_logfile;
}

int CO_get_comnd_logging() {
  return Global_constants->comnd_logging[0];
}

const char *CO_get_comnd_logfile() {
  return Global_constants->comnd_logfile;
}

int CO_get_tests_logging() {
  return Global_constants->tests_logging[0];
}

const char *CO_get_tests_logfile() {
  return Global_constants->tests_logfile;
}

int CO_get_thread_logging() {
  return Global_constants->thread_logging[0];
}

const char *CO_get_thread_logfile() {
  return Global_constants->thread_logfile;
}

int CO_get_socket_logging() {
  return Global_constants->socket_logging[0];
}

const char *CO_get_socket_logfile() {
  return Global_constants->socket_logfile;
}

int CO_get_config_logging() {
  return Global_constants->config_logging[0];
}

const char *CO_get_config_logfile() {
  return Global_constants->config_logfile;
}


/*+
 * Contains the constant definitions for the Token, set_function, show_function.
 * (See: _constant)
+*/
static struct _constant constant[MAX_CONSTS];

/* init_constants() */
/*++++++++++++++++++++++++++++++++++++++
  Initialize all the constants.

  More:
  +html+ <PRE>
  Authors:
        ottrey

  +html+ </PRE><DL COMPACT>
  +html+ <DT>Online References:
  +html+ <DD><UL>
  +html+ </UL></DL>

  ++++++++++++++++++++++++++++++++++++++*/
static void init_constants(void) {
  int n=0;

  constant[n].token="SV.max_threads";
  constant[n].deflt=DEFLT_MAX_THREADS;
  constant[n].set_func=set_int;
  constant[n].constant_ptr=Global_constants->max_threads;
  constant[n].show_func=show_int;
  n++;

  constant[n].token="SV.whois_port";
  constant[n].deflt=DEFLT_WHOIS_PORT;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->whois_port;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="SV.config_port";
  constant[n].deflt=DEFLT_CONFIG_PORT;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->config_port;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="SV.mirror_port";
  constant[n].deflt=DEFLT_MIRROR_PORT;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->mirror_port;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="DB.host";
  constant[n].deflt=DEFLT_HOST;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->host;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="DB.user";
  constant[n].deflt=DEFLT_USER;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->user;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="DB.password";
  constant[n].deflt=DEFLT_PASSWORD;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->password;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="DB.database_port";
  constant[n].deflt=DEFLT_DATABASE_PORT;
  constant[n].set_func=set_int;
  constant[n].constant_ptr=Global_constants->database_port;
  constant[n].show_func=show_int;
  n++;

  constant[n].token="DB.database";
  constant[n].deflt=DEFLT_DATABASE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->database;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="DB.query";
  constant[n].deflt=DEFLT_QUERY;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->query;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="RX.in_query";
  constant[n].deflt=DEFLT_IN_QUERY;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->in_query;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="RX.rt_query";
  constant[n].deflt=DEFLT_RT_QUERY;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->rt_query;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="SV.authenticate";
  constant[n].deflt=DEFLT_AUTHENTICATE;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->authenticate;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="SV.whois_suspended";
  constant[n].deflt=DEFLT_WHOIS_SUSPENDED;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->whois_suspended;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="PC.welcome";
  constant[n].deflt=DEFLT_WELCOME;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->welcome;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="PC.prompt";
  constant[n].deflt=DEFLT_PROMPT;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->prompt;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="PC.clear_screen";
  constant[n].deflt=DEFLT_CLEAR_SCREEN;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->clear_screen;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="PC.sleep_time";
  constant[n].deflt=DEFLT_SLEEP_TIME;
  constant[n].set_func=set_int;
  constant[n].constant_ptr=Global_constants->sleep_time;
  constant[n].show_func=show_int;
  n++;

  constant[n].token="WQ.accounting";
  constant[n].deflt=DEFLT_ACCOUNTING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->accounting;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.query_logging";
  constant[n].deflt=DEFLT_QUERY_LOGGING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->query_logging;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.query_logfile";
  constant[n].deflt=DEFLT_QUERY_LOGFILE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->query_logfile;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="LO.instr_logging";
  constant[n].deflt=DEFLT_INSTR_LOGGING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->instr_logging;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.insrt_logfile";
  constant[n].deflt=DEFLT_INSTR_LOGFILE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->instr_logfile;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="LO.comnd_logging";
  constant[n].deflt=DEFLT_COMND_LOGGING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->comnd_logging;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.comnd_logfile";
  constant[n].deflt=DEFLT_COMND_LOGFILE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->comnd_logfile;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="LO.tests_logging";
  constant[n].deflt=DEFLT_TESTS_LOGGING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->tests_logging;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.tests_logfile";
  constant[n].deflt=DEFLT_TESTS_LOGFILE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->tests_logfile;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="LO.thread_logging";
  constant[n].deflt=DEFLT_THREAD_LOGGING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->thread_logging;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.thread_logfile";
  constant[n].deflt=DEFLT_THREAD_LOGFILE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->thread_logfile;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="LO.socket_logging";
  constant[n].deflt=DEFLT_SOCKET_LOGGING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->socket_logging;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.socket_logfile";
  constant[n].deflt=DEFLT_SOCKET_LOGFILE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->socket_logfile;
  constant[n].show_func=show_string;
  n++;

  constant[n].token="LO.config_logging";
  constant[n].deflt=DEFLT_CONFIG_LOGGING;
  constant[n].set_func=set_boolean;
  constant[n].constant_ptr=Global_constants->config_logging;
  constant[n].show_func=show_boolean;
  n++;

  constant[n].token="LO.config_logfile";
  constant[n].deflt=DEFLT_CONFIG_LOGFILE;
  constant[n].set_func=set_string;
  constant[n].constant_ptr=Global_constants->config_logfile;
  constant[n].show_func=show_string;
  n++;

  constant[n].token=NULL;

} /* init_constants() */


/* CO_to_string() */
/*++++++++++++++++++++++++++++++++++++++
  Returns the constants as a string.

  More:
  +html+ <PRE>
  Authors:
        ottrey

  +html+ </PRE><DL COMPACT>
  +html+ <DT>Online References:
  +html+ <DD><UL>
  +html+ </UL></DL>

  ++++++++++++++++++++++++++++++++++++++*/
char *CO_to_string(void) {
  char *consts;
  const char *token;
  char *value;
  char tmp_consts[1024];
  char tmp_const[128];
  int i=0;

  sprintf(tmp_consts, "Constants = { ");
  while(constant[i].token != NULL) {
    token = constant[i].token;
    value = constant[i].show_func(constant[i].constant_ptr);
    sprintf(tmp_const, "\n[%s]=\"%s\"", token, value);
    strcat(tmp_consts, tmp_const);
    i++;
  }
  strcat(tmp_consts, "}");

  consts = calloc(1, strlen(tmp_consts)+1);
  strcpy(consts, tmp_consts);

  return consts;
} /* CO_to_string() */


char *CO_const_to_string(char *name) {
  char *result=NULL;
  int i;
  
  for (i=0; constant[i].token != NULL; i++) {
    if (strcmp(constant[i].token, name) == 0) {
      result = constant[i].show_func(constant[i].constant_ptr);
      break;
    }
  }

  return result;
} /* CO_const_to_string() */

 /* CO_set_const() */
/*++++++++++++++++++++++++++++++++++++++
  Sets the value of one constant.  Returns 0 if no error.

  More:
  +html+ <PRE>
  Authors:
        ottrey

  +html+ </PRE><DL COMPACT>
  +html+ <DT>Online References:
  +html+ <DD><UL>
  +html+ </UL></DL>

  ++++++++++++++++++++++++++++++++++++++*/
int CO_set_const(char *name, char *value) {
  int result=1;
  int i;
  
  for (i=0; constant[i].token != NULL; i++) {
    if (strcmp(constant[i].token, name) == 0) {
      result = constant[i].set_func((void *)constant[i].constant_ptr, value);
      break;
    }
  }

  return result;
} /* CO_set_const() */


/* CO_set() */
/*++++++++++++++++++++++++++++++++++++++
  Sets the constants from the properties module.
  Returns the number of constants set.

  More:
  +html+ <PRE>
  Authors:
        ottrey
  +html+ </PRE><DL COMPACT>
  +html+ <DT>Online References:
  +html+ <DD><UL>
  +html+   <LI><A HREF="../src/.properties">.properties</A>
  +html+ </UL></DL>

  ++++++++++++++++++++++++++++++++++++++*/
char *CO_set(void) {
  int i;
  int set_count=0;
  int set;
  char result_buff[256];
  char *result;
  char *property;

  /* Initialize if necessary */
  if (Global_constants == NULL) {
    Global_constants = (Constants)calloc(1, sizeof(struct _Constants));
    init_constants();
  }

  for (i=0; constant[i].token != NULL; i++) {
    property = PR_get_property(constant[i].token, constant[i].deflt);
    set = constant[i].set_func((void *)constant[i].constant_ptr, property);
    if (set == 0) {
      set_count++;
    }
  }

  sprintf(result_buff, "%d out of %d constant(s) set.", set_count, i);

  result = (char *)calloc(1, strlen(result_buff)+1);
  strcpy(result, result_buff);

  return result;
} /* CO_set() */

