/* Copyright 1993-2002 - Matti Aarnio
The way the Zmailer uses DBM entries is by using strings with
their terminating NULL as keys, and as data.. Thus the length
is strlen(string)+1, not strlen(string) !
*/
/*
* WARNING: Policy data parsing does use unchecked buffers!
*/
#define NO_Z_IO_H
#include "../lib/linebuffer.c"
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef HAVE_NDBM
#define datum Ndatum
#include <ndbm.h>
#undef datum
#endif
#ifdef HAVE_GDBM
#define datum Gdatum
#include <gdbm.h>
#undef datum
#endif
#include "sleepycatdb.h"
#define _POLICYTEST_INTERNAL_
#include "policy.h"
#define PROG "makedb"
#include <errno.h>
extern int errno; /* Not all systems declare it in <errno.h>, sigh ... */
extern int optind;
int store_errors = 0;
char *progname = NULL;
int D_alloc = 0;
int verbose = 0;
int append_mode = 0;
int lc_key = 0;
int uc_key = 0;
int silent = 0;
int aliasinput = 0;
int policyinput = 0;
/* extern char *strchr(); */
extern void create_dbase __((FILE *, void *, int));
extern char *skip821address __((char *));
extern void usage __((const char *, const char *, int));
void usage(prog, errs, err)
const char *prog, *errs;
int err;
{
fprintf(stderr, "Usage: %s [-l|-u]] [-A][-a|-p][-s] dbtype database.name [infilename|-]\n", prog);
fprintf(stderr, " where supported dbtypes are:");
#ifdef HAVE_NDBM
fprintf(stderr, " ndbm");
#endif
#ifdef HAVE_GDBM
fprintf(stderr, " gdbm");
#endif
#ifdef HAVE_DB
fprintf(stderr, " btree bhash");
#endif
fprintf(stderr, "\n");
fprintf(stderr, " Error now: %s", errs);
if (err != 0) {
fprintf(stderr, ", errno=%d (%s)", err, strerror(err));
fprintf(stderr, "\n");
exit(1);
}
fprintf(stderr, "\n\n If no infilename is defined, database.name is assumed.\n");
#ifdef HAVE_NDBM
fprintf(stderr, " (NDBM appends .pag, and .dir into actual db file names..)\n");
#endif
#ifdef HAVE_GDBM
fprintf(stderr, " (GDBM appends .gdbm, to the actual db file name..)\n");
#endif
#ifdef HAVE_DB
fprintf(stderr, " (BTREE appends .db, to the actual db file name..)\n");
fprintf(stderr, " (BHASH appends .pag, and .dir into actual db file names..)\n");
#if defined(HAVE_DB2) || defined(HAVE_DB3) || defined(HAVE_DB4)
fprintf(stderr, " (Version: %s)\n", db_version(NULL,NULL,NULL));
#else
fprintf(stderr, " (Version 1.x ?)\n");
#endif
#endif
fprintf(stderr, "\n");
fprintf(stderr,
" The '-a' option is for parsing input that comes in\n\
'aliases' format: 'key: data,in,long,line,'\n\
' with,indented,extended,lines'\n\
The '-p' option is for parsing smtpserver policy database.\n\
The '-A' option APPENDS new data to existing keyed data.\n\
The '-l' and '-u' will lower-/uppercasify key string before\n\
storing it into the database. This does not apply to '-p'.\n\
The '-s' option orders 'silent running' -- report only errors.\n");
exit(64);
}
/* KK() and KA() macroes are at "policy.h" */
static char *showkey __((const char *key));
static char *showkey(key)
const char *key;
{
static char buf[256];
if (key[1] != P_K_IPv4 && key[1] != P_K_IPv6) {
if (strlen(key+2) > (sizeof(buf) - 200))
sprintf(buf,"%d/%s/'%s'", key[0], KK(key[1]), "<too long name>");
else
sprintf(buf,"%d/%s/'%s'", key[0], KK(key[1]), key+2);
} else
if (key[1] == P_K_IPv4)
sprintf(buf,"%d/%s/%u.%u.%u.%u/%d",
key[0], KK(key[1]),
key[2] & 0xff, key[3] & 0xff, key[4] & 0xff, key[5] & 0xff,
key[6] & 0xff);
else
sprintf(buf,"%d/%s/%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x/%d",
key[0], KK(key[1]),
key[2] & 0xff, key[3] & 0xff, key[4] & 0xff, key[5] & 0xff,
key[6] & 0xff, key[7] & 0xff, key[8] & 0xff, key[9] & 0xff,
key[10] & 0xff, key[11] & 0xff, key[12] & 0xff, key[13] & 0xff,
key[14] & 0xff, key[15] & 0xff, key[16] & 0xff, key[17] & 0xff,
key[18] & 0xff);
return buf;
}
static int store_db __((void *, const int, const int, const int, const void *, const int, const void *, const int));
static int store_db(dbf, typ, overwritemode, linenum, t, tlen, s, slen)
void *dbf;
const int typ, linenum;
const void *s, *t;
const int slen, tlen;
{
#ifdef HAVE_NDBM
DBM *ndbmfile = dbf;
#endif
#ifdef HAVE_GDBM
GDBM_FILE gdbmfile = dbf;
#endif
#ifdef HAVE_DB
DB *dbfile = dbf;
#endif
int rc = -2;
if (verbose) {
if (policyinput) {
const char *k = (const char *)t;
fprintf(stderr, "Storing key='%s' data=...\n", showkey(k));
} else
fprintf(stderr, "Storing key='%s' data='%s'\n",
(const char*)t, (const char *)s);
}
switch (typ) {
#ifdef HAVE_NDBM
case 1:
{
Ndatum Ndat, Nkey;
Nkey.dptr = (void*)t;
Nkey.dsize = tlen;
Ndat.dptr = (void*)s;
Ndat.dsize = slen;
rc = dbm_store(ndbmfile, Nkey, Ndat,
overwritemode ? DBM_REPLACE : DBM_INSERT);
if (rc < 0 && errno == ENOSPC) {
fprintf(stderr,"NDBM does not allow KEY.LEN + DATA.LEN to exceed 1024 bytes! linenro=%d\n",linenum);
}
}
break;
#endif
#ifdef HAVE_GDBM
case 2:
{
Gdatum Gdat, Gkey;
Gkey.dptr = (void*)t;
Gkey.dsize = tlen;
Gdat.dptr = (void*)s;
Gdat.dsize = slen;
rc = gdbm_store(gdbmfile, Gkey, Gdat,
overwritemode ? GDBM_REPLACE : GDBM_INSERT);
}
break;
#endif
#ifdef HAVE_DB
case 3: case 4:
{
DBT Bkey, Bdat;
memset(&Bkey,0,sizeof(Bkey));
memset(&Bdat,0,sizeof(Bdat));
Bkey.data = (void*)t;
Bkey.size = tlen;
Bdat.data = (void*)s;
Bdat.size = slen;
#ifdef DB_INIT_TXN
rc = (dbfile->put) (dbfile, NULL, &Bkey, &Bdat,
overwritemode ? 0: DB_NOOVERWRITE);
/* emulate BSD DB 1.85 return values */
rc = -rc;
#else
rc = (dbfile->put) (dbfile, &Bkey, &Bdat,
overwritemode ? 0: R_NOOVERWRITE);
#endif
}
break;
#endif
} /* end of switch(typ) ... */
if (rc > 0 && append_mode == 0)
return rc; /* Duh! Duplicate, and no append_mode :-( */
if (rc > 0 && overwritemode == 0) {
/* we shall try append, at first we have to get the old
data, and then append to it... */
void *dataptr = NULL;
int datalen = 0;
char *newptr = NULL;
int newlen = 0;
switch (typ) {
#ifdef HAVE_NDBM
case 1:
{
Ndatum Ndat, Nkey;
Nkey.dptr = (void*)t;
Nkey.dsize = tlen;
Ndat = dbm_fetch(ndbmfile, Nkey);
dataptr = Ndat.dptr;
datalen = Ndat.dsize;
}
break;
#endif
#ifdef HAVE_GDBM
case 2:
{
Gdatum Gdat, Gkey;
Gkey.dptr = (void*)t;
Gkey.dsize = tlen;
Gdat = gdbm_fetch(gdbmfile, Gkey);
dataptr = Gdat.dptr; /* Must free() this */
datalen = Gdat.dsize;
}
break;
#endif
#ifdef HAVE_DB
case 3: case 4:
{
DBT Bkey, Bdat;
memset(&Bkey,0,sizeof(Bkey));
memset(&Bdat,0,sizeof(Bdat));
Bkey.data = (void*)t;
Bkey.size = tlen;
#ifdef DB_INIT_TXN
rc = (dbfile->get) (dbfile, NULL, &Bkey, &Bdat, 0);
#else
rc = (dbfile->get) (dbfile, &Bkey, &Bdat, 0);
#endif
if (rc != 0)
memset(&Bdat, 0, sizeof(Bdat));
dataptr = Bdat.data;
datalen = Bdat.size;
}
break;
#endif
} /* end of .. switch(typ) ... */
/* Ok, now we have dataptr and datalen -- we should have
non-NULL dataptr. We need to build a new block with
combined data */
if (dataptr == NULL)
return -1; /* Duh !? */
newlen = datalen + slen;
newptr = emalloc(newlen + 4);
if (append_mode > 0) { /* Ordinary alias append */
--datalen;
memcpy(newptr, dataptr, datalen);
memcpy(newptr + datalen, ",\n\t", 3);
memcpy(newptr + datalen + 3, s, slen);
newlen = datalen + slen + 3;
} else { /* append_mode < 0; PolicyDataset append; binary stuff */
memcpy(newptr, dataptr, datalen);
memcpy(newptr + datalen, s, slen);
}
if (typ == 2)
free(dataptr); /* GDBM fetched datablock must be freed */
rc = store_db(dbf, typ, 1, linenum, t, tlen, newptr, newlen);
free(newptr); /* Our temporary datablock must be freed */
return rc;
}
if (rc < 0)
store_errors = 1;
return rc;
}
extern int parsepolicykey __((void *, char *));
extern int parseattributepair __((void *, char *, char *));
/* Scan over quoted string with embedded white spaces, or
in case the object does not start with a double quote,
just all non-white-space chars. */
static char *tokskip __((char *, char **));
static char *
tokskip(s, sout)
char *s;
char **sout;
{
char *start;
while (*s == ' ' || *s == '\t')
++s;
*sout = s;
if (*s == '\0')
return NULL;
if (*s == '"') {
++s;
start = s;
/* Scan thru the quoted string:
"message text right here" */
while (*s != '\0') {
if (*s == '"') {
/* Ending double-quote */
*s = '\0';
++s;
break;
}
++s;
}
} else {
start = s;
/* Scan over non-white-space chars */
while (*s != '\0' && *s != ' ' && *s != '\t')
++s;
if (*s != '\0')
*(s++) = '\0';
}
*sout = s;
return start;
}
int create_policy_dbase(infile, dbf, typ)
FILE *infile;
void *dbf;
const int typ;
{
char policykeybuf[256]; /* Plenty enough ? */
char policydata[16*1024];
char *s, *t, *str1, *str2;
int rc, tlen, slen, llen;
int errflag = 0;
int policydatalen = 0;
int linenum = 0;
/* Turn the append_mode into negative value -- this tells
store_db() to work differently from alias append */
append_mode = -append_mode;
while ((llen = zgetline(infile)) != 0) {
++linenum;
policydatalen = 0;
if (zlinebuf[llen-1] != '\n') {
/* Eh ? No line ending newline ?
Ah well, there is always at least one byte
of space after the read block. */
++llen;
fprintf(stderr, "input line of len %d lacking trailing newline, corrupted file ?\n", llen-1);
errflag = 1;
}
zlinebuf[llen-1] = '\0';
if (*zlinebuf == '#')
continue; /* Comment! */
if (*zlinebuf == ' ' || *zlinebuf == '\t')
continue; /* Starts with a white-space! */
/* Scan first white-space separated token,
point its start with t! */
t = zlinebuf;
while (*t == '\t' || *t == ' ')
++t;
if (*t == 0)
continue; /* Blank line! */
if (*t == '#')
continue; /* Comment.. */
s = t;
/* scan over first word */
while (*s && *s != '\t' && *s != ' ')
++s;
/* Stopped without line-end NIL ? Trunc, and advance! */
if (*s)
*s++ = 0;
strlower(t); /* Lowercasify the key */
rc = parsepolicykey((void *) policykeybuf, t);
if (rc != 0) {
/* XX: rc != 0 ==> error */
fprintf(stderr,
"Error: line %d: bad policykey, rc = %d\n",
linenum, rc);
errflag = 1;
continue;
}
/* Skip LWSP */
/* while (*s == ' ' || *s == '\t') ++s;
*/
/* Collect attribute pairs */
str1 = tokskip(s, &s);
if (!str1 || *str1 == '#')
continue; /* Data begins a within line comment, or
is completely void.. */
if (str1 == NULL) {
fprintf(stderr,
"Error: No attribute pair on line %d.\n",
linenum);
errflag = 1;
continue;
} else {
int err = 0;
while (1) {
str2 = tokskip(s, &s);
if (str2 == NULL) {
fprintf(stderr,
"Error: Invalid attribute pair on line %d; aname='%s', value missing.\n",
linenum, str1);
errflag = 1;
err = 1;
break;
}
rc = parseattributepair((void *) &policydata[policydatalen],
str1, str2);
if (rc != 0) {
fprintf(stderr,
"Error: Invalid attribute pair (\"%s %s\") on line %d.\n",
str1, str2, linenum);
errflag = 1;
err = 1;
break;
}
policydatalen += policydata[policydatalen] & 0xFF;
str1 = tokskip(s, &s);
if (str1 == NULL)
break;
}
if (err)
continue;
}
t = (void *) &policykeybuf[0];
tlen = (policykeybuf[0] & 0xFF);
s = (void *) &policydata[0];
slen = policydatalen;
rc = store_db(dbf, typ, 0, linenum,
t, tlen, s, slen);
if (rc > 0) {
char *s;
fprintf(stderr, "WARNING: Duplicate key at line %d: ",
linenum);
s = showkey(policykeybuf);
fprintf(stderr, "%s\n", s);
}
}
return errflag;
}
char *
skipaliastoken(s)
char *s;
{
char quote = 0;
char c;
while ((c = *s)) {
if (c == '\\') {
++s;
if (*s == 0)
break;
}
if (c == quote) /* 'c' is non-zero here */
quote = 0;
else if (c == '"')
quote = '"';
else if (!quote && (c == ' ' || c == '\t' || c == ':'))
break;
++s;
}
/* Scan possible white space in between alias token,
and the colon after it; Zero it while doing this */
while (*s == '\t' || *s == ' ') {
*s++ = '\0';
}
/* Must have colon, if we have it, we zero it, and return
pointer to after it. */
if (*s == ':') {
*s++ = '\0';
return s;
}
/* Didn't have colon, error! */
return NULL;
}
int create_aliases_dbase(infile, dbf, typ)
FILE *infile;
void *dbf;
const int typ;
{
int tlen, slen, llen;
char *s, *t;
char *t0 = NULL, *s0 = NULL;
int linenum = 0;
int errflag = 0;
int longest = 0;
int count = 0;
long totsize = 0;
while ((llen = zgetline(infile)) != 0) {
++linenum;
if (zlinebuf[llen-1] != '\n') {
/* Eh ? No line ending newline ?
Ah well, there is always at least one byte
of space after the read block. */
++llen;
fprintf(stderr, "input line lacking trailing newline, corrupted file ?\n");
fprintf(stderr, " len=%d, zlinebuf='%s'\n", llen, zlinebuf);
}
zlinebuf[llen-1] = '\0';
if (verbose)
fprintf(stderr,"aliases parser: zgetline() llen=%d, str='%.*s'\n",
llen, llen, zlinebuf);
if (*zlinebuf == '#') {
/* Comment! */
store_and_continue:
if (t0 != NULL) {
tlen = strlen(t0) + 1;
slen = strlen(s0) + 1;
++count;
totsize += slen;
if (longest < slen)
longest = slen;
if (uc_key)
strupper(t0); /* Uppercasify the key */
if (lc_key)
strlower(t0); /* Lowercasify the key */
if (store_db(dbf, typ, 0, linenum,
t0, tlen, s0, slen) < 0)
break;
if (t0) free(t0); t0 = NULL;
if (s0) free(s0); s0 = NULL;
}
continue;
}
t = zlinebuf;
/* Key starts at line start, continuation lines start
with white-space */
if (*t == 0)
goto store_and_continue; /* Blank line! */
if (t0 != NULL && (*t == '\t' || *t == ' ')) {
/* Continuation line */
while (*t == '\t' || *t == ' ') ++t;
slen = strlen(s0);
tlen = strlen(t);
for (llen = slen; llen > 0; --llen) {
/* Chop trailing white-space, if any */
if (s0[llen-1] == ' ' || s0[llen-1] == '\t') {
s0[llen-1] = '\0';
} else
break;
}
slen = llen; /* Shortened, possibly.. */
if (s0[llen-1] != ',') {
fprintf(stderr, "Line %d: Continuation line on alias without preceeding line ending with comma (',')\n", linenum);
errflag = 1;
continue;
}
s0 = erealloc(s0, slen + tlen + 1);
memcpy(s0 + slen, t, tlen + 1); /* end NIL included */
continue;
}
if (*t == '\t' || *t == ' ') {
/* Continuation line without previous key line */
fprintf(stderr,"Line %d: Continuation line without initial keying line\n", linenum);
errflag = 1;
continue;
}
/* Ok, we MAY have proper line here.
If we now have saved t0/s0, we store them here */
if (t0 != NULL) {
tlen = strlen(t0) + 1;
slen = strlen(s0) + 1;
++count;
totsize += slen;
if (longest < slen)
longest = slen;
if (uc_key)
strupper(t0); /* Uppercasify the key */
if (lc_key)
strlower(t0); /* Lowercasify the key */
if (store_db(dbf, typ, 0, linenum,
t0, tlen, s0, slen) < 0)
break;
if (t0) free(t0); t0 = NULL;
if (s0) free(s0); s0 = NULL;
}
s = skipaliastoken(t);
/* We [s] are now at the white-space -- possibly the last
char of the line prefix is a double-colon (:) */
if (s == NULL) {
/* This alias-token is invalid */
fprintf(stderr,"Line %d: Invalid alias key token; missing colon ?\n",
linenum);
errflag = 1;
continue;
}
/* Scan forward for additional data start */
while (*s && (*s == '\t' || *s == ' '))
++s;
t0 = strdup(t);
strlower(t0); /* Lowercasify the key */
s0 = strdup(s);
/* Now we continue reading more input lines ... */
}
/* Something left to be stored ? */
if (t0 != NULL) {
tlen = strlen(t0) + 1;
slen = strlen(s0) + 1;
++count;
totsize += slen;
if (longest < slen)
longest = slen;
if (uc_key)
strupper(t0); /* Uppercasify the key */
if (lc_key)
strlower(t0); /* Lowercasify the key */
(void) store_db(dbf, typ, 0, linenum,
t0, tlen, s0, slen);
if (t0) free(t0); t0 = NULL;
if (s0) free(s0); s0 = NULL;
}
if (!silent)
fprintf(stdout, "%d aliases, longest %d bytes, %ld bytes total\n",
count, longest, totsize);
return errflag;
}
int create_keyed_dbase(infile, dbf, typ)
FILE *infile;
void *dbf;
const int typ;
{
int tlen, slen, llen;
char *s, *t;
int linenum = 0;
int errflag = 0;
while ((llen = zgetline(infile)) != 0) {
++linenum;
if (zlinebuf[llen-1] != '\n') {
/* Eh ? No line ending newline ?
Ah well, there is always at least one byte
of space after the read block. */
++llen;
fprintf(stderr, "input file lacking trailing newline, corrupted file ?\n");
}
zlinebuf[llen-1] = '\0';
if (*zlinebuf == '#')
continue; /* Comment! */
/* Scan first white-space separated token,
point its start with t! */
t = zlinebuf;
while (*t == '\t' || *t == ' ')
++t;
if (*t == 0)
continue; /* Blank line! */
if (*t == '#')
continue; /* Comment.. */
s = t;
/* Scan over the non-LWSP text */
while (*s && *s != '\t' && *s != ' ')
++s;
/* Stopped without line-end NIL ? Trunc, and advance! */
if (*s)
*s++ = 0;
/* Scan forward, if we have some LWSP here, and then more data ? */
while (*s && (*s == '\t' || *s == ' '))
++s;
if (uc_key)
strupper(t); /* Uppercasify the key */
if (lc_key)
strlower(t); /* Lowercasify the key */
tlen = strlen(t) + 1;
slen = strlen(s) + 1;
if (store_db(dbf, typ, 0, linenum,
t, tlen, s, slen) < 0) {
errflag = 1; /* Duplicate ?? */
break;
}
}
return errflag;
}
int main(argc, argv)
int argc;
char *argv[];
{
char *dbasename = NULL;
FILE *infile = NULL;
int c, rc;
int typ = 0;
#ifdef HAVE_NDBM
DBM *ndbmfile = NULL;
#endif
#ifdef HAVE_GDBM
GDBM_FILE gdbmfile = NULL;
#endif
#ifdef HAVE_DB
DB *dbfile = NULL;
#endif
char *dbtype = NULL;
void *dbf = NULL;
char *argv0 = argv[0];
int err;
progname = argv[0];
while ((c = getopt(argc, argv, "Aalpsuv")) != EOF) {
switch (c) {
case 'l':
lc_key = 1;
break;
case 'u':
uc_key = 1;
break;
case 'A':
append_mode = 1;
break;
case 'a':
aliasinput = 1;
break;
case 'p':
policyinput = 1;
break;
case 's':
silent = 1;
break;
case 'v':
verbose = 1;
break;
default:
break;
}
}
/* Usage: */
/* makedb [-Aap] dbtype database.name [infilename|-] */
/* argv[] 0 1 2 3 4 */
/* printf("optind = %d, argc = %d\n", optind, argc); */
if ((argc - optind) < 2)
usage(argv0, "too few arguments", 0);
if ((argc - optind) > 3)
usage(argv0, "too many arguments", 0);
dbasename = argv[optind + 1];
if ((argc - optind) == 3) {
if (strcmp(argv[optind + 2], "-") == 0)
infile = stdin;
else
infile = (FILE *) fopen(argv[optind + 2], "r");
} else
infile = stdin;
dbtype = argv[optind];
if (infile == NULL)
usage(argv0, "bad infile", errno);
typ = 0;
#ifdef HAVE_NDBM
if (cistrcmp(dbtype, "ndbm") == 0)
typ = 1;
#endif
#ifdef HAVE_GDBM
if (cistrcmp(dbtype, "gdbm") == 0)
typ = 2;
#endif
#ifdef HAVE_DB
if (cistrcmp(dbtype, "btree") == 0)
typ = 3;
if (cistrcmp(dbtype, "bhash") == 0)
typ = 4;
#endif
switch (typ) {
case 0:
usage(argv0, "unknown dbtype", 0);
break;
#ifdef HAVE_NDBM
case 1:
ndbmfile = dbm_open(dbasename, O_RDWR | O_CREAT | O_TRUNC, 0644);
dbf = ndbmfile;
break;
#endif
#ifdef HAVE_GDBM
case 2:
/* Play loose .. don't do syncs while writing */
dbasename = strcpy(malloc(strlen(dbasename) + 8), dbasename);
strcat(dbasename, ".gdbm"); /* ALWAYS append this */
gdbmfile = gdbm_open(dbasename, 0, GDBM_NEWDB | GDBM_FAST, 0644, NULL);
dbf = gdbmfile;
break;
#endif
#ifdef HAVE_DB
#if defined(HAVE_DB3) || defined(HAVE_DB4)
case 3:
dbasename = strcpy(malloc(strlen(dbasename) + 8), dbasename);
strcat(dbasename, ".db"); /* ALWAYS append this */
dbfile = NULL;
err = db_create(&dbfile, NULL, 0);
if (! err)
err = dbfile->open(dbfile,
#if (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR == 1)
NULL, /* TXN id was added at SleepyDB 4.1 */
#endif
dbasename, NULL, DB_BTREE,
DB_CREATE|DB_TRUNCATE, 0644);
if (!err)
dbf = dbfile;
break;
case 4:
dbasename = strcpy(malloc(strlen(dbasename) + 8), dbasename);
strcat(dbasename, ".db"); /* ALWAYS append this */
dbfile = NULL;
err = db_create(&dbfile, NULL, 0);
if (! err)
err = dbfile->open(dbfile,
#if (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR == 1)
NULL, /* TXN id was added at SleepyDB 4.1 */
#endif
dbasename, NULL, DB_HASH,
DB_CREATE|DB_TRUNCATE, 0644);
if (!err)
dbf = dbfile;
break;
#else
#if defined(HAVE_DB2)
case 3:
dbasename = strcpy(malloc(strlen(dbasename) + 8), dbasename);
strcat(dbasename, ".db"); /* ALWAYS append this */
dbfile = NULL;
err = db_open(dbasename, DB_BTREE, DB_CREATE|DB_TRUNCATE,
0644, NULL, NULL, &dbfile);
if (! err)
dbf = dbfile;
break;
case 4:
dbasename = strcpy(malloc(strlen(dbasename) + 8), dbasename);
strcat(dbasename, ".db"); /* ALWAYS append this */
dbfile = NULL;
err = db_open(dbasename, DB_HASH, DB_CREATE|DB_TRUNCATE,
0644, NULL, NULL, &dbfile);
if (! err)
dbf = dbfile;
break;
#else
case 3:
dbasename = strcpy(malloc(strlen(dbasename) + 8), dbasename);
strcat(dbasename, ".db"); /* ALWAYS append this */
dbfile = dbopen(dbasename, O_RDWR | O_CREAT | O_TRUNC, 0644,
DB_BTREE, NULL);
dbf = dbfile;
break;
case 4:
dbasename = strcpy(malloc(strlen(dbasename) + 8), dbasename);
strcat(dbasename, ".db"); /* ALWAYS append this */
dbfile = dbopen(dbasename, O_RDWR | O_CREAT | O_TRUNC, 0644,
DB_HASH, NULL);
dbf = dbfile;
break;
#endif
#endif
#endif
}
if (dbf == NULL)
usage(argv0, "Can't open dbase file", errno);
initzline(BUFSIZ);
if (policyinput)
rc = create_policy_dbase(infile, dbf, typ);
else if (aliasinput)
rc = create_aliases_dbase(infile, dbf, typ);
else
rc = create_keyed_dbase(infile, dbf, typ);
switch (typ) {
#ifdef HAVE_NDBM
case 1:
dbm_close(ndbmfile);
break;
#endif
#ifdef HAVE_GDBM
case 2:
gdbm_close(gdbmfile);
break;
#endif
#ifdef HAVE_DB
case 3: case 4:
(dbfile->sync) (dbfile, 0);
#if defined(HAVE_DB_CLOSE2)
(dbfile->close) (dbfile, 0);
#else
(dbfile->close) (dbfile);
#endif
break;
#endif
} /* end of .. switch(typ) .. */
if (store_errors) {
fprintf(stderr,"STORE ERRORS DURING DATABASE WRITE!\n");
rc = 1;
}
return (rc ? 1 : 0);
}
syntax highlighted by Code2HTML, v. 0.9.1