/* ** 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 #include #include #include #include #include #include #include #include /* libdb includes */ #include #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 #include #include /* 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; }