/*
 *  relaytest.c -- module for ZMailer's smtpserver
 *  By Matti Aarnio <mea@nic.funet.fi>
 *
 */

#include "hostenv.h"

#ifdef	HAVE_SYS_SOCKET_H
# include <sys/socket.h>

# include <netinet/in.h>
#ifdef HAVE_NETINET_IN6_H
# include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET6_IN6_H
# include <netinet6/in6.h>
#endif
#ifdef HAVE_LINUX_IN6_H
# include <linux/in6.h>
#endif

#endif

#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef HAVE_DB_H
#include <db.h>
#endif
#ifdef HAVE_NDBM_H
#define datum Ndatum
#include <ndbm.h>
#undef datum
#endif
#ifdef HAVE_GDBM_H
#define datum Gdatum
#include <gdbm.h>
#undef datum
#endif

#define _POLICYTEST_INTERNAL_
#include "policytest.h"


void policydefine(relp, dbtype, dbpath)
struct policytest **relp;
char *dbtype, *dbpath;
{
  struct policytest *rel = (void*)emalloc(sizeof(*rel));
  *relp = rel;
  rel->dbtype = strdup(dbtype);
  rel->dbpath = strdup(dbpath);
  rel->dbt = _dbt_none;
#ifdef HAVE_NDBM_H
  if (cistrcmp(dbtype,"ndbm")==0)
    rel->dbt = _dbt_ndbm;
  rel->ndbm = NULL; /* Initialize it in case we are the only variant */
#endif
#ifdef HAVE_GDBM_H
  if (cistrcmp(dbtype,"gdbm")==0)
    rel->dbt = _dbt_ndbm;
  rel->gdbm = NULL; /* Initialize it in case we are the only variant */
#endif
#ifdef HAVE_DB_H
  if (cistrcmp(dbtype,"btree")==0)
    rel->dbt = _dbt_btree;
  rel->btree = NULL; /* Initialize it in case we are the only variant */
#endif
  if (rel->dbt == _dbt_none) {
    /* XX: ERROR! Unknown/unsupported dbtype! */
    return;
  }

  rel->ndbm = NULL; /* Zero it -- well it is zeroed already.. */
  switch (rel->dbt) {
#ifdef HAVE_NDBM_H
    case _dbt_ndbm:
      rel->ndbm = dbm_open(dbpath, O_RDWR|O_CREAT|O_TRUNC, 0644);
      break;
#endif
#ifdef HAVE_GDBM_H
    case _dbt_gdbm:
      rel->gdbm = gdbm_open(dbpath, 0, GDBM_READER, 0644, NULL);
      break;
#endif
#ifdef HAVE_DB_H
    case _dbt_btree:
      rel->btree = dbopen(dbpath, O_RDONLY, 0644, DB_BTREE, NULL);
      break;
#endif
    default:
      break;
  }
  if (rel->ndbm == NULL) {
    /* XX: ERROR!  Could not open the database! */
    return;
  }

#ifdef HAVE_NDBM_H
#endif
#ifdef HAVE_GDBM_H
#endif
#ifdef HAVE_DB_H
#endif
}

/* Do the actual query - return pointer to the result record */
static void *dbquery(rel, qptr, qlen, rlenp)
	struct policytest *rel;
	void *qptr;
	int qlen;
	int *rlenp; /* result length ptr ! */
{
#ifdef HAVE_NDBM_H
  Ndatum Nkey, Nresult;
#endif
#ifdef HAVE_GDBM_H
  Gdatum Gkey, Gresult;
#endif
#ifdef HAVE_DB_H
  DBT Bkey, Bresult;
  int rc;
#endif


  switch (rel->dbt) {
#ifdef HAVE_NDBM_H
    case _dbt_ndbm:

      Nkey.dptr  = qptr;
      Nkey.dsize = qlen;

      Nresult = dbm_fetch(rel->ndbm,Nkey);
      *rlenp = Nresult.dsize;
      return Nresult.dptr;

      break;
#endif
#ifdef HAVE_GDBM_H
    case _dbt_gdbm:

      Gkey.dptr  = qptr;
      Gkey.dsize = qlen;

      Gresult = gdbm_fetch(rel->gdbm,Gkey);
      *rlenp = Gresult.dsize;
      return Gresult.dptr;

      break;
#endif
#ifdef HAVE_DB_H
    case _dbt_btree:


      Bkey.data = qptr;
      Bkey.size = qlen;

      rc = (rel->btree->get)(rel->btree,&Bkey,&Bresult,0);
      if (rc != 0)
	return NULL;

      *rlenp = Bresult.size;
      return Bresult.data;

      break;
#endif
    default:
      break;
  }
  return NULL;
}



int policytestaddr(rel, state, what, raddr)
	struct policytest *rel;
	struct policystate *state;
	PolicyTest what;
	struct sockaddr *raddr;
{
	return 0;
}

int policytest(rel, state, what, str)
	struct policytest *rel;
	struct policystate *state;
	PolicyTest what;
	char *str;
{
	/* XX: until we really test something... */

	return 0;
}
