Logo Search packages:      
Sourcecode: samhain version File versions  Download package

sh_database.c

/* SAMHAIN file system integrity testing                                   */
/* Copyright (C) 2001 Rainer Wichmann                                      */
/*                                                                         */
/*  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., 675 Mass Ave, Cambridge, MA 02139, USA.              */

#include "config_xor.h"

#include <stdio.h>     
#include <stdlib.h>     
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>

#ifdef WITH_DATABASE

/* define this if you want to debug the Oracle database support */
/* #define DB_DEBUG  */

#include "samhain.h"

#include "sh_cat.h"
#include "sh_error.h"
#include "sh_utils.h"

#undef  FIL__
#define FIL__  _("sh_database.c")

typedef struct my_attr_ 
{
  char * attr;
  char * attr_o;
  int    inHash;
  int    val;
  int    size;
  size_t off;
} my_attr;

typedef struct dbins_ {
  struct dbins_ * next;
  char            host[64];
  char            time[20];
  char            msg[1024];
  char            sev[8];
  char            path[12288];
  char            user[9];
  char            group[9];
  char            program[8];
  char            subroutine[16];
  char            status[12];
  char            hash[50];
  char            path_data[1024];
  char            hash_data[50];
  char            key_uid[64];
  char            key_uid_data[64];
  char            key_id[16];
  char            module[8];
  char            syscall[16];
  char            ip[16];     
  char            tty[16];    
  char            peer[64];
  char            fromhost[64];
  char            obj[1024];   
  char            interface[64];   
  char            ltime[64];   
  char            dir[1024];   
  char            linked_path[1024]; 
  char            service[64];   
  char            facility[32];   
  char            priority[32];   
  char            syslog_msg[1024];

  char            mode_old[16];
  char            mode_new[16];
  char            attr_old[16];
  char            attr_new[16];
  char            device_old[16];
  char            device_new[16];
  char            owner_old[9];
  char            owner_new[9];
  char            group_old[9];
  char            group_new[9];
  char            ctime_old[20];
  char            ctime_new[20];
  char            atime_old[20];
  char            atime_new[20];
  char            mtime_old[20];
  char            mtime_new[20];
  char            chksum_old[50];
  char            chksum_new[50];
  char            link_old[1024];
  char            link_new[1024];

  long            long_data[20];

  /*
  long            size_old;
  long            size_new;
  long            hardlinks_old;
  long            hardlinks_new;
  long            inode_old;
  long            inode_new;
  */

} dbins;

static my_attr attr_tab[] = {
  { NULL, N_("sev"),         0,   1,    8, offsetof(struct dbins_, sev) },
  { NULL, N_("tstamp"),      0,   2,   16, offsetof(struct dbins_, time) },
  { NULL, N_("remote_host"), 0,   3,   64, offsetof(struct dbins_, host) },
  { NULL, N_("msg"),         0,   4, 1024, offsetof(struct dbins_, msg) },

  { NULL, N_("path"),        0,   5,12288, offsetof(struct dbins_, path)  },
  /* username -> userid; replace (long) 'userid' - below - by 'dummy' */ 
  { NULL, N_("userid"),      0,   6,    9, offsetof(struct dbins_, user)  },
  { NULL, N_("group"),       0,   7,    9, offsetof(struct dbins_, group)  },
  { NULL, N_("program"),     0,   8,    8, offsetof(struct dbins_, program)  },
  { NULL, N_("subroutine"),  0,   9,   16, offsetof(struct dbins_, subroutine)},
  { NULL, N_("status"),      0,  10,   12, offsetof(struct dbins_, status)  },
  { NULL, N_("hash"),        0,  11,   50, offsetof(struct dbins_, hash)  },
  { NULL, N_("path_data"),   0,  12, 1024, offsetof(struct dbins_, path_data)  },
  { NULL, N_("hash_data"),   0,  13,   50, offsetof(struct dbins_, hash_data)  },
  { NULL, N_("key_uid"),     0,  14,   64, offsetof(struct dbins_, key_uid)  },
  { NULL, N_("key_uid_data"),0,  15,   64, offsetof(struct dbins_, key_uid_data)},
  { NULL, N_("key_id"),      0,  16,   16, offsetof(struct dbins_, key_id)  },
  { NULL, N_("module"),      0,  17,    8, offsetof(struct dbins_, module)  },
  { NULL, N_("syscall"),     0,  19,   16, offsetof(struct dbins_, syscall)  },
  { NULL, N_("ip"),          0,  20,   16, offsetof(struct dbins_, ip)  },
  { NULL, N_("tty"),         0,  21,   16, offsetof(struct dbins_, tty)  },
  { NULL, N_("peer"),        0,  22,   64, offsetof(struct dbins_, peer)  },
  { NULL, N_("obj"),         0,  23, 1024, offsetof(struct dbins_, obj)  },
  { NULL, N_("interface"),   0,  24,   64, offsetof(struct dbins_, interface)},
  { NULL, N_("time"),        0,  25,   64, offsetof(struct dbins_, ltime)  },
  { NULL, N_("dir"),         0,  26, 1024, offsetof(struct dbins_, dir)  },
  { NULL, N_("linked_path"), 0,  27, 1024, offsetof(struct dbins_, linked_path)},
  { NULL, N_("service"),     0,  29,   64, offsetof(struct dbins_, service)},
  { NULL, N_("facility"),    0,  30,   32, offsetof(struct dbins_, facility) },
  { NULL, N_("priority"),    0,  31,   32, offsetof(struct dbins_, priority) },
  { NULL, N_("syslog_msg"),  0,  32, 1024, offsetof(struct dbins_, syslog_msg)  },

  { NULL, N_("mode_old"),    0,  33,   16, offsetof(struct dbins_, mode_old) },
  { NULL, N_("mode_new"),    0,  34,   16, offsetof(struct dbins_, mode_new) },
  { NULL, N_("device_old"),  0,  35,   16, offsetof(struct dbins_, device_old)}, 
  { NULL, N_("device_new"),  0,  36,   16, offsetof(struct dbins_, device_new)},
  { NULL, N_("owner_old"),   0,  37,    9, offsetof(struct dbins_, owner_old)},
  { NULL, N_("owner_new"),   0,  38,    9, offsetof(struct dbins_, owner_new)},
  { NULL, N_("group_old"),   0,  39,    9, offsetof(struct dbins_, group_old)},
  { NULL, N_("group_new"),   0,  40,    9, offsetof(struct dbins_, group_new)},
  { NULL, N_("ctime_old"),   0,  41,   20, offsetof(struct dbins_, ctime_old)},
  { NULL, N_("ctime_new"),   0,  42,   20, offsetof(struct dbins_, ctime_new)},
  { NULL, N_("atime_old"),   0,  43,   20, offsetof(struct dbins_, atime_old)},
  { NULL, N_("atime_new"),   0,  44,   20, offsetof(struct dbins_, atime_new)},
  { NULL, N_("mtime_old"),   0,  45,   20, offsetof(struct dbins_, mtime_old)},
  { NULL, N_("mtime_new"),   0,  46,   20, offsetof(struct dbins_, mtime_new)},
  { NULL, N_("chksum_old"),  0,  47,   50, offsetof(struct dbins_, chksum_old)},
  { NULL, N_("chksum_new"),  0,  48,   50, offsetof(struct dbins_, chksum_new)},
  { NULL, N_("link_old"),    0,  49, 1024, offsetof(struct dbins_, link_old)},
  { NULL, N_("link_new"),    0,  50, 1024, offsetof(struct dbins_, link_new)},
               
  { NULL, N_("size_old"),     0,  51,    0, 0  },
  { NULL, N_("size_new"),     0,  52,    0, 0  },
  { NULL, N_("hardlinks_old"),0,  53,    0, 0  },
  { NULL, N_("hardlinks_new"),0,  54,    0, 0  },
  { NULL, N_("inode_old"),    0,  55,    0, 0  }, 
  { NULL, N_("inode_new"),    0,  56,    0, 0  }, 

  { NULL, N_("imode_old"),    0,  57,    0, 0  },
  { NULL, N_("imode_new"),    0,  58,    0, 0  },
  { NULL, N_("iattr_old"),    0,  59,    0, 0  },
  { NULL, N_("iattr_new"),    0,  60,    0, 0  },
  { NULL, N_("idevice_old"),  0,  61,    0, 0  }, 
  { NULL, N_("idevice_new"),  0,  62,    0, 0  }, 
  { NULL, N_("iowner_old"),   0,  63,    0, 0  },
  { NULL, N_("iowner_new"),   0,  64,    0, 0  },
  { NULL, N_("igroup_old"),   0,  65,    0, 0  },
  { NULL, N_("igroup_new"),   0,  66,    0, 0  },

  { NULL, N_("port"),         0,  67,    0, 0  },
  { NULL, N_("return_code"),  0,  68,    0, 0  },
  /* { NULL, N_("userid"),        0,  69,    0, 0  }, old 'userid', 1.8.1 */

  { NULL, N_("host"),         0,  70,   64, offsetof(struct dbins_, fromhost)},
  { NULL, N_("attr_old"),     0,  71,   16, offsetof(struct dbins_, attr_old)},
  { NULL, N_("attr_new"),     0,  72,   16, offsetof(struct dbins_, attr_new)},

  { NULL, NULL,      0,  0, 0, 0 }
};

#define SH_SLOT_HOST    70
#define SH_SLOT_GROUP    7
#define START_SEC_LONGS 51
#define END_SEC_LONGS   68

#if defined(HAVE_INT_32)
typedef unsigned int uint32;
#elif defined(HAVE_LONG_32)
typedef unsigned long uint32;
#elif defined(HAVE_SHORT_32)
typedef unsigned short uint32;
#else
#error No 32 byte type found !
#endif

typedef unsigned char uint8;

typedef struct
{
        uint32 h[4];
        uint32 data[16];
        uint8  offset;
        uint32  nblocks;
        int  count;
} md5Param;



typedef unsigned char        sh_byte;


extern int md5Reset(register md5Param* p);
extern int md5Update(md5Param* p, const sh_byte* data, int size);
extern int md5Digest(md5Param* p, uint32* data);

static char db_name[64]     = ""; 
static char db_table[64]    = ""; 
static char db_host[64]     = ""; 
static char db_user[64]     = ""; 
static char db_password[64] = "";

static int  sh_persistent_dbconn = S_TRUE;

int sh_database_use_persistent (char * str)
{
  return sh_util_flagval (str, &sh_persistent_dbconn);
}

static int insert_value (char * ptr, char * str)
{
  if (!ptr || !str)
    return -1;
  if (strlen(str) > 63)
    return -1;
  (void) sl_strlcpy(ptr, str, 64);
  return 0;
}

static void init_db_entry (dbins * ptr)
{
  memset (ptr, (int) '\0', sizeof(dbins));
  ptr->next = NULL;
  return;
}
  

int sh_database_set_database (char * str)
{
  return insert_value (db_name, str);
}
int sh_database_set_table (char * str)
{
  return insert_value (db_table, str);
}
int sh_database_set_host (char * str)
{
  return insert_value (db_host, str);
}
int sh_database_set_user (char * str)
{
  return insert_value (db_user, str);
}
int sh_database_set_password (char * str)
{
  return insert_value (db_password, str);
}

/******************************************************************
 *
 *  Oracle and unixODBC stuff, only Oracle tested untested
 *
 *  Based on the code in the snort output plugin (spo_database.c).
 *  Copyright/license statement in spo_database.c:
 *
 * Portions Copyright (C) 2000,2001,2002 Carnegie Mellon University
 * Copyright (C) 2001 Jed Pickel <jed@pickel.net>
 * Portions Copyright (C) 2001 Andrew R. Baker <andrewb@farm9.com>
 *
 * 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.
 *
 ******************************************************************/
#ifdef WITH_ODBC

#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>

static    SQLHENV     u_handle;
static    SQLHDBC     u_connection;
static    SQLHSTMT    u_statement;
static    SQLINTEGER  u_col;
static    SQLINTEGER  u_rows;

void sh_database_reset()
{
  return;
}

static
int sh_database_query (char  * query, /*@out@*/ long * id)
{
  static int fatal_error = 0;
  int result = 0;
  char         row_query[128];
  long result_call;

  SL_ENTER(_("sh_database_query"));

  *id = 0;

  if (fatal_error == 1)
    {
      SL_RETURN((-1), _("sh_database_query"));
    }

  /* Connect
   */
  if (db_name[0]     == '\0')
    sl_strlcpy(db_name,  _("samhain"),   64);

  if (db_user[0]     == '\0')
    sl_strlcpy(db_user,  _("samhain"),   64);

  result_call = SQLAllocEnv(&u_handle);
  if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO))
    {
      sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call, 
                  MSG_E_SUBGEN,
                  _("Error in SQLAllocEnv when connecting to ODBC data source"), 
                  _("sh_database_query"));
      fatal_error = 1;
      SL_RETURN((-1), _("sh_database_query"));
    }
  result_call = SQLAllocConnect(u_handle, &u_connection);
  if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO))
    {
      sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call,
                  MSG_E_SUBGEN,
                  _("Error in SQLAllocEnv when connecting to ODBC data source"), 
                  _("sh_database_query"));
      fatal_error = 1;
      SL_RETURN((-1), _("sh_database_query"));
    }
  result_call = SQLConnect(u_connection, db_name, SQL_NTS, 
                     db_user, SQL_NTS, db_password, SQL_NTS);
  if ((result_call != SQL_SUCCESS) && (result_call != SQL_SUCCESS_WITH_INFO))
    {
      sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, result_call, 
                  MSG_E_SUBGEN,
                  _("Error in SQLAllocEnv when connecting to ODBC data source"), 
                  _("sh_database_query"));
      fatal_error = 1;
      SL_RETURN((-1), _("sh_database_query"));
    }

  /* Insert
   */
  result_call = SQLAllocStmt(u_connection, &u_statement);
  if ((result_call == SQL_SUCCESS) || (result_call == SQL_SUCCESS_WITH_INFO))
    {
      result_call = SQLPrepare(u_statement, query, SQL_NTS);
      if ((result_call == SQL_SUCCESS) || 
        (result_call == SQL_SUCCESS_WITH_INFO))
      {
        result_call = SQLExecute(u_statement);
        if((result_call == SQL_SUCCESS) || 
           (result_call == SQL_SUCCESS_WITH_INFO))
          {
            result = 1;
          }
      }
    }

  if (result == 0)
    {
      sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("Error inserting into ODBC data source"), 
                  _("sh_database_query"));
      goto odbc_disconnect;
    }

  /* Select
   */
  result = 0;

  sl_strlcpy (row_query, _("SELECT MAX(log_index) FROM "), 128);
  sl_strlcat (row_query, db_table, 128);

  result_call = SQLAllocStmt(u_connection, &u_statement);
  if ((result_call == SQL_SUCCESS) ||
      (result_call == SQL_SUCCESS_WITH_INFO))
    {
      result_call = SQLPrepare(u_statement, row_query, SQL_NTS);
      if ((result_call == SQL_SUCCESS) ||
        (result_call == SQL_SUCCESS_WITH_INFO))
      {
        result_call = SQLExecute(u_statement);
        if ((result_call == SQL_SUCCESS) ||
            (result_call == SQL_SUCCESS_WITH_INFO))
          {
            result_call = SQLRowCount(u_statement, &u_rows);
            if ((result_call == SQL_SUCCESS) ||
              (result_call == SQL_SUCCESS_WITH_INFO))
            {
              if((u_rows) && (u_rows == 1))
                {
                  result_call = SQLFetch(u_statement);
                  if ((result_call == SQL_SUCCESS) ||
                    (result_call == SQL_SUCCESS_WITH_INFO))
                  {
                    result_call = SQLGetData(u_statement, 1, 
                                       SQL_INTEGER, &u_col,
                                       sizeof(u_col), NULL);
                    if ((result_call == SQL_SUCCESS) ||
                        (result_call == SQL_SUCCESS_WITH_INFO))
                      {
                        *id = (long int) u_col;
                        result = 1;
                      }
                  }
                }
            }
          }
      }
    }

  if (result == 0)
    {
      sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("Error selecting MAX(log_index) from ODBC data source"), 
                  _("sh_database_query"));
    }

 odbc_disconnect:
  SQLFreeHandle(SQL_HANDLE_STMT, u_statement);
  SQLDisconnect(u_connection); 
  SQLFreeHandle(SQL_HANDLE_DBC, u_connection);
  SQLFreeHandle(SQL_HANDLE_ENV, u_handle);

  SL_RETURN(((result == 0) ? -1 : 0), _("sh_database_query"));
  
}

/* #ifdef WITH_ODBC */
#endif

#ifdef WITH_ORACLE

#include <oci.h>

static    OCIDefine * o_define;
static    OCIEnv    * o_environment;
static    OCISvcCtx * o_servicecontext;
static    OCIError  * o_error;
static    OCIStmt   * o_statement;
static    text        o_errormsg[512];
static    sb4         o_errorcode;

static  int  connected = 0;

void sh_database_reset()
{
  if (connected == 1) 
    {
      OCILogoff(o_servicecontext, o_error);
      OCIHandleFree((dvoid *) o_statement,      OCI_HTYPE_STMT);
      OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX);
      OCIHandleFree((dvoid *) o_error,          OCI_HTYPE_ERROR);
    }
  connected = 0;
  return;
}

static char * sh_stripnl (char * str)
{
  size_t len = sl_strlen(str);
  if (len > 0)
    {
      if (str[len-1] == '\n')
      str[len-1] == '\0';
    }
  return str;
}

static
int sh_database_query (char  * query, /*@out@*/ long * id)
{
  static  int  bad_init  = 0;
  int          result    = 0;
  char         row_query[128];

  SL_ENTER(_("sh_database_query"));

  *id = 0;

  if (bad_init == 1) {
    SL_RETURN(-1, _("sh_database_query"));
  }
  else if (connected == 1) {
    goto oracle_connected;
  }

  /* 
   * Connect
   */
#define PRINT_ORACLE_ERR(func_name) \
     do { \
         OCIErrorGet(o_error, 1, NULL, &o_errorcode, \
                     o_errormsg, sizeof(o_errormsg), \
                     OCI_HTYPE_ERROR); \
         sh_stripnl (o_errormsg); \
         sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, \
                 o_errormsg, _("sh_database_query")); \
         sl_snprintf(row_query, 127, \
                 _("%s: Connection to database '%s' failed"), \
                     func_name, db_name); \
         sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, \
                 row_query, _("sh_database_query")); \
         bad_init = 1; \
         SL_RETURN(-1, _("sh_database_query")); \
     } while (1 == 0)


  if (!getenv("ORACLE_HOME")) 
    {
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("ORACLE_HOME environment variable not set"), 
                  _("sh_database_query"));
    }
  if (db_name[0]     == '\0')
    {
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("database name not set, using default 'samhain'"), 
                  _("sh_database_query"));
      sl_strlcpy(db_name,  _("samhain"),   64);
    }
  if (db_user[0]     == '\0')
    {
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("database user not set, using default 'samhain'"), 
                  _("sh_database_query"));
      sl_strlcpy(db_user,  _("samhain"),   64);
    }
  if (db_password[0] == '\0')
    {
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("database password not set, cannot proceed"), 
                  _("sh_database_query"));
      bad_init = 1;
      SL_RETURN(-1, _("sh_database_query"));
    }


#ifdef DB_DEBUG
  sl_snprintf(row_query, 127, 
            _("Conncting to oracle database '%s'"), 
            db_name); 
  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
              row_query, 
              _("sh_database_query"));
#endif

  /* a) Oracle says use OCIEnvCreate instead of OCIInitialize/OCIEnvcreate
   * b) why two times OCIEnvInit() ???
   */
  if (OCIInitialize(OCI_DEFAULT, NULL, NULL, NULL, NULL)) 
    PRINT_ORACLE_ERR("OCIInitialize");
  
  if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL)) 
    PRINT_ORACLE_ERR("OCIEnvInit");
  
  if (OCIEnvInit(&o_environment, OCI_DEFAULT, 0, NULL)) 
    PRINT_ORACLE_ERR("OCIEnvInit (2)");

  /* allocate and initialize the error handle 
   */
  if (OCIHandleAlloc(o_environment, (dvoid **)&o_error, 
                 OCI_HTYPE_ERROR, (size_t) 0, NULL))
    PRINT_ORACLE_ERR("OCIHandleAlloc");

  /* logon and allocate the service context handle 
   */
  if (OCILogon(o_environment, o_error, &o_servicecontext,
             (OraText*) db_user,     sl_strlen(db_user), 
             (OraText*) db_password, sl_strlen(db_password), 
             (OraText*) db_name,     sl_strlen(db_name))) 
      {   
      OCIErrorGet(o_error, 1, NULL, &o_errorcode, 
                o_errormsg, sizeof(o_errormsg), OCI_HTYPE_ERROR);
      sh_stripnl (o_errormsg);
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  o_errormsg, 
                  _("sh_database_query"));
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("check database is listed in tnsnames.ora"), 
                  _("sh_database_query"));
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("check tnsnames.ora readable"), 
                  _("sh_database_query"));
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("check database accessible with sqlplus"), 
                  _("sh_database_query"));
      sl_snprintf(row_query, 127, 
                _("OCILogon: Connection to database '%s' failed"), 
                db_name); 
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
                  row_query, _("sh_database_query")); 
      bad_init = 1;
      SL_RETURN(-1, _("sh_database_query")); 
      }
 
  if (OCIHandleAlloc(o_environment, (dvoid **)&o_statement, 
                 OCI_HTYPE_STMT, 0, NULL))
    PRINT_ORACLE_ERR("OCIHandleAlloc (2)");

  /* Flag connection status
   */
  connected = 1;

 oracle_connected:

  /* 
   * Insert
   */
#ifdef DB_DEBUG
  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
              query, 
              _("sh_database_query"));
#endif

  if (OCIStmtPrepare(o_statement, o_error, 
                 (OraText*) query, sl_strlen(query), 
                 OCI_NTV_SYNTAX, OCI_DEFAULT))
    {
      OCIErrorGet(o_error, 1, NULL, 
              &o_errorcode, o_errormsg, sizeof(o_errormsg), 
              OCI_HTYPE_ERROR);
      sh_stripnl (o_errormsg);
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  o_errormsg, 
                  _("sh_database_query"));
      goto err_out;
    }
 
   if (OCIStmtExecute(o_servicecontext, 
                  o_statement, o_error, 1,  0, 
                  NULL, NULL, OCI_COMMIT_ON_SUCCESS))
    {
      OCIErrorGet(o_error, 1, NULL, 
              &o_errorcode, o_errormsg, sizeof(o_errormsg), 
              OCI_HTYPE_ERROR);
      sh_stripnl (o_errormsg);
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  o_errormsg, 
                  _("sh_database_query"));
      goto err_out;
    }

#ifdef DB_DEBUG
  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
              _("No error on insert"), 
              _("sh_database_query"));
#endif

  /* Get row index
   */
  sl_strlcpy (row_query, _("SELECT MAX(log_index) FROM "), 128);
  sl_strlcat (row_query, db_table, 128);

#ifdef DB_DEBUG
  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
              row_query, 
              _("sh_database_query"));
#endif

  if (OCIStmtPrepare(o_statement, o_error, 
                 (OraText*) row_query, sl_strlen(row_query), 
                 OCI_NTV_SYNTAX, OCI_DEFAULT))
    {
      OCIErrorGet(o_error, 1, NULL, 
              &o_errorcode, o_errormsg, sizeof(o_errormsg), 
              OCI_HTYPE_ERROR);
      sh_stripnl (o_errormsg);
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  o_errormsg, 
                  _("sh_database_query"));
      goto err_out;
    }

  if (OCIStmtExecute(o_servicecontext, o_statement, o_error, 
                 0, 0, NULL, NULL, OCI_DEFAULT))
    {
      OCIErrorGet(o_error, 1, NULL, 
              &o_errorcode, o_errormsg, sizeof(o_errormsg), 
              OCI_HTYPE_ERROR);
      sh_stripnl (o_errormsg);
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  o_errormsg, 
                  _("sh_database_query"));
      goto err_out;
    }

  if (OCIDefineByPos (o_statement, &o_define, o_error, 1, 
                  &result, sizeof(result), 
                  SQLT_INT, 0, 0, 0, OCI_DEFAULT))
    {
      OCIErrorGet(o_error, 1, NULL, 
              &o_errorcode, o_errormsg, sizeof(o_errormsg), 
              OCI_HTYPE_ERROR);
      sh_stripnl (o_errormsg);
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  o_errormsg, 
                  _("sh_database_query"));
      goto err_out;
    }
  if (OCIStmtFetch (o_statement, o_error, 1, OCI_FETCH_NEXT, OCI_DEFAULT))
    {
      OCIErrorGet(o_error, 1, NULL, 
              &o_errorcode, o_errormsg, sizeof(o_errormsg), 
              OCI_HTYPE_ERROR);
      sh_stripnl (o_errormsg);
      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  o_errormsg, 
                  _("sh_database_query"));
      goto err_out;
    }
  
#ifdef DB_DEBUG
  sl_snprintf(row_query, 127, _("Returned value: %d"), result); 
  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
              row_query, 
              _("sh_database_query"));
#endif

  *id = result;

  if (sh_persistent_dbconn == S_FALSE)
    {
      OCILogoff(o_servicecontext, o_error);
      OCIHandleFree((dvoid *) o_statement,      OCI_HTYPE_STMT);
      OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX);
      OCIHandleFree((dvoid *) o_error,          OCI_HTYPE_ERROR);
      connected = 0;
    }
  SL_RETURN(0, _("sh_database_query"));

 err_out:
  /* 
   * Error
   */
  if (sh_persistent_dbconn == S_FALSE)
    {
      OCILogoff(o_servicecontext, o_error);
      OCIHandleFree((dvoid *) o_statement,      OCI_HTYPE_STMT);
      OCIHandleFree((dvoid *) o_servicecontext, OCI_HTYPE_SVCCTX);
      OCIHandleFree((dvoid *) o_error,          OCI_HTYPE_ERROR);
      connected = 0;
    }
  SL_RETURN(-1, _("sh_database_query"));
}

/* #ifdef WITH_ORACLE */
#endif

#ifdef WITH_POSTGRES
/******************************************************************
 *
 *  Postgresql stuff, tested
 *
 ******************************************************************/

#ifdef HAVE_PGSQL_LIBPQ_FE_H
#include <pgsql/libpq-fe.h>
#else
#include <libpq-fe.h>
#endif

static int        connection_status = S_FALSE;

void sh_database_reset()
{
  connection_status = S_FALSE;
  return;
}

static
int sh_database_query (char  * query, /*@out@*/ long * id)
{
  char              conninfo[256];
  char            * p;
  static PGconn   * conn = NULL;
  PGresult        * res;
  unsigned int      i;
  static SH_TIMEOUT sh_timer = { 0, 3600, S_TRUE };

  SL_ENTER(_("sh_database_query"));

  *id       = 0; 

  p = &conninfo[0]; 

  if (db_host[0]     == '\0')
    sl_strlcpy(db_host,  _("localhost"), 64);
  if (db_name[0]     == '\0')
    sl_strlcpy(db_name,  _("samhain"),   64);
  if (db_user[0]     == '\0')
    sl_strlcpy(db_user,  _("samhain"),   64);

  if (db_host[0]     != '\0' && NULL != strchr(db_host, '.')) 
    {
      sl_snprintf(p, 255, "hostaddr=%s ", db_host);
      p = &conninfo[strlen(conninfo)];
    }
  if (db_name[0]     != '\0') 
    {
      sl_snprintf(p, 255 - strlen(conninfo), "dbname=%s ", db_name);
      p = &conninfo[strlen(conninfo)];
    }

  if (db_user[0]     != '\0') 
    {
      sl_snprintf(p, 255 - strlen(conninfo), "user=%s ", db_user);
      p = &conninfo[strlen(conninfo)];
    }

  if (db_password[0] != '\0') 
    {
      sl_snprintf(p, 255 - strlen(conninfo), "password=%s ", db_password);
    }

  if (connection_status == S_FALSE)
    {
      if (conn)
      PQfinish(conn);
      conn = NULL;
      conn = PQconnectdb(conninfo);
    }
  else
    {
      if (PQstatus(conn) == CONNECTION_BAD) 
      PQreset(conn);
    }

  if ((conn == NULL) || (PQstatus(conn) == CONNECTION_BAD))
    {
      connection_status = S_FALSE;

      sh_timer.flag_ok = S_FALSE;
      if (S_TRUE == sh_util_timeout_check(&sh_timer))
      {
        goto err_out;
      }
      else
      {
        if (conn)
          PQfinish(conn);
        conn = NULL;
        SL_RETURN(0, _("sh_database_query"));
      }
    }
  connection_status = S_TRUE;


  /* do the insert
   */
  res = PQexec(conn, query);
  if (PQresultStatus(res) != PGRES_COMMAND_OK) 
    {
      PQclear(res);
      goto err_out;
    }
  PQclear(res);

  /* get the unique row index
   */
  res = PQexec(conn, _("SELECT last_value FROM log_log_index_seq"));
  if (PQresultStatus(res) != PGRES_TUPLES_OK) 
    {
      PQclear(res);
      goto err_out;
    }

  *id = atoi (PQgetvalue(res, 0, 0)); 

  PQclear(res);
  if (S_FALSE == sh_persistent_dbconn)
    {
      if (conn)
      PQfinish(conn);
      conn = NULL;
      connection_status = S_FALSE;
    }
  SL_RETURN(0, _("sh_database_query"));


 err_out:
  if (conn)
    {
      p = PQerrorMessage(conn);
      for (i = 0; i < sl_strlen(p); ++i)
      if (p[i] == '\n') p[i] = ' ';
    }
  else
    {
      p = NULL;
    }
  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
              (p == NULL ? _("(null)") : p), 
              _("sh_database_query"));
  if (conn)
    PQfinish(conn);
  conn = NULL;
  connection_status = S_FALSE;
  SL_RETURN(-1, _("sh_database_query"));
}
#endif 


#ifdef WITH_MYSQL 

#ifdef HAVE_MYSQL_MYSQL_H
#include <mysql/mysql.h>
#else
#include <mysql.h>
#endif 

extern int flag_err_debug;

static int        connection_status = S_FALSE;

void sh_database_reset()
{
  connection_status = S_FALSE;
  return;
}

static
int sh_database_query (char  * query, /*@out@*/ long * id)
{
  int               status = 0;
  char            * p;
  static MYSQL    * db_conn = NULL;
  static SH_TIMEOUT sh_timer = { 0, 3600, S_TRUE };

  SL_ENTER(_("sh_database_query"));

  *id = 0;

  if (query == NULL)
    {
      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
                  _("NULL query"), 
                  _("sh_database_query"));
      SL_RETURN(0, _("sh_database_query"));
    }

  if (db_host[0]     == '\0')
    (void) sl_strlcpy(db_host,  _("localhost"), 64);
  if (db_name[0]     == '\0')
    (void) sl_strlcpy(db_name,  _("samhain"),   64);
  if (db_user[0]     == '\0')
    (void) sl_strlcpy(db_user,  _("samhain"),   64);

  if ((db_conn == NULL) || (connection_status == S_FALSE))
    {
      if (db_conn)
      {
        mysql_close(db_conn);
        db_conn = NULL;
      }
      connection_status = S_FALSE;

      db_conn = mysql_init(NULL);
      if (NULL == db_conn)
      {
        p = NULL; status = 0;
        sh_timer.flag_ok = S_FALSE;
        if (S_TRUE == sh_util_timeout_check(&sh_timer))
          {
            goto alt_out;
          }
        else
          {
            SL_RETURN(0, _("sh_database_query"));
          }
      }

      status = 0;
  
      if (NULL == mysql_real_connect(db_conn, 
                             db_host[0] == '\0'     ? NULL : db_host, 
                             db_user[0] == '\0'     ? NULL : db_user, 
                             db_password[0] == '\0' ? NULL : db_password,
                             db_name[0] == '\0'     ? NULL : db_name, 
                             0, NULL, 0))
      {
        sh_timer.flag_ok = S_FALSE;
        if (S_TRUE == sh_util_timeout_check(&sh_timer))
          {
            goto err_out;
          }
        else
          {
            SL_RETURN(0, _("sh_database_query"));
          }
      }
      connection_status = S_TRUE;
    }
  else
    {
      if (0 != mysql_ping(db_conn))
      {
        connection_status = S_FALSE;
        sh_timer.flag_ok = S_FALSE;
        if (S_TRUE == sh_util_timeout_check(&sh_timer))
          {
            goto err_out;
          }
        else
          {
            SL_RETURN(0, _("sh_database_query"));
          }
      }
    }
  
  if (0 != mysql_query(db_conn, query))
    {
      goto err_out;
    }

  if (flag_err_debug == SL_TRUE)
    {
      p = mysql_info (db_conn);
      if (p != NULL)
      {
        sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
                    p, 
                    _("sh_database_query"));
      }
    }

  *id = (long) mysql_insert_id(db_conn);
  if (S_FALSE == sh_persistent_dbconn)
    {
      if (db_conn)
      mysql_close(db_conn);
      db_conn = NULL;
      connection_status = S_FALSE;
    }
  SL_RETURN(0, _("sh_database_query"));

 err_out:

  if (db_conn)
    {
      p      = mysql_error (db_conn);
      status = (int) mysql_errno (db_conn);
    }
  else
    {
      p = NULL; p = 0;
    }

 alt_out:

  *id = 0;
  sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
              (p == NULL ? _("(null)") : p), 
              _("sh_database_query"));
  if (db_conn)
    mysql_close(db_conn);
  db_conn = NULL;
  connection_status = S_FALSE;
  SL_RETURN(status, _("sh_database_query"));
}
#endif

static
char * null_or_val (char * end,   char * val,   int * size, int flag)
{
  long len;

  if (!end    || !val   || !size)
    return end;

  if (val[0] == '\0')
    {
      return end;
    }
  else
    {
      if (*size > 1)
      {
        *end = ','; ++end; (*size) -= 1;
        if (flag == 1) { *end = '\''; ++end; (*size) -= 1; }
        *end = '\0';
      }
      len = (long) strlen(val);
      if ((long) *size > (len+1))
      {
        (void) sl_strlcat(end, val, (size_t) *size);
        end   += len; (*size) -= len;
        if (flag == 1) { *end = '\''; ++end;  (*size) -= 1; }
        *end = '\0'; 
      }
    }
  return end;
}

#define SH_QUERY_MAX 16383

static
long sh_database_entry (dbins * db_entry, long id)
{
  /* This does not need to be re-entrant
   */
  char * query;
  static char   columns[1024];
  char * values;

  int    status;
  long   the_id;
  int    size;
  char * end;
  int    c_size;
  char * c_end;
  char * p;
  int    i;
  char   num[64];

  md5Param crc;
  unsigned char md5buffer[16];
  char md5out[33];
  int  cnt;

  SL_ENTER(_("sh_database_entry"));

  query  = SH_ALLOC(SH_QUERY_MAX+1);
  values = SH_ALLOC(SH_QUERY_MAX+1);

  (void) md5Reset(&crc);

  if (db_entry->host[0] == '\0')
    {
      if (sh.host.name[0] == '\0')
      (void) strcpy (db_entry->host, _("localhost"));  /* known to fit  */
      else
      (void) sl_strlcpy (db_entry->host, sh.host.name, 64); 
    }

  /*@-bufferoverflowhigh@*/
  if (id >= 0)
    sprintf(num, "%ld", id);                       /* known to fit  */
  /*@+bufferoverflowhigh@*/

#ifdef WITH_ORACLE
  /* Oracle needs some help for the time format (fix by Michael Somers)
   */
  (void)
  sl_snprintf (values, SH_QUERY_MAX,  
             _("(%s,%c%s%c,to_date(%c%s%c,'YYYY-MM-DD HH24:MI:SS'),%c%s%c,%c%s%c"),
               id >= 0 ? num : _("NULL"),
               '\'', db_entry->host,'\'', 
               '\'', db_entry->time,'\'', 
               '\'', db_entry->sev, '\'',
               '\'', 
               (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg),
               '\'');
#else
  (void)
  sl_snprintf (values, SH_QUERY_MAX, _("(%s,%c%s%c,%c%s%c,%c%s%c,%c%s%c"),
             id >= 0 ? num : _("NULL"),
             '\'', db_entry->host,'\'', 
             '\'', db_entry->time,'\'', 
             '\'', db_entry->sev, '\'',
             '\'', 
             (db_entry->msg[0] == '\0' ? _("NULL") : db_entry->msg), 
             '\'');
#endif

  (void) sl_snprintf (columns, 1023, 
                  _("(log_ref,log_host,log_time,log_sev,log_msg"));

  /*@-type@*//* byte* versus char[..] */
  if (attr_tab[0].inHash == 1) 
    (void) md5Update(&crc, (sh_byte*) db_entry->sev,  
                 (int) strlen(db_entry->sev));
  if (attr_tab[1].inHash == 1) 
    (void) md5Update(&crc, (sh_byte*) db_entry->time, 
                 (int) strlen(db_entry->time));
  if (attr_tab[2].inHash == 1) 
    (void) md5Update(&crc, (sh_byte*) db_entry->host, 
                 (int) strlen(db_entry->host));
  if (attr_tab[3].inHash == 1 && db_entry->msg[0] != '\0') 
    (void) md5Update(&crc, (sh_byte*) db_entry->msg,  
                 (int) strlen(db_entry->sev));
  /*@+type@*/

  size   =  (int) (SH_QUERY_MAX - strlen(values));
  end    =  values + strlen(values);
  c_size =  1023   - (int) strlen(columns); /* sizeof(colums) == 1024 */
  c_end  =  columns + strlen(columns);

  i = 4;

  while (attr_tab[i].attr != NULL)
    {
      if (attr_tab[i].size != 0)
      {
        if (attr_tab[i].val > 40 && attr_tab[i].val < 47)
          {
            /* remove the 'T' between date and time 
             */
            p = (char *)(db_entry)+attr_tab[i].off;
            p = strchr(p, 'T');
            if (p) *p = ' ';
          }
        p = end;
        end = null_or_val(end,((char *)(db_entry)+attr_tab[i].off),&size,1);
        if (p != end)
          {
            /* 
             * 'host' is a reserved word in SQL
             */
            if (attr_tab[i].val == SH_SLOT_HOST)
            c_end = null_or_val (c_end, _("fromhost"), &c_size,0);
            /* 
             * 'group' is a reserved word in SQL
             */
            else if (attr_tab[i].val == SH_SLOT_GROUP)
            c_end = null_or_val (c_end, _("grp"), &c_size,0);
            else
            c_end = null_or_val (c_end, attr_tab[i].attr, &c_size,0);
          }
        /*@-type@*//* byte* versus char[..] */
        if (attr_tab[i].inHash == 1 && 
            ((char *)(db_entry)+attr_tab[i].off) != '\0')
          {
            (void)md5Update(&crc, 
                        (sh_byte*) ((char *)(db_entry)+attr_tab[i].off), 
                        (int)strlen((char *)(db_entry)+attr_tab[i].off));
          }
        /*@+type@*/
      }
      else if (attr_tab[i].val >= START_SEC_LONGS &&
             attr_tab[i].val <= END_SEC_LONGS)
      {
        (void)
        sl_snprintf(end, (size_t)(size-1), _(",\'%ld\'"), 
                  db_entry->long_data[attr_tab[i].val-START_SEC_LONGS]);
        while (*end != '\0') { ++end; --size; }
        (void) sl_snprintf(c_end, (size_t)(c_size-1), 
                       _(",%s"), attr_tab[i].attr);
        while (*c_end != '\0') { ++c_end; --c_size; }
        if (attr_tab[i].inHash == 1) 
          {
            /*@-type@*//* byte* versus char[..] */
            (void)
            md5Update(&crc,
                  (sh_byte *) db_entry->long_data[attr_tab[i].val-START_SEC_LONGS], 
                  sizeof(long));
            /*@+type@*/
          }
      }

      ++i;
    }

  (void) md5Digest(&crc, (uint32 *) md5buffer);
  /*@-bufferoverflowhigh -usedef@*/
  for (cnt = 0; cnt < 16; ++cnt)
    sprintf (&md5out[cnt*2], _("%02X"),            /* known to fit  */
           (unsigned int) md5buffer[cnt]); 
  /*@+bufferoverflowhigh +usedef@*/
  md5out[32] = '\0';

  (void) sl_snprintf(end, (size_t) (size-1), _(",%c%s%c"), '\'', md5out, '\'');
  while (*end != '\0') { ++end; --size; }
  (void) sl_snprintf(c_end, (size_t) (c_size-1),_(",log_hash"));
  while (*c_end != '\0') { ++c_end; --c_size; }


  if (size > 1)   { *end   = ')'; ++end;   *end   = '\0'; }
  if (c_size > 1) { *c_end = ')'; ++c_end; *c_end = '\0'; }

  if (db_table[0]    == '\0')
    (void) sl_strlcpy(db_table, _("log"),       64);

  (void) sl_snprintf (query, SH_QUERY_MAX,
                  _("INSERT INTO %s %s VALUES %s"),
                  db_table, columns, values);

  status = sh_database_query (query, &the_id);

  /*@-usedef@*//* no, 'values' is allocated here */
  SH_FREE(values);
  /*@+usedef@*/
  SH_FREE(query);
  
  SL_RETURN(the_id, _("sh_database_entry"));
}
 

static void init_attr_table()
{
  static  int first = S_TRUE;
  int         i;

#ifdef SH_STEALTH
  int     j, k;

  if (first == S_TRUE)
    {
      i = 0;
      while (attr_tab[i].attr_o != NULL)
      {
        j = strlen(attr_tab[i].attr_o);
        attr_tab[i].attr = malloc (j+1); /* only once */
        if (NULL == attr_tab[i].attr)
          SL_RETURN (NULL, _("sh_database_parse"));
        for (k = 0; k < j; ++k)
          attr_tab[i].attr[k] = attr_tab[i].attr_o[k] ^ XOR_CODE;
        attr_tab[i].attr[j] = '\0';
        ++i;
      }
      first = S_FALSE;
    }
#else
  if (first == S_TRUE)
    {
      i = 0;
      while (attr_tab[i].attr_o != NULL)
      {
        attr_tab[i].attr = attr_tab[i].attr_o;
        ++i;
      }
      first = S_FALSE;
    }
#endif
  return;
}

int sh_database_add_to_hash  (char * str)
{
  int i;

  if (!str)
    return -1;
  init_attr_table();
  if (0 == strcmp(str, _("log_msg")))  { attr_tab[3].inHash = 1; return 0;}
  if (0 == strcmp(str, _("log_sev")))  { attr_tab[0].inHash = 1; return 0;}
  if (0 == strcmp(str, _("log_time"))) { attr_tab[1].inHash = 1; return 0;}
  if (0 == strcmp(str, _("log_host"))) { attr_tab[2].inHash = 1; return 0;}
  i = 4;
  while (attr_tab[i].attr != NULL)
    {
      if (0 == strcmp(str, attr_tab[i].attr))  
      { attr_tab[i].inHash = 1; return 0; }
      ++i;
    }
  return -1;
}


/* this is not a real XML parser, but it copes with the XML format of
 * the log messages provided by sh_error_handle()
 */
static
char *  sh_database_parse (char * message, dbins * db_entry)
{
  static  int first = S_TRUE;
  char  * p;
  char  * q;
  char  * z;
  dbins * new;
  int     i;
  size_t  j;

  SL_ENTER(_("sh_database_parse"));

  if (!message || *message == '\0')
    SL_RETURN (NULL, _("sh_database_parse"));

  if (first == S_TRUE)
    {
      init_attr_table();
      first = S_FALSE;
    }

  p = strchr (message, '<');
  if (!p)
    SL_RETURN (NULL, _("sh_database_parse"));

  while ((p != NULL) && (*p != '\0') && (*p != '>'))
    {
      if (p[0] == '/' && p[1] == '>')
      SL_RETURN (&p[2], _("sh_database_parse"));
      if (p[0] == '/' && p[1] == 'l' && p[2] == 'o' && 
        p[3] == 'g' && p[4] == '>')
      SL_RETURN (&p[5], _("sh_database_parse"));
      if (p[0] == 'l' && p[1] == 'o' && p[2] == 'g' &&
        (p[3] == ' ' || p[3] == '>'))
      {
        p = &p[4];
        goto parse;
      }
      ++p;
    }
  SL_RETURN(NULL, _("sh_database_parse")); 

 parse:

  while ((p != NULL) && (*p == ' ' || *p == '>'))
    ++p;

  if (!p || *p == '\0')
    SL_RETURN(NULL, _("sh_database_parse"));

  if (p[0] == '<' && p[1] == 'l' &&
      p[2] == 'o' && p[3] == 'g')
    {
      new       = SH_ALLOC(sizeof(dbins));
      init_db_entry(new);
      db_entry->next = new;
      p = sh_database_parse (p, new);
    }

  if (p[0] == '/' && p[1] == '>')
    SL_RETURN (&p[1], _("sh_database_parse"));
  
  if (p[0] == '<' && p[1] == '/' && p[2] == 'l' &&
      p[3] == 'o' && p[4] == 'g' && p[5] == '>')
    SL_RETURN (&p[5], _("sh_database_parse"));


  /* non-whitespace 
   */
  i = 0;
  while (attr_tab[i].attr != NULL)
    {
      j = strlen(attr_tab[i].attr);
      if (0 == strncmp(p, attr_tab[i].attr, j) && 
        p[j] == '=' && p[j+1] == '"')
      {
        q = strchr(&p[j+2], '"');
        if (!q)
          {
            SL_RETURN(NULL, _("sh_database_parse"));
          }
        else
          {
            *q = '\0';

            if      (attr_tab[i].val == 1)
            (void) sl_strlcpy(db_entry->sev, &p[j+2], 
                          (size_t)attr_tab[i].size);
            else if (attr_tab[i].val == 2)
            {
              z = strchr(&p[j+2], 'T');
              if (z) *z = ' ';
              (void) sl_strlcpy(db_entry->time, &p[j+2],  20);
            }
            else if (attr_tab[i].val == 3)
            (void) sl_strlcpy(db_entry->host, &p[j+2], 
                          (size_t) attr_tab[i].size);
            else if (attr_tab[i].val == 4)
            (void) sl_strlcpy(db_entry->msg,  &p[j+2], 
                          (size_t) attr_tab[i].size);
            else if (attr_tab[i].size != 0)
            {
              (void) sl_strlcpy( (((char *)(db_entry))+ attr_tab[i].off),
                             &p[j+2], 
                             (size_t) attr_tab[i].size);
            }
            else if (attr_tab[i].val >= START_SEC_LONGS)
            {
              db_entry->long_data[attr_tab[i].val-START_SEC_LONGS]
                = atol(&p[j+2]);
            }

            *q = '"';
            p  = q; 
            ++p;

            goto parse;
          }
      }
      ++i;
    }

  /* unknown attribute, skip
   */
  while ((p != NULL) && (*p != '\0') && (*p != ' '))
    ++p;

  goto parse;
}

static int enter_wrapper = 1;

int set_enter_wrapper (char * str)
{
  return sh_util_flagval(str, &enter_wrapper);
}

int sh_database_insert (char * message)
{
  dbins * db_entry;
  dbins * prev;
  dbins * curr;
  long    id = 0;
#ifdef HOST_SWITCH
  char  * temp[64];
#endif

  SL_ENTER(_("sh_database_insert"));

  db_entry        = SH_ALLOC(sizeof(dbins));
  init_db_entry(db_entry);

  /* recursively parse the message into a linked list
   */
  (void) sh_database_parse (message, db_entry);

  /* Enter the list into the database. Actually, the list can only have
   * two entries at most.
   */
  curr = db_entry;
  if (curr->next)
    {
      prev = curr->next;
#ifdef HOST_SWITCH
      strncpy(temp, prev->host,       64);
#endif
      strncpy(prev->host, curr->host, 64);
#ifdef HOST_SWITCH
      strncpy(curr->host, temp,       64);
#endif
      id = sh_database_entry (prev, -1);
      SH_FREE(prev);
    }

  if (id != 0)                       /* this is a server wrapper          */
    {
      if (enter_wrapper != 0)
      (void) sh_database_entry (curr, id);
    }
  else                                /* this is a generic server message */
    {
      (void) sh_database_entry (curr, 0);
    }
  SH_FREE(curr);

  SL_RETURN(0, _("sh_database_insert"));
}

#endif

Generated by  Doxygen 1.6.0   Back to index