/* 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 #include #include #include #ifdef HAVE_NDBM #define datum Ndatum #include #undef datum #endif #ifdef HAVE_GDBM #define datum Gdatum #include #undef datum #endif #include "sleepycatdb.h" #define _POLICYTEST_INTERNAL_ #include "policy.h" #define PROG "makedb" #include extern int errno; /* Not all systems declare it in , 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]), ""); 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); }