/*
** Copyright (c) 2007 Sendmail, Inc. and its suppliers.
** All rights reserved.
**
** $Id: dkim-stats.c,v 1.11 2007/06/27 19:49:23 msk Exp $
*/
#ifndef lint
static char dkim_stats_c_id[] = "@(#)$Id: dkim-stats.c,v 1.11 2007/06/27 19:49:23 msk Exp $";
#endif /* !lint */
/* system includes */
#include <sys/types.h>
#include <sys/param.h>
#include <string.h>
#include <sysexits.h>
#include <errno.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <time.h>
/* libdb includes */
#include <db.h>
#ifndef DB_NOTFOUND
# define DB_NOTFOUND 1
#endif /* ! DB_NOTFOUND */
#ifndef DB_VERSION_MAJOR
# define DB_VERSION_MAJOR 1
#endif /* ! DB_VERSION_MAJOR */
#define DB_VERSION_CHECK(x,y,z) ((DB_VERSION_MAJOR == (x) && \
DB_VERSION_MINOR >= (y)) || \
DB_VERSION_MAJOR > (x))
/* sendmail includes */
#include <sm/gen.h>
#include <sm/cdefs.h>
#include <sm/string.h>
/* dkim-filter includes */
#include "stats.h"
/* globals */
char *progname;
/*
** DKIMS_DUMP -- dump a database's contents
**
** Parameters:
** path -- path to the database to dump
**
** Return value:
** None.
*/
void
dkims_dump(char *path)
{
#if ! DB_VERSION_CHECK(2,0,0)
bool first = TRUE;
#endif /* ! DB_VERSION_CHECK(2,0,0) */
int status = 0;
DB *db;
DBT key;
DBT data;
#if DB_VERSION_CHECK(2,0,0)
DBC *dbc;
#endif /* DB_VERSION_CHECK(2,0,0) */
struct dkim_stats_key reckey;
struct dkim_stats_data recdata;
assert(path != NULL);
/* open the DB */
#if DB_VERSION_CHECK(3,0,0)
status = db_create(&db, NULL, 0);
if (status == 0)
{
# if DB_VERSION_CHECK(4,0,0)
status = db->open(db, NULL, path, NULL, DB_HASH,
DB_RDONLY, 0);
# else /* DB_VERSION_CHECK(4,0,0) */
status = db->open(db, path, NULL, DB_HASH, DB_RDONLY, 0);
# endif /* DB_VERSION_CHECK(4,0,0) */
}
#elif DB_VERSION_CHECK(2,0,0)
status = db_open(path, DB_HASH, DB_RDONLY, 0, NULL, NULL, &db);
#else /* DB_VERSION_CHECK(2,0,0) */
db = dbopen(path, O_RDONLY, 0, DB_HASH, NULL);
if (db == NULL)
status = errno;
#endif /* DB_VERSION_CHECK */
if (status != 0)
{
char *err;
#if DB_VERSION_CHECK(3,0,0)
err = db_strerror(status);
#else /* DB_VERSION_CHECK(3,0,0) */
err = strerror(errno);
#endif /* DB_VERSION_CHECK(3,0,0) */
fprintf(stderr, "%s: %s: db->open(): %s\n", progname, path,
err);
return;
}
#if DB_VERSION_CHECK(2,0,0)
/* establish a cursor */
status = db->cursor(db, NULL, &dbc, 0);
if (status != 0)
{
char *err;
# if DB_VERSION_CHECK(3,0,0)
err = db_strerror(status);
# else /* DB_VERSION_CHECK(3,0,0) */
err = strerror(errno);
# endif /* DB_VERSION_CHECK(3,0,0) */
fprintf(stderr, "%s: %s: db->cursor(): %s\n", progname, path,
err);
(void) db->close(db, 0);
return;
}
#endif /* DB_VERSION_CHECK(3,0,0) */
for (;;)
{
/* read next record */
memset(&reckey, '\0', sizeof reckey);
memset(&recdata, '\0', sizeof recdata);
memset(&key, '\0', sizeof key);
memset(&data, '\0', sizeof data);
#if DB_VERSION_CHECK(3,0,0)
key.data = (void *) &reckey;
key.flags = DB_DBT_USERMEM;
key.ulen = sizeof reckey;
#endif /* DB_VERSION_CHECK(3,0,0) */
#if DB_VERSION_CHECK(3,0,0)
data.data = (void *) &recdata;
data.flags = DB_DBT_USERMEM;
data.ulen = sizeof recdata;
#endif /* DB_VERSION_CHECK(3,0,0) */
#if DB_VERSION_CHECK(2,0,0)
status = dbc->c_get(dbc, &key, &data, DB_NEXT);
if (status == DB_NOTFOUND)
{
break;
}
else if (status != 0)
{
char *err;
# if DB_VERSION_CHECK(3,0,0)
err = db_strerror(status);
# else /* DB_VERSION_CHECK(3,0,0) */
err = strerror(errno);
# endif /* DB_VERSION_CHECK(3,0,0) */
fprintf(stderr, "%s: %s: dbc->c_get(): %s\n",
progname, path, err);
dbc->c_close(dbc);
(void) db->close(db, 0);
return;
}
#else /* DB_VERSION_CHECK(2,0,0) */
status = db->seq(db, &key, &data, first ? R_FIRST : R_NEXT);
if (status == DB_NOTFOUND)
{
break;
}
else if (status != 0)
{
fprintf(stderr, "%s: %s: db->seq(): %s\n",
progname, path, strerror(errno));
(void) db->close(db);
return;
}
first = FALSE;
memcpy((void *) &reckey, key.data,
MIN(sizeof reckey, key.size));
memcpy((void *) &recdata, data.data,
MIN(sizeof recdata, key.size));
#endif /* DB_VERSION_CHECK(2,0,0) */
/* dump record contents */
fprintf(stdout,
"%s:%d/%d\t%lu pass/%lu fail, last l=%d, a=%d, %s",
reckey.sk_sigdomain,
reckey.sk_hdrcanon, reckey.sk_bodycanon,
recdata.sd_pass, recdata.sd_fail,
recdata.sd_lengths, recdata.sd_lastalg,
ctime(&recdata.sd_lastseen));
}
/* close database */
#if DB_VERSION_CHECK(2,0,0)
(void) dbc->c_close(dbc);
(void) db->close(db, 0);
#else /* DB_VERSION_CHECK(2,0,0) */
(void) db->close(db);
#endif /* DB_VERSION_CHECK(2,0,0) */
}
/*
** USAGE -- print usage message
**
** Parameters:
** None.
**
** Return value:
** EX_USAGE
*/
int
usage(void)
{
fprintf(stderr, "%s: usage(): %s path\n", progname, progname);
return EX_USAGE;
}
/*
** MAIN -- program mainline
**
** Parameters:
** argc, argv -- the usual
**
** Return value:
** Exit status.
*/
int
main(int argc, char **argv)
{
char *p;
progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1;
if (argc != 2)
return usage();
dkims_dump(argv[1]);
return EX_OK;
}
syntax highlighted by Code2HTML, v. 0.9.1