Postfix version 19991231 Patchlevel 10 is available. This version contain fixes that were already made available via snapshot releases. - Berkeley DB support has changed for Solaris, HP-UX, UNIXWARE, IRIX. On these systems, Postfix loses the file lock while building a table, so that table lookups fail and mail is lost. See the DB_README file for instructions on how to build Postfix with third-party Berkeley DB support. - Virtual map expansion stopped too early with self-referential aliases. The patch, too large for distribution via email, as well as a fully patched release, is made available from the usual Postfix mirror sites listed at http://www.postfix.org/ftp-sites.html. Primary site is: ftp://ftp.porcupine.org/mirrors/postfix-release/experimental/ files: postfix-19991231-pl10.tar.gz (Source code) postfix-19991231-pl10.tar.gz.sig (PGP signature) postfix-19991231-patch10.gz (Source patch) Or point your web browser to: ftp://ftp.porcupine.org/mirrors/postfix-release/index.html Happy Postfixing! Wietse Prereq: "Postfix-19991231-pl09" diff -cr --new-file ../postfix-19991231-pl09/global/mail_version.h ./global/mail_version.h *** ../postfix-19991231-pl09/global/mail_version.h Sun Sep 17 09:52:53 2000 --- ./global/mail_version.h Sun Oct 29 19:06:58 2000 *************** *** 15,21 **** * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "Postfix-19991231-pl09" extern char *var_mail_version; /* LICENSE --- 15,21 ---- * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "Postfix-19991231-pl10" extern char *var_mail_version; /* LICENSE diff -cr --new-file ../postfix-19991231-pl09/DB_README ./DB_README *** ../postfix-19991231-pl09/DB_README Wed Dec 31 19:00:00 1969 --- ./DB_README Sun Oct 29 18:56:55 2000 *************** *** 0 **** --- 1,68 ---- + Purpose of this document + ======================== + + This document describes how to build Postfix with third-party + Berkeley DB from www.sleepycat.com, or how to choose a specific + Berkeley DB version when your system provides multiple implementations. + + Building Postfix with Sleepycat Berkeley DB + =========================================== + + Many commercial UNIXes ship without Berkeley DB support. Examples + are Solaris, HP-UX, IRIX, UNIXWARE. In order to build Postfix with + Berkeley DB support you need to download and install the source + code from www.sleepycat.com. + + To build Postfix after you installed the Berkeley DB from Sleepycat, + use something like: + + % make tidy + % make makefiles CCARGS="-DHAS_DB -I/usr/local/BerkeleyDB.3.1/include" \ + AUXLIBS=/usr/local/BerkeleyDB.3.1/lib/libdb.a + % make + + The exact pathnames depend on the DB version that you installed. + For example, Berkeley DB version 2 installs in /usr/local/BerkeleyDB. + + Beware, the file format produced by Berkeley DB version 1 is not + compatible with that of versions 2 and 3 (versions 2 and 3 have + the same format). If you switch between DB versions, then you may + have to rebuild all your Postfix DB files. + + Building Postfix on BSD systems with a specific Berkeley DB version + =================================================================== + + Some BSD systems ship with multiple Berkeley DB implementations. + Normally, Postfix builds with the default DB version that ships + with the system. + + To build Postfix on BSD systems with a specific DB version, use a + variant of the following commands: + + % make tidy + % make makefiles CCARGS=-I/usr/include/db2 AUXLIBS=-ldb2 + % make + + Beware, the file format produced by Berkeley DB version 1 is not + compatible with that of versions 2 and 3 (versions 2 and 3 have + the same format). If you switch between DB versions, then you may + have to rebuild all your Postfix DB files. + + Building Postfix on Linux with a specific Berkeley DB version + ============================================================= + + Some Linux systems systems ship with multiple Berkeley DB + implementations. Normally, Postfix builds with the default DB + version that ships with the system. + + On Linux, you need to edit the makedefs script in order to specify + a non-default DB library. + + The reason is that the location of the default db.h include file + changes randomly between vendors and between versions, so that + Postfix has to choose the file for you. + + Beware, the file format produced by Berkeley DB version 1 is not + compatible with that of versions 2 and 3 (versions 2 and 3 have + the same format). If you switch between DB versions, then you may + have to rebuild all your Postfix DB files. diff -cr --new-file ../postfix-19991231-pl09/HISTORY ./HISTORY *** ../postfix-19991231-pl09/HISTORY Sun Sep 17 21:25:53 2000 --- ./HISTORY Mon Oct 30 09:35:25 2000 *************** *** 3752,3758 **** 20000621 AIX 4.x had POSIX regular expression support all the time ! I was working on Postfix. Beter find out late than never. 20000623 --- 3752,3758 ---- 20000621 AIX 4.x had POSIX regular expression support all the time ! I was working on Postfix. Better find out late than never. 20000623 *************** *** 3826,3828 **** --- 3826,3856 ---- Bugfix: postalias -i would complain about duplicate entries for the Sendmail-compatible @ entry and for the NIS-compatible YP_LAST_MODIFIED and YP_MASTER_NAME entries. + + 20001025 + + Bugfix: virtual map expansion stopped too early with + self-referential aliases. Reported by Michael Douglass + @ datafoundry.net. File: cleanup/cleanup_map1n.c. + + 20001026 + + Horror: postmap and postalias (newaliases) silently lose + the file lock while building a lookup table with Berkeley + DB 2.x and later on Solaris, HP-UX, IRIX, and UNIXWARE. + The result is that table lookups fail while the table is + being built, so that mail is lost. In order to avoid this + misbehavior one has to use an undocumented feature that is + NOT available with the DB1.85 compatibility interface. + Therefore, Postfix now supports three Berkeley DB programming + interfaces of increasing complexity. File: util/dict_db.c. + + Bugfix: some character manipulations were not portable for + signed/unsigned characters. Files: global/quote_821_local.c, + global/quote_822_local.c. + + 20001030 + + Bugfix: further testing in preparation for 19991231-pl10 + revealed that the DB map code was now broken for every + platform. diff -cr --new-file ../postfix-19991231-pl09/RELEASE_NOTES ./RELEASE_NOTES *** ../postfix-19991231-pl09/RELEASE_NOTES Sun May 28 19:43:08 2000 --- ./RELEASE_NOTES Sun Oct 29 18:58:01 2000 *************** *** 1,3 **** --- 1,13 ---- + Incompatible changes with postfix-19991231-pl10: + ================================================ + + Berkeley DB support has changed for Solaris, HP-UX, UNIXWARE, IRIX. + On these systems, Postfix must no longer use DB 1.85 compatibility + mode, because that mode loses the file lock while building a table, + so that table lookups fail and mail is lost. See the DB_README file + for instructions on how to build Postfix with third-party Berkeley + DB support. + Major changes with postfix-19991231-pl08: ========================================= diff -cr --new-file ../postfix-19991231-pl09/cleanup/cleanup_map1n.c ./cleanup/cleanup_map1n.c *** ../postfix-19991231-pl09/cleanup/cleanup_map1n.c Sat May 8 19:19:45 1999 --- ./cleanup/cleanup_map1n.c Sun Oct 29 19:02:33 2000 *************** *** 54,59 **** --- 54,60 ---- #include #include #include + #include /* Application-specific. */ *************** *** 68,74 **** int count; int i; int arg; ! int expand_to_self; char *saved_lhs; /* --- 69,75 ---- int count; int i; int arg; ! BH_TABLE *been_here; char *saved_lhs; /* *************** *** 77,82 **** --- 78,84 ---- argv = argv_alloc(1); argv_add(argv, addr, ARGV_END); argv_terminate(argv); + been_here = been_here_init(0, BH_FLAG_FOLD); /* * Rewrite the address vector in place. With each map lookup result, *************** *** 89,102 **** #define MAX_RECURSION 1000 #define MAX_EXPANSION 1000 #define STR vstring_str ! for (expand_to_self = 0, arg = 0; arg < argv->argc; arg++) { if (argv->argc > MAX_EXPANSION) { msg_warn("%s: unreasonable %s map expansion size for %s", cleanup_queue_id, maps->title, addr); break; } for (count = 0; /* void */ ; count++) { if (count >= MAX_RECURSION) { msg_warn("%s: unreasonable %s map nesting for %s", cleanup_queue_id, maps->title, addr); --- 91,107 ---- #define MAX_RECURSION 1000 #define MAX_EXPANSION 1000 #define STR vstring_str + #define RETURN(x) { been_here_free(been_here); return (x); } ! for (arg = 0; arg < argv->argc; arg++) { if (argv->argc > MAX_EXPANSION) { msg_warn("%s: unreasonable %s map expansion size for %s", cleanup_queue_id, maps->title, addr); break; } for (count = 0; /* void */ ; count++) { + if (been_here_fixed(been_here, argv->argv[arg]) != 0) + break; if (count >= MAX_RECURSION) { msg_warn("%s: unreasonable %s map nesting for %s", cleanup_queue_id, maps->title, addr); *************** *** 106,113 **** saved_lhs = mystrdup(argv->argv[arg]); for (i = 0; i < lookup->argc; i++) { unquote_822_local(cleanup_temp1, lookup->argv[i]); - if (strcasecmp(saved_lhs, STR(cleanup_temp1)) == 0) - expand_to_self = 1; if (i == 0) { UPDATE(argv->argv[arg], STR(cleanup_temp1)); } else { --- 111,116 ---- *************** *** 117,133 **** } myfree(saved_lhs); argv_free(lookup); - if (expand_to_self) - return (argv); } else if (dict_errno != 0) { msg_warn("%s: %s map lookup problem for %s", cleanup_queue_id, maps->title, addr); cleanup_errs |= CLEANUP_STAT_WRITE; ! return (argv); } else { break; } } } ! return (argv); } --- 120,134 ---- } myfree(saved_lhs); argv_free(lookup); } else if (dict_errno != 0) { msg_warn("%s: %s map lookup problem for %s", cleanup_queue_id, maps->title, addr); cleanup_errs |= CLEANUP_STAT_WRITE; ! RETURN(argv); } else { break; } } } ! RETURN(argv); } diff -cr --new-file ../postfix-19991231-pl09/global/quote_822_local.c ./global/quote_822_local.c *** ../postfix-19991231-pl09/global/quote_822_local.c Sat Dec 25 16:31:23 1999 --- ./global/quote_822_local.c Sun Oct 29 19:01:49 2000 *************** *** 80,86 **** */ if (local_part[0] == 0 || local_part[0] == '.') return (NO); ! for (cp = local_part; cp < end && (ch = *cp) != 0; cp++) { if (ch == '.' && (cp + 1) < end && cp[1] == '.') return (NO); #if 0 --- 80,86 ---- */ if (local_part[0] == 0 || local_part[0] == '.') return (NO); ! for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == '.' && (cp + 1) < end && cp[1] == '.') return (NO); #if 0 diff -cr --new-file ../postfix-19991231-pl09/html/faq.html ./html/faq.html *** ../postfix-19991231-pl09/html/faq.html Sat Jan 22 15:59:30 2000 --- ./html/faq.html Sun Oct 29 18:59:33 2000 *************** *** 2161,2190 ****

In order to build Postfix with db support on UNIX systems ! that do not have db support out of the box, you need the ! db-1.85 release, or the current ! version which has a db-1.85 compatible interface. ! !

! ! Use the following commands in the Postfix top-level directory. ! The LD_LIBRARY_PATH unset commands may be required to avoid linking ! in the wrong libraries. ! !

! !

!     % LD_LIBRARY_PATH=         (Bourne-shell syntax)
!     % unsetenv LD_LIBRARY_PATH (C-shell syntax)
!     % make tidy
!     % make makefiles CCARGS="-DHAS_DB -DPATH_DB_H='<db_185.h>' -I/some/where/include" AUXLIBS=/some/where/libdb.a
!     % make
! 
! !

! ! Of course you will have to specify the actual location of the ! include directory and of the object library.

--- 2161,2171 ----

In order to build Postfix with db support on UNIX systems ! that do not have db support out of the box, you can use the ! Berkeley DB source code from www.sleepycat.com. See the file ! DB_README in the Postfix source code distribution for ! instructions on how to build Postfix with Sleepycat's Berkeley DB.

diff -cr --new-file ../postfix-19991231-pl09/smtp/quote_821_local.c ./smtp/quote_821_local.c *** ../postfix-19991231-pl09/smtp/quote_821_local.c Sat Dec 25 16:31:41 1999 --- ./smtp/quote_821_local.c Sun Oct 29 19:01:19 2000 *************** *** 67,73 **** */ if (local_part[0] == 0 || local_part[0] == '.') return (NO); ! for (cp = local_part; cp < end && (ch = *cp) != 0; cp++) { if (ch == '.' && cp[1] == '.') return (NO); if (ch > 127) --- 67,73 ---- */ if (local_part[0] == 0 || local_part[0] == '.') return (NO); ! for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == '.' && cp[1] == '.') return (NO); if (ch > 127) diff -cr --new-file ../postfix-19991231-pl09/util/dict_db.c ./util/dict_db.c *** ../postfix-19991231-pl09/util/dict_db.c Sat Sep 16 19:58:09 2000 --- ./util/dict_db.c Mon Oct 30 09:33:27 2000 *************** *** 57,62 **** --- 57,90 ---- #endif #include #include + #include + + #if defined(_DB_185_H_) && defined(USE_FCNTL_LOCK) + #error "Error: this system must not use the db 1.85 compatibility interface" + #endif + + #ifndef DB_VERSION_MAJOR + #define DB_VERSION_MAJOR 1 + #define DICT_DB_GET(db, key, val, flag) db->get(db, key, val, flag) + #define DICT_DB_PUT(db, key, val, flag) db->put(db, key, val, flag) + #define DICT_DB_DEL(db, key, flag) db->del(db, key, flag) + #define DICT_DB_SYNC(db, flag) db->sync(db, flag) + #define DICT_DB_CLOSE(db) db->close(db) + #define DONT_CLOBBER R_NOOVERWRITE + #endif + + #if DB_VERSION_MAJOR > 1 + #define DICT_DB_GET(db, key, val, flag) sanitize(db->get(db, 0, key, val, flag)) + #define DICT_DB_PUT(db, key, val, flag) sanitize(db->put(db, 0, key, val, flag)) + #define DICT_DB_DEL(db, key, flag) sanitize(db->del(db, 0, key, flag)) + #define DICT_DB_SYNC(db, flag) ((errno = db->sync(db, flag)) ? -1 : 0) + #define DICT_DB_CLOSE(db) ((errno = db->close(db, 0)) ? -1 : 0) + #define DONT_CLOBBER DB_NOOVERWRITE + #endif + + #ifndef DB_FCNTL_LOCKING + #define DB_FCNTL_LOCKING 0 + #endif /* Utility library. */ *************** *** 78,84 **** } DICT_DB; #define DICT_DB_CACHE_SIZE (1024 * 1024) ! #define DICT_DB_NELM 4096 /* dict_db_lookup - find database entry */ --- 106,143 ---- } DICT_DB; #define DICT_DB_CACHE_SIZE (1024 * 1024) ! #define DICT_DB_NELM 4096 ! ! #if DB_VERSION_MAJOR > 1 ! ! /* sanitize - sanitize db_get/put/del result */ ! ! static int sanitize(int status) ! { ! ! /* ! * XXX This is unclean but avoids a lot of clutter elsewhere. Categorize ! * results into non-fatal errors (i.e., errors that we can deal with), ! * success, or fatal error (i.e., all other errors). ! */ ! switch (status) { ! ! case DB_NOTFOUND: /* get, del */ ! case DB_KEYEXIST: /* put */ ! return (1); /* non-fatal */ ! ! case 0: ! return (0); /* success */ ! ! case DB_KEYEMPTY: /* get, others? */ ! status = EINVAL; ! default: ! errno = status; ! return (-1); /* fatal */ ! } ! } ! ! #endif /* dict_db_lookup - find database entry */ *************** *** 93,98 **** --- 152,159 ---- const char *result = 0; dict_errno = 0; + memset(&db_key, 0, sizeof(db_key)); + memset(&db_value, 0, sizeof(db_value)); /* * Acquire a shared lock. *************** *** 107,113 **** if (dict->flags & DICT_FLAG_TRY1NULL) { db_key.data = (void *) name; db_key.size = strlen(name) + 1; ! if ((status = db->get(db, &db_key, &db_value, 0)) < 0) msg_fatal("error reading %s: %m", dict_db->path); if (status == 0) { dict->flags &= ~DICT_FLAG_TRY0NULL; --- 168,174 ---- if (dict->flags & DICT_FLAG_TRY1NULL) { db_key.data = (void *) name; db_key.size = strlen(name) + 1; ! if ((status = DICT_DB_GET(db, &db_key, &db_value, 0)) < 0) msg_fatal("error reading %s: %m", dict_db->path); if (status == 0) { dict->flags &= ~DICT_FLAG_TRY0NULL; *************** *** 122,128 **** if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) { db_key.data = (void *) name; db_key.size = strlen(name); ! if ((status = db->get(db, &db_key, &db_value, 0)) < 0) msg_fatal("error reading %s: %m", dict_db->path); if (status == 0) { if (buf == 0) --- 183,189 ---- if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) { db_key.data = (void *) name; db_key.size = strlen(name); ! if ((status = DICT_DB_GET(db, &db_key, &db_value, 0)) < 0) msg_fatal("error reading %s: %m", dict_db->path); if (status == 0) { if (buf == 0) *************** *** 152,157 **** --- 213,220 ---- DBT db_value; int status; + memset(&db_key, 0, sizeof(db_key)); + memset(&db_value, 0, sizeof(db_value)); db_key.data = (void *) name; db_value.data = (void *) value; db_key.size = strlen(name); *************** *** 187,194 **** /* * Do the update. */ ! if ((status = db->put(db, &db_key, &db_value, ! (dict->flags & DICT_FLAG_DUP_REPLACE) ? 0 : R_NOOVERWRITE)) < 0) msg_fatal("error writing %s: %m", dict_db->path); if (status) { if (dict->flags & DICT_FLAG_DUP_IGNORE) --- 250,257 ---- /* * Do the update. */ ! if ((status = DICT_DB_PUT(db, &db_key, &db_value, ! (dict->flags & DICT_FLAG_DUP_REPLACE) ? 0 : DONT_CLOBBER)) < 0) msg_fatal("error writing %s: %m", dict_db->path); if (status) { if (dict->flags & DICT_FLAG_DUP_IGNORE) *************** *** 198,203 **** --- 261,271 ---- else msg_fatal("%s: duplicate entry: \"%s\"", dict_db->path, name); } + #ifdef DICT_FLAG_SYNC_UPDATE + if (dict->flags & DICT_FLAG_SYNC_UPDATE) + if (DICT_DB_SYNC(db, 0) < 0) + msg_fatal("%s: flush dictionary: %m", dict_db->path); + #endif /* * Release the exclusive lock. *************** *** 229,235 **** if (dict->flags & DICT_FLAG_TRY1NULL) { db_key.data = (void *) name; db_key.size = strlen(name) + 1; ! if ((status = db->del(db, &db_key, flags)) < 0) msg_fatal("error deleting from %s: %m", dict_db->path); if (status == 0) dict->flags &= ~DICT_FLAG_TRY0NULL; --- 297,303 ---- if (dict->flags & DICT_FLAG_TRY1NULL) { db_key.data = (void *) name; db_key.size = strlen(name) + 1; ! if ((status = DICT_DB_DEL(db, &db_key, flags)) < 0) msg_fatal("error deleting from %s: %m", dict_db->path); if (status == 0) dict->flags &= ~DICT_FLAG_TRY0NULL; *************** *** 242,252 **** if (status > 0 && (dict->flags & DICT_FLAG_TRY0NULL)) { db_key.data = (void *) name; db_key.size = strlen(name); ! if ((status = db->del(db, &db_key, flags)) < 0) msg_fatal("error deleting from %s: %m", dict_db->path); if (status == 0) dict->flags &= ~DICT_FLAG_TRY1NULL; } /* * Release the exclusive lock. --- 310,325 ---- if (status > 0 && (dict->flags & DICT_FLAG_TRY0NULL)) { db_key.data = (void *) name; db_key.size = strlen(name); ! if ((status = DICT_DB_DEL(db, &db_key, flags)) < 0) msg_fatal("error deleting from %s: %m", dict_db->path); if (status == 0) dict->flags &= ~DICT_FLAG_TRY1NULL; } + #ifdef DICT_FLAG_SYNC_UPDATE + if (dict->flags & DICT_FLAG_SYNC_UPDATE) + if (DICT_DB_SYNC(db, 0) < 0) + msg_fatal("%s: flush dictionary: %m", dict_db->path); + #endif /* * Release the exclusive lock. *************** *** 262,267 **** --- 335,343 ---- static int dict_db_sequence(DICT *dict, const int function, const char **key, const char **value) { + #if DB_VERSION_MAJOR > 1 + msg_fatal("dict_db_sequence - operation is to be implemented"); + #else char *myname = "dict_db_sequence"; DICT_DB *dict_db = (DICT_DB *) dict; DB *db = dict_db->db; *************** *** 325,330 **** --- 401,407 ---- } } return status; + #endif } /* dict_db_close - close data base */ *************** *** 333,339 **** { DICT_DB *dict_db = (DICT_DB *) dict; ! if (dict_db->db->close(dict_db->db) < 0) msg_fatal("close database %s: %m", dict_db->path); myfree(dict_db->path); myfree((char *) dict_db); --- 410,418 ---- { DICT_DB *dict_db = (DICT_DB *) dict; ! if (DICT_DB_SYNC(dict_db->db, 0) < 0) ! msg_fatal("flush database %s: %m", dict_db->path); ! if (DICT_DB_CLOSE(dict_db->db) < 0) msg_fatal("close database %s: %m", dict_db->path); myfree(dict_db->path); myfree((char *) dict_db); *************** *** 349,354 **** --- 428,439 ---- DB *db; char *db_path; int lock_fd = -1; + int dbfd; + + #if DB_VERSION_MAJOR > 1 + int db_flags; + + #endif db_path = concatenate(path, ".db", (char *) 0); *************** *** 358,379 **** if (myflock(lock_fd, MYFLOCK_SHARED) < 0) msg_fatal("shared-lock database %s for open: %m", db_path); } if ((db = dbopen(db_path, open_flags, 0644, type, tweak)) == 0) msg_fatal("open database %s: %m", db_path); if (dict_flags & DICT_FLAG_LOCK) { if (myflock(lock_fd, MYFLOCK_NONE) < 0) msg_fatal("unlock database %s for open: %m", db_path); if (close(lock_fd) < 0) msg_fatal("close database %s: %m", db_path); } dict_db = (DICT_DB *) mymalloc(sizeof(*dict_db)); dict_db->dict.lookup = dict_db_lookup; dict_db->dict.update = dict_db_update; dict_db->dict.delete = dict_db_delete; dict_db->dict.sequence = dict_db_sequence; dict_db->dict.close = dict_db_close; ! dict_db->dict.fd = db->fd(db); if (fstat(dict_db->dict.fd, &st) < 0) msg_fatal("dict_db_open: fstat: %m"); dict_db->dict.mtime = st.st_mtime; --- 443,518 ---- if (myflock(lock_fd, MYFLOCK_SHARED) < 0) msg_fatal("shared-lock database %s for open: %m", db_path); } + + /* + * Use the DB 1.x programming interface. This is the default interface + * with 4.4BSD systems. It is also available via the db_185 compatibility + * interface, but that interface does not have the undocumented feature + * that we need to make file locking safe with POSIX fcntl() locking. + */ + #if DB_VERSION_MAJOR < 2 if ((db = dbopen(db_path, open_flags, 0644, type, tweak)) == 0) msg_fatal("open database %s: %m", db_path); + dbfd = db->fd(db); + #endif + + /* + * Use the DB 2.x programming interface. Jump a couple extra hoops. + */ + #if DB_VERSION_MAJOR == 2 + db_flags = DB_FCNTL_LOCKING; + if (open_flags == O_RDONLY) + db_flags |= DB_RDONLY; + if (open_flags & O_CREAT) + db_flags |= DB_CREATE; + if (open_flags & O_TRUNC) + db_flags |= DB_TRUNCATE; + if ((errno = db_open(db_path, type, db_flags, 0644, 0, tweak, &db)) != 0) + msg_fatal("open database %s: %m", db_path); + if (db == 0) + msg_panic("db_open null result"); + if ((errno = db->fd(db, &dbfd)) != 0) + msg_fatal("get database file descriptor: %m"); + #endif + /* + * Use the DB 3.x programming interface. Jump even more hoops. + */ + #if DB_VERSION_MAJOR > 2 + db_flags = DB_FCNTL_LOCKING; + if (open_flags == O_RDONLY) + db_flags |= DB_RDONLY; + if (open_flags & O_CREAT) + db_flags |= DB_CREATE; + if (open_flags & O_TRUNC) + db_flags |= DB_TRUNCATE; + if ((errno = db_create(&db, 0, 0)) != 0) + msg_fatal("create DB database: %m"); + if (db == 0) + msg_panic("db_create null result"); + if ((errno = db->set_cachesize(db, 0, DICT_DB_CACHE_SIZE, 0)) != 0) + msg_fatal("set DB cache size %d: %m", DICT_DB_CACHE_SIZE); + if (type == DB_HASH && db->set_h_nelem(db, DICT_DB_NELM) != 0) + msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM); + if ((errno = db->open(db, db_path, 0, type, db_flags, 0644)) != 0) + msg_fatal("open database %s: %m", db_path); + if ((errno = db->fd(db, &dbfd)) != 0) + msg_fatal("get database file descriptor: %m"); + #endif if (dict_flags & DICT_FLAG_LOCK) { if (myflock(lock_fd, MYFLOCK_NONE) < 0) msg_fatal("unlock database %s for open: %m", db_path); if (close(lock_fd) < 0) msg_fatal("close database %s: %m", db_path); } + dict_db = (DICT_DB *) mymalloc(sizeof(*dict_db)); dict_db->dict.lookup = dict_db_lookup; dict_db->dict.update = dict_db_update; dict_db->dict.delete = dict_db_delete; dict_db->dict.sequence = dict_db_sequence; dict_db->dict.close = dict_db_close; ! dict_db->dict.fd = dbfd; if (fstat(dict_db->dict.fd, &st) < 0) msg_fatal("dict_db_open: fstat: %m"); dict_db->dict.mtime = st.st_mtime; *************** *** 390,400 **** --- 529,553 ---- DICT *dict_hash_open(const char *path, int open_flags, int dict_flags) { + #if DB_VERSION_MAJOR < 2 HASHINFO tweak; memset((char *) &tweak, 0, sizeof(tweak)); tweak.nelem = DICT_DB_NELM; tweak.cachesize = DICT_DB_CACHE_SIZE; + #endif + #if DB_VERSION_MAJOR == 2 + DB_INFO tweak; + + memset((char *) &tweak, 0, sizeof(tweak)); + tweak.h_nelem = DICT_DB_NELM; + tweak.db_cachesize = DICT_DB_CACHE_SIZE; + #endif + #if DB_VERSION_MAJOR > 2 + void *tweak; + + tweak = 0; + #endif return (dict_db_open(path, open_flags, DB_HASH, (void *) &tweak, dict_flags)); } *************** *** 402,411 **** --- 555,577 ---- DICT *dict_btree_open(const char *path, int open_flags, int dict_flags) { + #if DB_VERSION_MAJOR < 2 BTREEINFO tweak; memset((char *) &tweak, 0, sizeof(tweak)); tweak.cachesize = DICT_DB_CACHE_SIZE; + #endif + #if DB_VERSION_MAJOR == 2 + DB_INFO tweak; + + memset((char *) &tweak, 0, sizeof(tweak)); + tweak.db_cachesize = DICT_DB_CACHE_SIZE; + #endif + #if DB_VERSION_MAJOR > 2 + void *tweak; + + tweak = 0; + #endif return (dict_db_open(path, open_flags, DB_BTREE, (void *) &tweak, dict_flags)); } diff -cr --new-file ../postfix-19991231-pl09/util/dict_open.c ./util/dict_open.c *** ../postfix-19991231-pl09/util/dict_open.c Tue Nov 16 16:30:51 1999 --- ./util/dict_open.c Tue Oct 24 13:11:00 2000 *************** *** 363,372 **** dict = dict_open(dict_name, open_flags, DICT_FLAG_LOCK); dict_register(dict_name, dict); while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) { ! if (dict_changed()) { ! msg_warn("dictionary has changed -- exiting"); ! exit(0); ! } if ((key = strtok(vstring_str(keybuf), " =")) == 0) continue; if ((value = strtok((char *) 0, " =")) == 0) { --- 363,370 ---- dict = dict_open(dict_name, open_flags, DICT_FLAG_LOCK); dict_register(dict_name, dict); while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) { ! if (dict_changed()) ! msg_warn("dictionary has changed"); if ((key = strtok(vstring_str(keybuf), " =")) == 0) continue; if ((value = strtok((char *) 0, " =")) == 0) {