aboutsummaryrefslogtreecommitdiffstats
path: root/main/postfix/0001-support-for-dynamic-maps.patch
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2011-03-11 15:49:23 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2011-03-11 16:13:27 +0000
commit2b5f5f568811f27a8734d0476b47aad6be7964e6 (patch)
tree4c4d124c2634f9ddb9270c0a3496613a5660b174 /main/postfix/0001-support-for-dynamic-maps.patch
parent38529ac18bb454d2daaf661b43edad4b75d5fdac (diff)
downloadaports-2b5f5f568811f27a8734d0476b47aad6be7964e6.tar.bz2
aports-2b5f5f568811f27a8734d0476b47aad6be7964e6.tar.xz
main/postfix: upgrade to 2.8.1 and forward port dynamic maps patch
Diffstat (limited to 'main/postfix/0001-support-for-dynamic-maps.patch')
-rw-r--r--main/postfix/0001-support-for-dynamic-maps.patch1107
1 files changed, 1107 insertions, 0 deletions
diff --git a/main/postfix/0001-support-for-dynamic-maps.patch b/main/postfix/0001-support-for-dynamic-maps.patch
new file mode 100644
index 0000000000..a15a62bf11
--- /dev/null
+++ b/main/postfix/0001-support-for-dynamic-maps.patch
@@ -0,0 +1,1107 @@
+From 7e51893c53eca9bb0e952941e5f50163131c21eb Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Fri, 11 Mar 2011 15:33:18 +0000
+Subject: [PATCH] support for dynamic maps
+
+forward ported
+---
+ conf/postfix-files | 11 +++
+ src/dns/Makefile.in | 5 +-
+ src/global/Makefile.in | 44 +++++++++--
+ src/global/mail_conf.c | 6 ++
+ src/global/mail_dict.c | 2 +
+ src/global/mail_params.c | 4 +
+ src/global/mkmap_open.c | 11 +++-
+ src/master/Makefile.in | 6 +-
+ src/milter/Makefile.in | 6 +-
+ src/postconf/postconf.c | 10 +++
+ src/postmap/postmap.c | 51 +++++++++++--
+ src/tls/Makefile.in | 6 +-
+ src/util/Makefile.in | 29 +++++---
+ src/util/dict.h | 6 ++
+ src/util/dict_db.c | 6 ++
+ src/util/dict_dbm.c | 4 +
+ src/util/dict_open.c | 183 +++++++++++++++++++++++++++++++++++++++++++++-
+ src/util/load_lib.c | 135 ++++++++++++++++++++++++++++++++++
+ src/util/load_lib.h | 41 ++++++++++
+ 19 files changed, 520 insertions(+), 46 deletions(-)
+ create mode 100644 src/util/load_lib.c
+ create mode 100644 src/util/load_lib.h
+
+diff --git a/conf/postfix-files b/conf/postfix-files
+index d3911d6..7a7b619 100644
+--- a/conf/postfix-files
++++ b/conf/postfix-files
+@@ -65,6 +65,11 @@ $queue_directory/saved:d:$mail_owner:-:700:ucr
+ $queue_directory/trace:d:$mail_owner:-:700:ucr
+ $daemon_directory/anvil:f:root:-:755
+ $daemon_directory/bounce:f:root:-:755
++$daemon_directory/dict_ldap.so:f:root:-:755
++$daemon_directory/dict_pcre.so:f:root:-:755
++$daemon_directory/dict_mysql.so:f:root:-:755
++$daemon_directory/dict_pgsql.so:f:root:-:755
++$daemon_directory/dict_sqlite.so:f:root:-:755
+ $daemon_directory/cleanup:f:root:-:755
+ $daemon_directory/discard:f:root:-:755
+ $daemon_directory/dnsblog:f:root:-:755
+@@ -97,6 +102,11 @@ $daemon_directory/tlsmgr:f:root:-:755
+ $daemon_directory/trivial-rewrite:f:root:-:755
+ $daemon_directory/verify:f:root:-:755
+ $daemon_directory/virtual:f:root:-:755
++/usr/lib/libpostfix-dns.so.1:f:root:-:755
++/usr/lib/libpostfix-global.so.1:f:root:-:755
++/usr/lib/libpostfix-tls.so.1:f:root:-:755
++/usr/lib/libpostfix-master.so.1:f:root:-:755
++/usr/lib/libpostfix-util.so.1:f:root:-:755
+ $daemon_directory/nqmgr:h:$daemon_directory/qmgr
+ $daemon_directory/lmtp:h:$daemon_directory/smtp
+ $command_directory/postalias:f:root:-:755
+@@ -120,6 +130,7 @@ $config_directory/access:f:root:-:644:p1
+ $config_directory/aliases:f:root:-:644:p1
+ $config_directory/bounce.cf.default:f:root:-:644:1
+ $config_directory/canonical:f:root:-:644:p1
++$config_directory/dynamicmaps.cf:f:root:-:644:p
+ $config_directory/cidr_table:f:root:-:644:o
+ $config_directory/generic:f:root:-:644:p1
+ $config_directory/generics:f:root:-:644:o
+diff --git a/src/dns/Makefile.in b/src/dns/Makefile.in
+index bbc5e98..b71082e 100644
+--- a/src/dns/Makefile.in
++++ b/src/dns/Makefile.in
+@@ -14,7 +14,7 @@ LIBS = ../../lib/libutil.a
+ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(LIB)
+
+@@ -32,11 +32,10 @@ root_tests:
+
+ $(LIB): $(OBJS)
+ $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-dns.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+diff --git a/src/global/Makefile.in b/src/global/Makefile.in
+index 1a35114..bc4b643 100644
+--- a/src/global/Makefile.in
++++ b/src/global/Makefile.in
+@@ -35,8 +35,8 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
+ canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
+ clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
+ defer.o deliver_completed.o deliver_flock.o deliver_pass.o \
+- deliver_request.o dict_ldap.o dict_mysql.o dict_pgsql.o \
+- dict_proxy.o dict_sqlite.o domain_list.o dot_lockfile.o dot_lockfile_as.o \
++ deliver_request.o \
++ dict_proxy.o domain_list.o dot_lockfile.o dot_lockfile_as.o \
+ dsb_scan.o dsn.o dsn_buf.o dsn_mask.o dsn_print.o dsn_util.o \
+ ehlo_mask.o ext_prop.o file_id.o flush_clnt.o header_opts.o \
+ header_token.o input_transp.o int_filt.o is_header.o log_adhoc.o \
+@@ -106,10 +106,14 @@ LIBS = ../../lib/libutil.a
+ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ MAKES =
++LDAPSO = dict_ldap.so
++MYSQLSO = dict_mysql.so
++PGSQLSO = dict_pgsql.so
++SQLITESO = dict_sqlite.so
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+-all: $(LIB)
++all: $(LIB) $(LDAPSO) $(MYSQLSO) $(PGSQLSO) $(SQLITESO)
+
+ $(OBJS): ../../conf/makedefs.out
+
+@@ -119,14 +123,36 @@ Makefile: Makefile.in
+ test: $(TESTPROG)
+
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-global.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
++
++$(LDAPSO): dict_ldap.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_ldap.so -o $@ $? -lldap -llber -L../../lib -lutil -L. -lglobal
++
++$(MYSQLSO): dict_mysql.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_mysql.so -o $@ $? -lmysqlclient -L. -lutil -lglobal
++
++$(PGSQLSO): dict_pgsql.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_pgsql.so -o $@ $? -lpq -L. -lutil -lglobal
++
++$(SQLITESO): dict_sqlite.o $(LIB) ../../lib/libglobal.a
++ $(CC) -shared -Wl,-soname,dict_sqlite.so -o $@ $? -lsqlite3 -L. -lutil -lglobal
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+-update: $(LIB_DIR)/$(LIB) $(HDRS)
++../../libexec/$(LDAPSO): $(LDAPSO)
++ cp $(LDAPSO) ../../libexec
++
++../../libexec/$(MYSQLSO): $(MYSQLSO)
++ cp $(MYSQLSO) ../../libexec
++
++../../libexec/$(PGSQLSO): $(PGSQLSO)
++ cp $(PGSQLSO) ../../libexec
++
++../../libexec/$(SQLITESO): $(SQLITESO)
++ cp $(SQLITESO) ../../libexec
++
++update: $(LIB_DIR)/$(LIB) ../../libexec/$(LDAPSO) ../../libexec/$(MYSQLSO) ../../libexec/$(PGSQLSO) ../../libexec/$(SQLITESO) $(HDRS)
+ -for i in $(HDRS); \
+ do \
+ cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \
+@@ -497,7 +523,7 @@ lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+ clean:
+- rm -f *.o $(LIB) *core $(TESTPROG) junk
++ rm -f *.o $(LIB) $(LDAPSO) $(MYSQLSO) $(PGSQLSO) $(SQLITESO) *core $(TESTPROG) junk
+ rm -rf printfck
+
+ tidy: clean
+diff --git a/src/global/mail_conf.c b/src/global/mail_conf.c
+index 1fc7847..2af757f 100644
+--- a/src/global/mail_conf.c
++++ b/src/global/mail_conf.c
+@@ -190,6 +190,12 @@ void mail_conf_suck(void)
+ path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
+ dict_load_file(CONFIG_DICT, path);
+ myfree(path);
++
++#ifndef NO_DYNAMIC_MAPS
++ path = concatenate(var_config_dir, "/", "dynamicmaps.cf", (char *) 0);
++ dict_open_dlinfo(path);
++ myfree(path);
++#endif
+ }
+
+ /* mail_conf_flush - discard configuration dictionary */
+diff --git a/src/global/mail_dict.c b/src/global/mail_dict.c
+index 337861d..663f90f 100644
+--- a/src/global/mail_dict.c
++++ b/src/global/mail_dict.c
+@@ -46,6 +46,7 @@ typedef struct {
+
+ static const DICT_OPEN_INFO dict_open_info[] = {
+ DICT_TYPE_PROXY, dict_proxy_open,
++#ifdef NO_DYNAMIC_MAPS
+ #ifdef HAS_LDAP
+ DICT_TYPE_LDAP, dict_ldap_open,
+ #endif
+@@ -58,6 +59,7 @@ static const DICT_OPEN_INFO dict_open_info[] = {
+ #ifdef HAS_SQLITE
+ DICT_TYPE_SQLITE, dict_sqlite_open,
+ #endif
++#endif /* NO_DYNAMIC_MAPS */
+ 0,
+ };
+
+diff --git a/src/global/mail_params.c b/src/global/mail_params.c
+index f5350a1..db33da1 100644
+--- a/src/global/mail_params.c
++++ b/src/global/mail_params.c
+@@ -79,6 +79,7 @@
+ /* char *var_export_environ;
+ /* char *var_debug_peer_list;
+ /* int var_debug_peer_level;
++/* int var_command_maxtime;
+ /* int var_in_flow_delay;
+ /* int var_fault_inj_code;
+ /* char *var_bounce_service;
+@@ -91,6 +92,7 @@
+ /* char *var_error_service;
+ /* char *var_flush_service;
+ /* char *var_verify_service;
++/* char *var_scache_service;
+ /* char *var_trace_service;
+ /* char *var_proxymap_service;
+ /* char *var_proxywrite_service;
+@@ -265,6 +267,7 @@ char *var_import_environ;
+ char *var_export_environ;
+ char *var_debug_peer_list;
+ int var_debug_peer_level;
++int var_command_maxtime;
+ int var_fault_inj_code;
+ char *var_bounce_service;
+ char *var_cleanup_service;
+@@ -276,6 +279,7 @@ char *var_showq_service;
+ char *var_error_service;
+ char *var_flush_service;
+ char *var_verify_service;
++char *var_scache_service;
+ char *var_trace_service;
+ char *var_proxymap_service;
+ char *var_proxywrite_service;
+diff --git a/src/global/mkmap_open.c b/src/global/mkmap_open.c
+index 69a0d57..eb8de71 100644
+--- a/src/global/mkmap_open.c
++++ b/src/global/mkmap_open.c
+@@ -81,7 +81,7 @@
+ * We use a different table (in dict_open.c) when querying maps.
+ */
+ typedef struct {
+- char *type;
++ const char *type;
+ MKMAP *(*before_open) (const char *);
+ } MKMAP_OPEN_INFO;
+
+@@ -156,7 +156,16 @@ MKMAP *mkmap_open(const char *type, const char *path,
+ */
+ for (mp = mkmap_types; /* void */ ; mp++) {
+ if (mp->type == 0)
++#ifndef NO_DYNAMIC_MAPS
++ {
++ static MKMAP_OPEN_INFO oi;
++ oi.before_open=(MKMAP*(*)(const char*))dict_mkmap_func(type);
++ oi.type=type;
++ mp=&oi;
++ }
++#else
+ msg_fatal("unsupported map type: %s", type);
++#endif
+ if (strcmp(type, mp->type) == 0)
+ break;
+ }
+diff --git a/src/master/Makefile.in b/src/master/Makefile.in
+index 53f65bd..6a562cf 100644
+--- a/src/master/Makefile.in
++++ b/src/master/Makefile.in
+@@ -20,7 +20,7 @@ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ BIN_DIR = ../../libexec
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(PROG) $(LIB)
+
+@@ -39,12 +39,10 @@ tests:
+ root_tests:
+
+ $(LIB): $(LIB_OBJ)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-master.so.1 -o $(LIB) $(LIB_OBJ) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)/$(LIB)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ $(BIN_DIR)/$(PROG): $(PROG)
+ cp $(PROG) $(BIN_DIR)
+diff --git a/src/milter/Makefile.in b/src/milter/Makefile.in
+index c28263a..c475629 100644
+--- a/src/milter/Makefile.in
++++ b/src/milter/Makefile.in
+@@ -14,7 +14,7 @@ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ MAKES =
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(LIB)
+
+@@ -30,12 +30,10 @@ tests:
+ root_tests:
+
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-milter.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+diff --git a/src/postconf/postconf.c b/src/postconf/postconf.c
+index 82d8be0..e12baa9 100644
+--- a/src/postconf/postconf.c
++++ b/src/postconf/postconf.c
+@@ -1013,6 +1013,16 @@ static void show_maps(void)
+ {
+ ARGV *maps_argv;
+ int i;
++#ifndef NO_DYNAMIC_MAPS
++ char *path;
++ char *config_dir;
++
++ var_config_dir = mystrdup((config_dir = safe_getenv(CONF_ENV_PATH)) != 0 ?
++ config_dir : DEF_CONFIG_DIR); /* XXX */
++ path = concatenate(var_config_dir, "/", "dynamicmaps.cf", (char *) 0);
++ dict_open_dlinfo(path);
++ myfree(path);
++#endif
+
+ maps_argv = dict_mapnames();
+ for (i = 0; i < maps_argv->argc; i++)
+diff --git a/src/postmap/postmap.c b/src/postmap/postmap.c
+index e956aed..0981c7e 100644
+--- a/src/postmap/postmap.c
++++ b/src/postmap/postmap.c
+@@ -5,7 +5,7 @@
+ /* Postfix lookup table management
+ /* SYNOPSIS
+ /* .fi
+-/* \fBpostmap\fR [\fB-Nbfhimnoprsvw\fR] [\fB-c \fIconfig_dir\fR]
++/* \fBpostmap\fR [\fB-Nbfhimnoprsuvw\fR] [\fB-c \fIconfig_dir\fR]
+ /* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
+ /* [\fIfile_type\fR:]\fIfile_name\fR ...
+ /* DESCRIPTION
+@@ -151,6 +151,8 @@
+ /* .sp
+ /* This feature is available in Postfix version 2.2 and later,
+ /* and is not available for all database types.
++/* .IP \fB-u\fR
++/* Upgrade the database to the current version.
+ /* .IP \fB-v\fR
+ /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
+ /* options make the software increasingly verbose.
+@@ -723,6 +725,18 @@ static void postmap_seq(const char *map_type, const char *map_name,
+ dict_close(dict);
+ }
+
++/* postmap_upgrade - upgrade a map */
++
++static int postmap_upgrade(const char *map_type, const char *map_name)
++{
++ DICT *dict;
++
++ dict = dict_open3(map_type, map_name, O_RDWR,
++ DICT_FLAG_LOCK|DICT_FLAG_UPGRADE);
++ dict_close(dict);
++ return (dict != 0);
++}
++
+ /* usage - explain */
+
+ static NORETURN usage(char *myname)
+@@ -743,6 +757,7 @@ int main(int argc, char **argv)
+ int postmap_flags = POSTMAP_FLAG_AS_OWNER | POSTMAP_FLAG_SAVE_PERM;
+ int open_flags = O_RDWR | O_CREAT | O_TRUNC;
+ int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_FIX;
++ int upgrade = 0;
+ char *query = 0;
+ char *delkey = 0;
+ int sequence = 0;
+@@ -787,7 +802,7 @@ int main(int argc, char **argv)
+ /*
+ * Parse JCL.
+ */
+- while ((ch = GETOPT(argc, argv, "Nbc:d:fhimnopq:rsvw")) > 0) {
++ while ((ch = GETOPT(argc, argv, "Nbc:d:fhimnopq:rsuvw")) > 0) {
+ switch (ch) {
+ default:
+ usage(argv[0]);
+@@ -804,8 +819,8 @@ int main(int argc, char **argv)
+ msg_fatal("out of memory");
+ break;
+ case 'd':
+- if (sequence || query || delkey)
+- msg_fatal("specify only one of -s -q or -d");
++ if (sequence || query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
+ delkey = optarg;
+ break;
+ case 'f':
+@@ -831,8 +846,8 @@ int main(int argc, char **argv)
+ postmap_flags &= ~POSTMAP_FLAG_SAVE_PERM;
+ break;
+ case 'q':
+- if (sequence || query || delkey)
+- msg_fatal("specify only one of -s -q or -d");
++ if (sequence || query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
+ query = optarg;
+ break;
+ case 'r':
+@@ -840,10 +855,15 @@ int main(int argc, char **argv)
+ dict_flags |= DICT_FLAG_DUP_REPLACE;
+ break;
+ case 's':
+- if (query || delkey)
+- msg_fatal("specify only one of -s or -q or -d");
++ if (query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
+ sequence = 1;
+ break;
++ case 'u':
++ if (sequence || query || delkey || upgrade)
++ msg_fatal("specify only one of -s -q -u or -d");
++ upgrade=1;
++ break;
+ case 'v':
+ msg_verbose++;
+ break;
+@@ -914,6 +934,21 @@ int main(int argc, char **argv)
+ exit(0);
+ }
+ exit(1);
++ } else if (upgrade) { /* Upgrade the map(s) */
++ int success = 1;
++ if (optind + 1 > argc)
++ usage(argv[0]);
++ while (optind < argc) {
++ if ((path_name = split_at(argv[optind], ':')) != 0) {
++ success &= postmap_upgrade(argv[optind], path_name);
++ } else {
++ success &= postmap_upgrade(var_db_type, path_name);
++ }
++ if (!success)
++ exit(1);
++ optind++;
++ }
++ exit(0);
+ } else { /* create/update map(s) */
+ if (optind + 1 > argc)
+ usage(argv[0]);
+diff --git a/src/tls/Makefile.in b/src/tls/Makefile.in
+index 1dbe154..b952aa4 100644
+--- a/src/tls/Makefile.in
++++ b/src/tls/Makefile.in
+@@ -24,7 +24,7 @@ LIB_DIR = ../../lib
+ INC_DIR = ../../include
+ MAKES =
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+ all: $(LIB)
+
+@@ -40,12 +40,10 @@ tests:
+ root_tests:
+
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-tls.so.1 -o $(LIB) $(OBJS) $(LIBS) $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+ update: $(LIB_DIR)/$(LIB) $(HDRS)
+ -for i in $(HDRS); \
+diff --git a/src/util/Makefile.in b/src/util/Makefile.in
+index 4455fbf..481ec42 100644
+--- a/src/util/Makefile.in
++++ b/src/util/Makefile.in
+@@ -33,21 +33,22 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
+ allascii.c load_file.c killme_after.c vstream_tweak.c \
+ unix_pass_listen.c unix_pass_trigger.c edit_file.c inet_windowsize.c \
+ unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
+- ip_match.c nbbio.c stream_pass_connect.c
++ ip_match.c nbbio.c stream_pass_connect.c load_lib.c
+ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
+ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
+ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
+ chroot_uid.o cidr_match.o clean_env.o close_on_exec.o concatenate.o \
+ ctable.o dict.o dict_alloc.o dict_cdb.o dict_cidr.o dict_db.o \
+ dict_dbm.o dict_debug.o dict_env.o dict_ht.o dict_ni.o dict_nis.o \
+- dict_nisplus.o dict_open.o dict_pcre.o dict_regexp.o dict_sdbm.o \
+- dict_static.o dict_tcp.o dict_unix.o dir_forest.o doze.o dummy_read.o \
++ dict_nisplus.o dict_open.o dict_regexp.o dict_sdbm.o \
++ dict_static.o dict_unix.o dir_forest.o doze.o dummy_read.o \
+ dummy_write.o duplex_pipe.o environ.o events.o exec_command.o \
+ fifo_listen.o fifo_trigger.o file_limit.o find_inet.o fsspace.o \
+ fullname.o get_domainname.o get_hostname.o hex_code.o hex_quote.o \
+ host_port.o htable.o inet_addr_host.o inet_addr_list.o \
+ inet_addr_local.o inet_connect.o inet_listen.o inet_proto.o \
+ inet_trigger.o line_wrap.o lowercase.o lstat_as.o mac_expand.o \
++ load_lib.o \
+ mac_parse.o make_dirs.o mask_addr.o match_list.o match_ops.o msg.o \
+ msg_output.o msg_syslog.o msg_vstream.o mvect.o myaddrinfo.o myflock.o \
+ mymalloc.o myrand.o mystrtok.o name_code.o name_mask.o netstring.o \
+@@ -89,13 +90,14 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
+ username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
+ vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
+ edit_file.h dict_cache.h dict_thash.h \
+- ip_match.h nbbio.h
++ ip_match.h nbbio.h load_lib.h
+ TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
+ stream_test.c dup2_pass_on_exec.c
+ DEFS = -I. -D$(SYSTYPE)
+ CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+ FILES = Makefile $(SRCS) $(HDRS)
+ INCL =
++PCRESO = dict_pcre.so
+ LIB = libutil.a
+ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
+ fifo_rdonly_bug fifo_rdwr_bug fifo_trigger fsspace fullname \
+@@ -111,10 +113,11 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
+
+ LIB_DIR = ../../lib
+ INC_DIR = ../../include
++LIBS = $(LIB_DIR)/$(LIB) $(PCRESO)
+
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
+
+-all: $(LIB)
++all: $(LIB) $(PCRESO)
+
+ $(OBJS): ../../conf/makedefs.out
+
+@@ -123,15 +126,19 @@ Makefile: Makefile.in
+
+ test: $(TESTPROG)
+
++$(PCRESO): dict_pcre.o libutil.a
++ $(CC) -shared -Wl,-soname,dict_pcre.so -o $@ $? -lpcre -L. -lutil
++
+ $(LIB): $(OBJS)
+- $(AR) $(ARFL) $(LIB) $?
+- $(RANLIB) $(LIB)
++ $(CC) -shared -Wl,-soname,libpostfix-util.so.1 -o $(LIB) $(OBJS) -ldl $(SYSLIBS)
+
+ $(LIB_DIR)/$(LIB): $(LIB)
+ cp $(LIB) $(LIB_DIR)
+- $(RANLIB) $(LIB_DIR)/$(LIB)
+
+-update: $(LIB_DIR)/$(LIB) $(HDRS)
++../../libexec/$(PCRESO): $(PCRESO)
++ cp $(PCRESO) ../../libexec
++
++update: $(LIBS) $(HDRS) ../../libexec/$(PCRESO)
+ -for i in $(HDRS); \
+ do \
+ cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \
+@@ -153,7 +160,7 @@ lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+ clean:
+- rm -f *.o $(LIB) *core $(TESTPROG) junk $(MAKES) *.tmp
++ rm -f *.o $(LIB) $(PCRESO) *core $(TESTPROG) junk $(MAKES) *.tmp
+ rm -rf printfck
+
+ tidy: clean
+diff --git a/src/util/dict.h b/src/util/dict.h
+index 9829d28..d7dc53c 100644
+--- a/src/util/dict.h
++++ b/src/util/dict.h
+@@ -66,6 +66,7 @@ extern DICT *dict_debug(DICT *);
+ #define DICT_FLAG_NO_UNAUTH (1<<13) /* disallow unauthenticated data */
+ #define DICT_FLAG_FOLD_FIX (1<<14) /* case-fold key with fixed-case map */
+ #define DICT_FLAG_FOLD_MUL (1<<15) /* case-fold key with multi-case map */
++#define DICT_FLAG_UPGRADE (1<<30) /* Upgrade the db */
+ #define DICT_FLAG_FOLD_ANY (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
+
+ /* IMPORTANT: Update the dict_mask[] table when the above changes */
+@@ -138,6 +139,11 @@ extern const char *dict_eval(const char *, const char *, int);
+ extern DICT *dict_open(const char *, int, int);
+ extern DICT *dict_open3(const char *, const char *, int, int);
+ extern void dict_open_register(const char *, DICT *(*) (const char *, int, int));
++#ifndef NO_DYNAMIC_MAPS
++extern void dict_open_dlinfo(const char *path);
++typedef void* (*dict_mkmap_func_t)(const char *);
++dict_mkmap_func_t dict_mkmap_func(const char *dict_type);
++#endif
+
+ #define dict_get(dp, key) ((const char *) (dp)->lookup((dp), (key)))
+ #define dict_put(dp, key, val) (dp)->update((dp), (key), (val))
+diff --git a/src/util/dict_db.c b/src/util/dict_db.c
+index c827b8d..e33fc24 100644
+--- a/src/util/dict_db.c
++++ b/src/util/dict_db.c
+@@ -676,6 +676,12 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
+ 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 (dict_flags & DICT_FLAG_UPGRADE) {
++ if (msg_verbose)
++ msg_info("upgrading database %s",db_path);
++ if ((errno = db->upgrade(db,db_path,0)) != 0)
++ msg_fatal("upgrade of database %s: %m",db_path);
++ }
+ #if DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0)
+ if ((errno = db->open(db, 0, db_path, 0, type, db_flags, 0644)) != 0)
+ msg_fatal("open database %s: %m", db_path);
+diff --git a/src/util/dict_dbm.c b/src/util/dict_dbm.c
+index 3603e44..1958556 100644
+--- a/src/util/dict_dbm.c
++++ b/src/util/dict_dbm.c
+@@ -409,6 +409,10 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
+ char *dbm_path;
+ int lock_fd;
+
++#ifdef HAVE_GDBM
++ msg_fatal("%s: gdbm maps use locking that is incompatible with postfix. Use a hash map instead.",
++ path);
++#endif
+ /*
+ * Note: DICT_FLAG_LOCK is used only by programs that do fine-grained (in
+ * the time domain) locking while accessing individual database records.
+diff --git a/src/util/dict_open.c b/src/util/dict_open.c
+index 9e1358f..19e40bf 100644
+--- a/src/util/dict_open.c
++++ b/src/util/dict_open.c
+@@ -44,6 +44,8 @@
+ /* DICT *(*open) (const char *, int, int);
+ /*
+ /* ARGV *dict_mapnames()
++/*
++/* void (*)() dict_mkmap_func(const char *dict_type)
+ /* DESCRIPTION
+ /* This module implements a low-level interface to multiple
+ /* physical dictionary types.
+@@ -161,6 +163,9 @@
+ /*
+ /* dict_mapnames() returns a sorted list with the names of all available
+ /* dictionary types.
++/*
++/* dict_mkmap_func() returns a pointer to the mkmap setup function
++/* for the given map type, as given in /etc/dynamicmaps.cf
+ /* DIAGNOSTICS
+ /* Fatal error: open error, unsupported dictionary type, attempt to
+ /* update non-writable dictionary.
+@@ -185,6 +190,9 @@
+ #include <strings.h>
+ #endif
+
++#include <sys/stat.h>
++#include <unistd.h>
++
+ /* Utility library. */
+
+ #include <argv.h>
+@@ -211,6 +219,27 @@
+ #include <split_at.h>
+ #include <htable.h>
+
++#ifndef NO_DYNAMIC_MAPS
++#include <load_lib.h>
++#include <vstring.h>
++#include <vstream.h>
++#include <vstring_vstream.h>
++#include <mvect.h>
++
++ /*
++ * Interface for dynamic map loading.
++ */
++typedef struct {
++ const char *pattern;
++ const char *soname;
++ const char *openfunc;
++ const char *mkmapfunc;
++} DLINFO;
++
++static DLINFO *dict_dlinfo;
++static DLINFO *dict_open_dlfind(const char *type);
++#endif
++
+ /*
+ * lookup table for available map types.
+ */
+@@ -226,7 +255,9 @@ static const DICT_OPEN_INFO dict_open_info[] = {
+ DICT_TYPE_ENVIRON, dict_env_open,
+ DICT_TYPE_HT, dict_ht_open,
+ DICT_TYPE_UNIX, dict_unix_open,
++#ifdef NO_DYNAMIC_MAPS
+ DICT_TYPE_TCP, dict_tcp_open,
++#endif
+ #ifdef HAS_SDBM
+ DICT_TYPE_SDBM, dict_sdbm_open,
+ #endif
+@@ -246,9 +277,11 @@ static const DICT_OPEN_INFO dict_open_info[] = {
+ #ifdef HAS_NETINFO
+ DICT_TYPE_NETINFO, dict_ni_open,
+ #endif
++#ifdef NO_DYNAMIC_MAPS
+ #ifdef HAS_PCRE
+ DICT_TYPE_PCRE, dict_pcre_open,
+ #endif
++#endif /* NO_DYNAMIC_MAPS */
+ #ifdef HAS_POSIX_REGEXP
+ DICT_TYPE_REGEXP, dict_regexp_open,
+ #endif
+@@ -307,8 +340,31 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
+ dict_type, dict_name);
+ if (dict_open_hash == 0)
+ dict_open_init();
+- if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0)
+- msg_fatal("unsupported dictionary type: %s", dict_type);
++ if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) {
++#ifdef NO_DYNAMIC_MAPS
++ msg_fatal("%s: unsupported dictionary type: %s", myname, dict_type);
++#else
++ struct stat st;
++ LIB_FN fn[2];
++ DICT *(*open) (const char *, int, int);
++ DLINFO *dl=dict_open_dlfind(dict_type);
++ if (!dl)
++ msg_fatal("%s: unsupported dictionary type: %s: Is the postfix-%s package installed?", myname, dict_type, dict_type);
++ if (stat(dl->soname,&st) < 0) {
++ msg_fatal("%s: unsupported dictionary type: %s (%s not found. Is the postfix-%s package installed?)",
++ myname, dict_type, dl->soname, dict_type);
++ }
++ fn[0].name = dl->openfunc;
++ fn[0].ptr = (void**)&open;
++ fn[1].name = NULL;
++ load_library_symbols(dl->soname, fn, NULL);
++ dict_open_register(dict_type, open);
++ dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type);
++#endif
++ }
++ if (msg_verbose>1) {
++ msg_info("%s: calling %s open routine",myname,dict_type);
++ }
+ if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
+ msg_fatal("opening %s:%s %m", dict_type, dict_name);
+ if (msg_verbose)
+@@ -316,6 +372,36 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
+ return (dict);
+ }
+
++dict_mkmap_func_t dict_mkmap_func(const char *dict_type)
++{
++ char *myname="dict_mkmap_func";
++ struct stat st;
++ LIB_FN fn[2];
++ dict_mkmap_func_t mkmap;
++ DLINFO *dl;
++#ifndef NO_DYNAMIC_MAPS
++ if (!dict_dlinfo)
++ msg_fatal("dlinfo==NULL");
++ dl=dict_open_dlfind(dict_type);
++ if (!dl)
++ msg_fatal("%s: unsupported dictionary type: %s: Is the postfix-%s package installed?", myname, dict_type, dict_type);
++ if (stat(dl->soname,&st) < 0) {
++ msg_fatal("%s: unsupported dictionary type: %s (%s not found. Is the postfix-%s package installed?)",
++ myname, dict_type, dl->soname, dict_type);
++ }
++ if (!dl->mkmapfunc)
++ msg_fatal("%s: unsupported dictionary type: %s does not allow map creation.", myname, dict_type);
++
++ fn[0].name = dl->mkmapfunc;
++ fn[0].ptr = (void**)&mkmap;
++ fn[1].name = NULL;
++ load_library_symbols(dl->soname, fn, NULL);
++ return mkmap;
++#else
++ return (void(*)())NULL;
++#endif
++}
++
+ /* dict_open_register - register dictionary type */
+
+ void dict_open_register(const char *type,
+@@ -349,6 +435,9 @@ ARGV *dict_mapnames()
+ HTABLE_INFO **ht;
+ DICT_OPEN_INFO *dp;
+ ARGV *mapnames;
++#ifndef NO_DYNAMIC_MAPS
++ DLINFO *dlp;
++#endif
+
+ if (dict_open_hash == 0)
+ dict_open_init();
+@@ -357,6 +446,13 @@ ARGV *dict_mapnames()
+ dp = (DICT_OPEN_INFO *) ht[0]->value;
+ argv_add(mapnames, dp->type, ARGV_END);
+ }
++#ifndef NO_DYNAMIC_MAPS
++ if (!dict_dlinfo)
++ msg_fatal("dlinfo==NULL");
++ for (dlp=dict_dlinfo; dlp->pattern; dlp++) {
++ argv_add(mapnames, dlp->pattern, ARGV_END);
++ }
++#endif
+ qsort((void *) mapnames->argv, mapnames->argc, sizeof(mapnames->argv[0]),
+ dict_sort_alpha_cpp);
+ myfree((char *) ht_info);
+@@ -364,6 +460,89 @@ ARGV *dict_mapnames()
+ return mapnames;
+ }
+
++#ifndef NO_DYNAMIC_MAPS
++#define STREQ(x,y) (x == y || (x[0] == y[0] && strcmp(x,y) == 0))
++
++void dict_open_dlinfo(const char *path)
++{
++ char *myname="dict_open_dlinfo";
++ VSTREAM *conf_fp=vstream_fopen(path,O_RDONLY,0);
++ VSTRING *buf = vstring_alloc(100);
++ char *cp;
++ ARGV *argv;
++ MVECT vector;
++ int nelm=0;
++ int linenum=0;
++
++ dict_dlinfo=(DLINFO*)mvect_alloc(&vector,sizeof(DLINFO),3,NULL,NULL);
++
++ if (!conf_fp) {
++ msg_warn("%s: cannot open %s. No dynamic maps will be allowed.",
++ myname, path);
++ } else {
++ while (vstring_get_nonl(buf,conf_fp) != VSTREAM_EOF) {
++ cp = vstring_str(buf);
++ linenum++;
++ if (*cp == '#' || *cp == '\0')
++ continue;
++ argv = argv_split(cp, " \t");
++ if (argv->argc != 3 && argv->argc != 4) {
++ msg_fatal("%s: Expected \"pattern .so-name open-function [mkmap-function]\" at line %d",
++ myname, linenum);
++ }
++ if (STREQ(argv->argv[0],"*")) {
++ msg_warn("%s: wildcard dynamic map entry no longer supported.",
++ myname);
++ continue;
++ }
++ if (argv->argv[1][0] != '/') {
++ msg_fatal("%s: .so name must begin with a \"/\" at line %d",
++ myname, linenum);
++ }
++ if (nelm >= vector.nelm) {
++ dict_dlinfo=(DLINFO*)mvect_realloc(&vector,vector.nelm+3);
++ }
++ dict_dlinfo[nelm].pattern = mystrdup(argv->argv[0]);
++ dict_dlinfo[nelm].soname = mystrdup(argv->argv[1]);
++ dict_dlinfo[nelm].openfunc = mystrdup(argv->argv[2]);
++ if (argv->argc==4)
++ dict_dlinfo[nelm].mkmapfunc = mystrdup(argv->argv[3]);
++ else
++ dict_dlinfo[nelm].mkmapfunc = NULL;
++ nelm++;
++ argv_free(argv);
++ }
++ }
++ if (nelm >= vector.nelm) {
++ dict_dlinfo=(DLINFO*)mvect_realloc(&vector,vector.nelm+1);
++ }
++ dict_dlinfo[nelm].pattern = NULL;
++ dict_dlinfo[nelm].soname = NULL;
++ dict_dlinfo[nelm].openfunc = NULL;
++ dict_dlinfo[nelm].mkmapfunc = NULL;
++ if (conf_fp)
++ vstream_fclose(conf_fp);
++ vstring_free(buf);
++}
++
++static DLINFO *dict_open_dlfind(const char *type)
++{
++ DLINFO *dp;
++
++ if (!dict_dlinfo)
++ return NULL;
++
++ for (dp=dict_dlinfo; dp->pattern; dp++) {
++ if (STREQ(dp->pattern,type))
++ return dp;
++ }
++ return NULL;
++}
++
++#endif /* !NO_DYNAMIC_MAPS */
++
++
++
+ #ifdef TEST
+
+ /*
+diff --git a/src/util/load_lib.c b/src/util/load_lib.c
+new file mode 100644
+index 0000000..b6526ef
+--- /dev/null
++++ b/src/util/load_lib.c
+@@ -0,0 +1,135 @@
++/*++
++/* NAME
++/* load_lib 3
++/* SUMMARY
++/* library loading wrappers
++/* SYNOPSIS
++/* #include <load_lib.h>
++/*
++/* extern int load_library_symbols(const char *, LIB_FN *, LIB_FN *);
++/* const char *libname;
++/* LIB_FN *libfuncs;
++/* LIB_FN *libdata;
++/*
++/* DESCRIPTION
++/* This module loads functions from libraries, returnine pointers
++/* to the named functions.
++/*
++/* load_library_symbols() loads all of the desired functions, and
++/* returns zero for success, or exits via msg_fatal().
++/*
++/* SEE ALSO
++/* msg(3) diagnostics interface
++/* DIAGNOSTICS
++/* Problems are reported via the msg(3) diagnostics routines:
++/* library not found, symbols not found, other fatal errors.
++/* LICENSE
++/* .ad
++/* .fi
++/* The Secure Mailer license must be distributed with this software.
++/* AUTHOR(S)
++/* LaMont Jones
++/* Hewlett-Packard Company
++/* 3404 Harmony Road
++/* Fort Collins, CO 80528, USA
++/*
++/* Wietse Venema
++/* IBM T.J. Watson Research
++/* P.O. Box 704
++/* Yorktown Heights, NY 10598, USA
++/*--*/
++
++/* System libraries. */
++
++#include "sys_defs.h"
++#include <stdlib.h>
++#include <stddef.h>
++#include <string.h>
++#if defined(HAS_DLOPEN)
++#include <dlfcn.h>
++#elif defined(HAS_SHL_LOAD)
++#include <dl.h>
++#endif
++
++/* Application-specific. */
++
++#include "msg.h"
++#include "load_lib.h"
++
++extern int load_library_symbols(const char * libname, LIB_FN * libfuncs, LIB_FN * libdata)
++{
++ char *myname = "load_library_symbols";
++ LIB_FN *fn;
++
++#if defined(HAS_DLOPEN)
++ void *handle;
++ char *emsg;
++
++ handle=dlopen(libname,RTLD_NOW);
++ emsg=dlerror();
++ if (emsg) {
++ msg_fatal("%s: dlopen failure loading %s: %s", myname, libname, emsg);
++ }
++
++ if (libfuncs) {
++ for (fn=libfuncs; fn->name; fn++) {
++ *(fn->ptr) = dlsym(handle,fn->name);
++ emsg=dlerror();
++ if (emsg) {
++ msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
++ fn->name, libname, emsg);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %lx",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++
++ if (libdata) {
++ for (fn=libdata; fn->name; fn++) {
++ *(fn->ptr) = dlsym(handle,fn->name);
++ emsg=dlerror();
++ if (emsg) {
++ msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
++ fn->name, libname, emsg);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %lx",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++#elif defined(HAS_SHL_LOAD)
++ shl_t handle;
++
++ handle = shl_load(libname,BIND_IMMEDIATE,0);
++
++ if (libfuncs) {
++ for (fn=libfuncs; fn->name; fn++) {
++ if (shl_findsym(&handle,fn->name,TYPE_PROCEDURE,fn->ptr) != 0) {
++ msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
++ myname, fn->name, libname);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %x",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++
++ if (libdata) {
++ for (fn=libdata; fn->name; fn++) {
++ if (shl_findsym(&handle,fn->name,TYPE_DATA,fn->ptr) != 0) {
++ msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
++ myname, fn->name, libname);
++ }
++ if (msg_verbose>1) {
++ msg_info("loaded %s = %x",fn->name, *((long*)(fn->ptr)));
++ }
++ }
++ }
++
++#else
++ msg_fatal("%s: need dlopen or shl_load support for dynamic libraries",
++ myname);
++#endif
++ return 0;
++}
+diff --git a/src/util/load_lib.h b/src/util/load_lib.h
+new file mode 100644
+index 0000000..adebd25
+--- /dev/null
++++ b/src/util/load_lib.h
+@@ -0,0 +1,41 @@
++#ifndef _LOAD_LIB_H_INCLUDED_
++#define _LOAD_LIB_H_INCLUDED_
++
++/*++
++/* NAME
++/* load_lib 3h
++/* SUMMARY
++/* library loading wrappers
++/* SYNOPSIS
++/* #include "load_lib.h"
++/* DESCRIPTION
++/* .nf
++
++ /*
++ * External interface.
++ */
++/* NULL name terminates list */
++typedef struct LIB_FN {
++ const char *name;
++ void **ptr;
++} LIB_FN;
++
++extern int load_library_symbols(const char *, LIB_FN *, LIB_FN *);
++
++/* LICENSE
++/* .ad
++/* .fi
++/* The Secure Mailer license must be distributed with this software.
++/* AUTHOR(S)
++/* LaMont Jones
++/* Hewlett-Packard Company
++/* 3404 Harmony Road
++/* Fort Collins, CO 80528, USA
++/*
++/* Wietse Venema
++/* IBM T.J. Watson Research
++/* P.O. Box 704
++/* Yorktown Heights, NY 10598, USA
++/*--*/
++
++#endif
+--
+1.7.4.1
+