/*************************************************
*     Exim - an Internet mail transport agent    *
*************************************************/

/* Copyright (c) University of Cambridge 1995 - 1999 */
/* See the file NOTICE for conditions of use and distribution. */

#include "../exim.h"
#include "dbmdb.h"

/* Compile these functions only if LOOKUP_DBM is defined. However, some
compilers don't like compiling empty modules, so keep them happy with a dummy
when skipping the rest. Make it reference itself to stop picky compilers
complaining that it is unused, and put in a dummy argument to stop even pickier
compilers complaining about infinite loops. */

#ifndef LOOKUP_DBM
static void dummy(int x) { dummy(x-1); }
#else


/*************************************************
*              Open entry point                  *
*************************************************/

/* See local README for interface description */

void *
dbmdb_open(char *filename, char **errmsg)
{
EXIM_DB *yield;
EXIM_DBOPEN(filename, O_RDONLY, 0, &yield);
if (yield == NULL)
  {
  int save_errno = errno;
  *errmsg = string_open_failed(errno, "%s as a %s file", filename, EXIM_DBTYPE);
  errno = save_errno;
  }
return yield;
}



/*************************************************
*             Check entry point                  *
*************************************************/

/* This needs to know more about the underlying files than is good for it!
We need to know what the real file names are in order to check the owners
and modes. If USE_DB is set, we know it is Berkeley DB, which an unmodified
file name. Otherwise, for safety, we have to check for x.db or x.dir and
x.pag. */

BOOL
dbmdb_check(void *handle, char *filename, int modemask, int *owners,
  int *owngroups, char **errmsg)
{
int rc;
handle = handle;    /* Keep picky compilers happy */

#ifdef USE_DB
rc = search_check_file(-1, filename, modemask, owners, owngroups,
  "dbm", errmsg);
#else
  {
  char filebuffer[256];
  sprintf(filebuffer, "%.250s.db", filename);
  rc = search_check_file(-1, filebuffer, modemask, owners, owngroups,
    "dbm", errmsg);
  if (rc < 0)        /* stat() failed */
    {
    sprintf(filebuffer, "%.250s.dir", filename);
    rc = search_check_file(-1, filebuffer, modemask, owners, owngroups,
      "dbm", errmsg);
    if (rc == 0)     /* x.dir was OK */
      {
      sprintf(filebuffer, "%.250s.pag", filename);
      rc = search_check_file(-1, filebuffer, modemask, owners, owngroups,
        "dbm", errmsg);
      }
    }
  }
#endif

return rc == 0;
}



/*************************************************
*              Find entry point                  *
*************************************************/

/* See local README for interface description */

int
dbmdb_find(void *handle, char *filename, char *keystring, int length,
  char **result, char **errmsg)
{
EXIM_DB *d = (EXIM_DB *)handle;
EXIM_DATUM key, data;

filename = filename;    /* Keep picky compilers happy */
errmsg = errmsg;

#ifdef EXIM_CLEAR_DATUMSTRUCT
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
#endif

EXIM_DATUM_DATA(key) = keystring;
EXIM_DATUM_SIZE(key) = length + 1;
if (EXIM_DBGET(d, key, data))
  {
  *result = string_copy(EXIM_DATUM_DATA(data));
  return OK;
  }
return FAIL;
}



/*************************************************
*              Close entry point                 *
*************************************************/

/* See local README for interface description */

void
dbmdb_close(void *handle)
{
EXIM_DBCLOSE((EXIM_DB *)handle);
}

#endif  /* LOOKUP_DBM */

/* End of lookups/dbmdb.c */
