From d69101f1a6fb4920fee5dedfa8b79a6eb5b56152 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Fri, 16 May 2014 00:00:00 -0500 Subject: [PATCH] postfix-2.12-20140516-nonprod --- postfix/.indent.pro | 6 +- postfix/HISTORY | 22 +- postfix/makedefs | 3 + postfix/src/fsstone/Makefile.in | 2 +- postfix/src/global/Makefile.in | 25 +- postfix/src/global/dynamicmaps.c | 292 +++++++++++++++++++++ postfix/src/{util => global}/dynamicmaps.h | 11 - postfix/src/global/mail_version.h | 2 +- postfix/src/global/mkmap.h | 9 +- postfix/src/global/mkmap_open.c | 123 ++++++--- postfix/src/pipe/pipe.c | 1 + postfix/src/smtpstone/Makefile.in | 8 +- postfix/src/util/Makefile.in | 10 +- postfix/src/util/dict.h | 8 +- postfix/src/util/dict_db.c | 5 +- postfix/src/util/dict_open.c | 87 ++++-- postfix/src/util/dynamicmaps.c | 248 ----------------- 17 files changed, 531 insertions(+), 331 deletions(-) create mode 100644 postfix/src/global/dynamicmaps.c rename postfix/src/{util => global}/dynamicmaps.h (68%) delete mode 100644 postfix/src/util/dynamicmaps.c diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 879fd42be..469ceb812 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -74,7 +74,6 @@ -TDICT_DB -TDICT_DBM -TDICT_DEBUG --TDICT_DL_INFO -TDICT_ENV -TDICT_FAIL -TDICT_HT @@ -86,6 +85,8 @@ -TDICT_NIS -TDICT_NISPLUS -TDICT_NODE +-TDICT_OPEN_EXTEND_FN +-TDICT_OPEN_FN -TDICT_OPEN_INFO -TDICT_OWNER -TDICT_PCRE @@ -124,6 +125,7 @@ -TDSN_FILTER -TDSN_SPLIT -TDSN_STAT +-TDYMAP_INFO -TEC_GROUP -TEC_KEY -TEDIT_FILE @@ -200,6 +202,8 @@ -TMKMAP -TMKMAP_DB -TMKMAP_DBM +-TMKMAP_OPEN_EXTEND_FN +-TMKMAP_OPEN_FN -TMKMAP_OPEN_INFO -TMKMAP_SDBM -TMSG_STATS diff --git a/postfix/HISTORY b/postfix/HISTORY index 6e997a50c..64f15530d 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -19721,7 +19721,7 @@ Apologies for any names omitted. poorly reflected their purpose. "DEAD" is replaced with "FORBIDDEN" (no I/O allowed) and "BAD" is replaced with "THROTTLED" (anything that causes the queue manager to back - off from some destination). Files: smtp.h, smtp_coonnect.c, + off from some destination). Files: smtp.h, smtp_connect.c, smtp_proto.c, smtp_trouble.c. Cleanup: enable SMTP connection cache lookup by destination @@ -19764,3 +19764,23 @@ Apologies for any names omitted. print/view README-format files are in the INSTALL file). Documentation: updated INSTALL instructions and RELEASE_NOTES. + +20140512 + + Portability: Berkeley DB6 support. File: util/dict_db.c. + +20140514 + + Cleanup: replace #ifdefs with hard-coded dynamicmaps calls + with an extension mechanism. Files: util/dict.h, util/dict_open.c, + global/dynamicmaps.[hc], global/mkmap.h, global/mkmap_open.c. + +20140515 + + Bugfix (introduced: 20140320): missing initialization. + Viktor Dukhovni. File pipe/pipe.c. + + Cleanup: mkmap_open() now caches a dynamically-loaded + function. This is useful because postmap/postalias may open + the same database type multiple times. Files: global/mkmap.h, + global/mkmap_open.c. diff --git a/postfix/makedefs b/postfix/makedefs index 24af0dd14..c1297fae3 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -683,6 +683,9 @@ queue_directory_macro=DEF_QUEUE_DIR sendmail_path_macro=DEF_SENDMAIL_PATH shlib_directory_macro=DEF_SHLIB_DIR +# shlib_directory is checked here because "no" is not a good answer. +# Instead, build with "shared=no". + for parm_name in command_directory config_directory daemon_directory \ data_directory mailq_path newaliases_path \ queue_directory sendmail_path shlib_directory diff --git a/postfix/src/fsstone/Makefile.in b/postfix/src/fsstone/Makefile.in index 2456448ef..564a3009a 100644 --- a/postfix/src/fsstone/Makefile.in +++ b/postfix/src/fsstone/Makefile.in @@ -21,7 +21,7 @@ Makefile: Makefile.in cat ../../conf/makedefs.out $? >$@ fsstone: fsstone.o $(LIBS) - $(CC) $(CFLAGS) -o $@ fsstone.o $(LIBS) $(SYSLIBS) + $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ fsstone.o $(LIBS) $(SYSLIBS) test: $(TESTPROG) diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 306b92b24..9b252c9a8 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -32,7 +32,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \ smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \ dict_memcache.c mail_version.c memcache_proto.c server_acl.c \ - mkmap_fail.c haproxy_srvr.c dsn_filter.c + mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c 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 \ @@ -66,7 +66,7 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \ smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \ dict_memcache.o mail_version.o memcache_proto.o server_acl.o \ - mkmap_fail.o haproxy_srvr.o dsn_filter.o + mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \ conv_time.h db_common.h debug_peer.h debug_process.h defer.h \ @@ -93,7 +93,7 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ fold_addr.h header_body_checks.h data_redirect.h match_service.h \ addr_match_list.h smtp_reply_footer.h safe_ultostr.h \ verify_sender_addr.h dict_memcache.h memcache_proto.h server_acl.h \ - haproxy_srvr.h dsn_filter.h + haproxy_srvr.h dsn_filter.h dynamicmaps.h TESTSRC = rec2stream.c stream2rec.c recdump.c DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) @@ -1054,6 +1054,21 @@ dsn_util.o: ../../include/vbuf.h dsn_util.o: ../../include/vstring.h dsn_util.o: dsn_util.c dsn_util.o: dsn_util.h +dynamicmaps.o: ../../include/argv.h +dynamicmaps.o: ../../include/dict.h +dynamicmaps.o: ../../include/load_lib.h +dynamicmaps.o: ../../include/msg.h +dynamicmaps.o: ../../include/mvect.h +dynamicmaps.o: ../../include/myflock.h +dynamicmaps.o: ../../include/mymalloc.h +dynamicmaps.o: ../../include/sys_defs.h +dynamicmaps.o: ../../include/vbuf.h +dynamicmaps.o: ../../include/vstream.h +dynamicmaps.o: ../../include/vstring.h +dynamicmaps.o: ../../include/vstring_vstream.h +dynamicmaps.o: dynamicmaps.c +dynamicmaps.o: dynamicmaps.h +dynamicmaps.o: mkmap.h ehlo_mask.o: ../../include/name_mask.h ehlo_mask.o: ../../include/sys_defs.h ehlo_mask.o: ../../include/vbuf.h @@ -1380,7 +1395,6 @@ mail_date.o: mail_date.c mail_date.o: mail_date.h mail_dict.o: ../../include/argv.h mail_dict.o: ../../include/dict.h -mail_dict.o: ../../include/dynamicmaps.h mail_dict.o: ../../include/msg.h mail_dict.o: ../../include/myflock.h mail_dict.o: ../../include/mymalloc.h @@ -1395,6 +1409,7 @@ mail_dict.o: dict_mysql.h mail_dict.o: dict_pgsql.h mail_dict.o: dict_proxy.h mail_dict.o: dict_sqlite.h +mail_dict.o: dynamicmaps.h mail_dict.o: mail_dict.c mail_dict.o: mail_dict.h mail_dict.o: mail_params.h @@ -1705,10 +1720,10 @@ mkmap_open.o: ../../include/dict.h mkmap_open.o: ../../include/dict_cdb.h mkmap_open.o: ../../include/dict_db.h mkmap_open.o: ../../include/dict_dbm.h -mkmap_open.o: ../../include/dynamicmaps.h mkmap_open.o: ../../include/dict_fail.h mkmap_open.o: ../../include/dict_lmdb.h mkmap_open.o: ../../include/dict_sdbm.h +mkmap_open.o: ../../include/htable.h mkmap_open.o: ../../include/msg.h mkmap_open.o: ../../include/myflock.h mkmap_open.o: ../../include/mymalloc.h diff --git a/postfix/src/global/dynamicmaps.c b/postfix/src/global/dynamicmaps.c new file mode 100644 index 000000000..b4e417604 --- /dev/null +++ b/postfix/src/global/dynamicmaps.c @@ -0,0 +1,292 @@ +/*++ +/* NAME +/* dynamicmaps 3 +/* SUMMARY +/* load dictionaries dynamically +/* SYNOPSIS +/* #include +/* +/* void dymap_init(const char *path) +/* +/* ARGV *dymap_list(ARGV *map_names) +/* DESCRIPTION +/* This module reads the dynamicmaps.cf file and performs +/* run-time loading of Postfix dictionaries. Each dynamicmaps.cf +/* entry specifies the name of a dictionary type, the pathname +/* of a shared-library object, the name of an "open" function +/* for access to individual dictionary entries, and optionally +/* the name of a "mkmap" function for bulk-mode dictionary +/* creation. +/* +/* dymap_init() must be called at least once before any other +/* functions in this module. This function reads the specified +/* configuration file which is in dynamicmaps.cf format, hooks +/* itself into the dict_open(), dict_mapames(), and mkmap_open() +/* functions, and may be called multiple times during a process +/* lifetime, but only the last-read dynamicmaps content will be +/* remembered. +/* +/* dymap_list() appends to its argument the names of dictionary +/* types available in dynamicmaps.cf. +/* SEE ALSO +/* load_lib(3) low-level run-time linker adapter +/* DIAGNOSTICS +/* Fatal errors: memory allocation problem, dictionary or +/* dictionary function not available. Panic: invalid use. +/* 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 library. + */ +#include +#include +#include + + /* + * Utility library. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + /* + * Global library. + */ +#include +#include + +#ifdef USE_DYNAMIC_LIBS + + /* + * Contents of one dynamicmaps.cf entry. + */ +typedef struct { + const char *dict_type; /* database type name */ + const char *soname; /* shared-object file name */ + const char *open_name; /* dict_xx_open() function name */ + const char *mkmap_name; /* mkmap_xx_open() function name */ +} DYMAP_INFO; + +static DYMAP_INFO *dymap_info; +static DICT_OPEN_EXTEND_FN saved_dict_open_hook = 0; +static MKMAP_OPEN_EXTEND_FN saved_mkmap_open_hook = 0; +static DICT_MAPNAMES_EXTEND_FN saved_dict_mapnames_hook = 0; + +#define STREQ(x, y) (strcmp((x), (y)) == 0) + +/* dymap_find - find dynamicmaps.cf metadata */ + +static DYMAP_INFO *dymap_find(const char *dict_type) +{ + static const char myname[] = "dymap_find"; + DYMAP_INFO *dp; + + if (!dymap_info) + msg_panic("%s: dlinfo==NULL", myname); + + for (dp = dymap_info; dp->dict_type; dp++) { + if (STREQ(dp->dict_type, dict_type)) + return dp; + } + return (0); +} + +/* dymap_open_lookup - look up "dict_foo_open" function */ + +static DICT_OPEN_FN dymap_open_lookup(const char *dict_type) +{ + struct stat st; + LIB_FN fn[2]; + DICT_OPEN_FN dict_open_fn; + DYMAP_INFO *dp; + + /* + * Respect the hook nesting order. + */ + if (saved_dict_open_hook != 0 + && (dict_open_fn = saved_dict_open_hook(dict_type)) != 0) + return (dict_open_fn); + + /* + * Allow for graceful degradation when a database is unavailable. This + * allows daemon processes to continue handling email with reduced + * functionality. + */ + if ((dp = dymap_find(dict_type)) == 0 + || stat(dp->soname, &st) < 0 + || dp->open_name == 0) + return (0); + if (st.st_uid != 0 || (st.st_mode & (S_IWGRP | S_IWOTH)) != 0) { + msg_warn("%s: file must be writable only by root", dp->soname); + return (0); + } + fn[0].name = dp->open_name; + fn[0].ptr = (void **) &dict_open_fn; + fn[1].name = NULL; + load_library_symbols(dp->soname, fn, NULL); + return (dict_open_fn); +} + +/* dymap_mkmap_lookup - look up "mkmap_foo_open" function */ + +static MKMAP_OPEN_FN dymap_mkmap_lookup(const char *dict_type) +{ + struct stat st; + LIB_FN fn[2]; + MKMAP_OPEN_FN mkmap_open_fn; + DYMAP_INFO *dp; + + /* + * Respect the hook nesting order. + */ + if (saved_mkmap_open_hook != 0 + && (mkmap_open_fn = saved_mkmap_open_hook(dict_type)) != 0) + return (mkmap_open_fn); + + /* + * All errors are fatal. If we can't create the requetsed database, then + * graceful degradation is not useful. + */ + dp = dymap_find(dict_type); + if (!dp) + msg_fatal("unsupported dictionary type: %s. " + "Is the postfix-%s package installed?", + dict_type, dict_type); + if (!dp->mkmap_name) + msg_fatal("unsupported dictionary type: %s does not support " + "bulk-mode creation.", dict_type); + if (stat(dp->soname, &st) < 0) + msg_fatal("unsupported dictionary type: %s (%s not found). " + "Is the postfix-%s package installed?", + dict_type, dp->soname, dict_type); + if (st.st_uid != 0 || (st.st_mode & (S_IWGRP | S_IWOTH)) != 0) + msg_fatal("%s: file must be writable only by root", dp->soname); + fn[0].name = dp->mkmap_name; + fn[0].ptr = (void **) &mkmap_open_fn; + fn[1].name = NULL; + load_library_symbols(dp->soname, fn, NULL); + return (mkmap_open_fn); +} + +/* dymap_list - enumerate dynamically-linked database type names */ + +static ARGV *dymap_list(ARGV *map_names) +{ + static const char myname[] = "dymap_list"; + DYMAP_INFO *dp; + + if (!dymap_info) + msg_panic("%s: dlinfo==NULL", myname); + + /* + * Respect the hook nesting order. + */ + if (saved_dict_mapnames_hook != 0) + map_names = saved_dict_mapnames_hook(map_names); + + if (map_names == 0) + map_names = argv_alloc(2); + for (dp = dymap_info; dp->dict_type; dp++) { + argv_add(map_names, dp->dict_type, ARGV_END); + } + return (map_names); +} + +/* dymap_init - initialize dictionary type to soname etc. mapping */ + +void dymap_init(const char *path) +{ + VSTREAM *conf_fp; + VSTRING *buf; + char *cp; + ARGV *argv; + static MVECT vector; + int nelm = 0; + int linenum = 0; + static int hooks_done = 0; + struct stat st; + + if (dymap_info != 0) + mvect_free(&vector); + + dymap_info = + (DYMAP_INFO *) mvect_alloc(&vector, sizeof(DYMAP_INFO), 3, 0, 0); + + /* Silently ignore missing dynamic maps file. */ + if ((conf_fp = vstream_fopen(path, O_RDONLY, 0)) != 0) { + if (fstat(vstream_fileno(conf_fp), &st) < 0) + msg_fatal("%s: fstat failed; %m", path); + if (st.st_uid != 0 || (st.st_mode & (S_IWGRP | S_IWOTH)) != 0) + msg_fatal("%s: file must be writable only by root", path); + buf = vstring_alloc(100); + 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 \"dict_type .so-name open-function" + " [mkmap-function]\" at line %d", path, linenum); + } + if (STREQ(argv->argv[0], "*")) { + msg_warn("%s: wildcard dynamic map entry no longer supported.", + path); + continue; + } + if (argv->argv[1][0] != '/') { + msg_fatal("%s: .so name must begin with a \"/\" at line %d", + path, linenum); + } + if (nelm >= vector.nelm) { + dymap_info = (DYMAP_INFO *) mvect_realloc(&vector, vector.nelm + 3); + } + dymap_info[nelm].dict_type = mystrdup(argv->argv[0]); + dymap_info[nelm].soname = mystrdup(argv->argv[1]); + dymap_info[nelm].open_name = mystrdup(argv->argv[2]); + if (argv->argc == 4) + dymap_info[nelm].mkmap_name = mystrdup(argv->argv[3]); + else + dymap_info[nelm].mkmap_name = NULL; + nelm++; + argv_free(argv); + if (hooks_done == 0) { + hooks_done = 1; + saved_dict_open_hook = dict_open_extend(dymap_open_lookup); + saved_mkmap_open_hook = mkmap_open_extend(dymap_mkmap_lookup); + saved_dict_mapnames_hook = dict_mapnames_extend(dymap_list); + } + } + vstring_free(buf); + vstream_fclose(conf_fp); + } + if (nelm >= vector.nelm) { + dymap_info = (DYMAP_INFO *) mvect_realloc(&vector, vector.nelm + 1); + } + dymap_info[nelm].dict_type = NULL; + dymap_info[nelm].soname = NULL; + dymap_info[nelm].open_name = NULL; + dymap_info[nelm].mkmap_name = NULL; +} + +#endif diff --git a/postfix/src/util/dynamicmaps.h b/postfix/src/global/dynamicmaps.h similarity index 68% rename from postfix/src/util/dynamicmaps.h rename to postfix/src/global/dynamicmaps.h index 5afca96b9..d1613d4fe 100644 --- a/postfix/src/util/dynamicmaps.h +++ b/postfix/src/global/dynamicmaps.h @@ -11,23 +11,12 @@ /* DESCRIPTION /* .nf - /* - * Utility library. - */ -#include - /* * External interface. */ #ifdef USE_DYNAMIC_LIBS -typedef DICT *(*dymap_open_t) (const char *, int, int); -typedef void *(*dymap_mkmap_t) (const char *); - extern void dymap_init(const char *); -extern ARGV *dymap_list(ARGV *); -extern dymap_open_t dymap_get_open_fn(const char *); -extern dymap_mkmap_t dymap_get_mkmap_fn(const char *); #endif /* LICENSE diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 73c31170a..1531aca66 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20140508" +#define MAIL_RELEASE_DATE "20140516" #define MAIL_VERSION_NUMBER "2.12" #ifdef SNAPSHOT diff --git a/postfix/src/global/mkmap.h b/postfix/src/global/mkmap.h index fa5f889b6..e49311474 100644 --- a/postfix/src/global/mkmap.h +++ b/postfix/src/global/mkmap.h @@ -23,11 +23,11 @@ * acquire the lock after the DB/DBM initialization. */ typedef struct MKMAP { - struct DICT *(*open) (const char *, int, int); /* dict_xx_open() */ + DICT_OPEN_FN open; /* dict_xx_open() */ struct DICT *dict; /* dict_xx_open() result */ void (*after_open) (struct MKMAP *); /* may be null */ void (*after_close) (struct MKMAP *); /* may be null */ - int multi_writer; /* multi-writer safe */ + int multi_writer; /* multi-writer safe */ } MKMAP; extern MKMAP *mkmap_open(const char *, const char *, int, int); @@ -45,6 +45,11 @@ extern MKMAP *mkmap_sdbm_open(const char *); extern MKMAP *mkmap_proxy_open(const char *); extern MKMAP *mkmap_fail_open(const char *); +typedef MKMAP *(*MKMAP_OPEN_FN) (const char *); +typedef MKMAP_OPEN_FN (*MKMAP_OPEN_EXTEND_FN) (const char *); +extern void mkmap_open_register(const char *, MKMAP_OPEN_FN); +extern MKMAP_OPEN_EXTEND_FN mkmap_open_extend(MKMAP_OPEN_EXTEND_FN); + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mkmap_open.c b/postfix/src/global/mkmap_open.c index 70c79836e..18eedfdb1 100644 --- a/postfix/src/global/mkmap_open.c +++ b/postfix/src/global/mkmap_open.c @@ -6,6 +6,14 @@ /* SYNOPSIS /* #include /* +/* typedef struct MKMAP { +/* DICT_OPEN_FN open; /* dict_xx_open() */ +/* DICT *dict; /* dict_xx_open() result */ +/* void (*after_open) (struct MKMAP *); /* may be null */ +/* void (*after_close) (struct MKMAP *); /* may be null */ +/* int multi_writer; /* multi-writer safe */ +/* } MKMAP; +/* /* MKMAP *mkmap_open(type, path, open_flags, dict_flags) /* char *type; /* char *path; @@ -20,6 +28,16 @@ /* /* void mkmap_close(mkmap) /* MKMAP *mkmap; +/* +/* typedef MKMAP *(*MKMAP_OPEN_FN) (const char *); +/* typedef MKMAP_OPEN_FN *(*MKMAP_OPEN_EXTEND_FN) (const char *); +/* +/* void mkmap_open_register(type, open_fn) +/* const char *type; +/* MKMAP_OPEN_FN open_fn; +/* +/* MKMAP_OPEN_EXTEND_FN mkmap_open_extend(call_back) +/* MKMAP_OPEN_EXTEND_FN call_back; /* DESCRIPTION /* This module implements support for creating Postfix databases. /* It is a dict(3) wrapper that adds global locking to dict-level @@ -29,8 +47,8 @@ /* appending the appropriate suffixes to the specified filename. /* Before the database is updated, it is locked for exclusive /* access, and signal delivery is suspended. -/* See dict(3) for a description of \fBopen_flags\fR and \fBdict_flags\fR. -/* All errors are fatal. +/* See dict(3) for a description of \fBopen_flags\fR and +/* \fBdict_flags\fR. All errors are fatal. /* /* mkmap_append() appends the named (key, value) pair to the /* database. Update errors are fatal; duplicate keys are ignored @@ -39,6 +57,15 @@ /* /* mkmap_close() closes the database, releases any locks, /* and resumes signal delivery. All errors are fatal. +/* +/* mkmap_open_register() adds support for a new database type. +/* +/* mkmap_open_extend() registers a call-back function that looks +/* up the mkmap open() function for a database type that is not +/* registered, or null in case of error. The result value is the +/* last previously-registered call-back or null. A mkmap open() +/* function is cached after it is looked up through this extension +/* mechanism. /* SEE ALSO /* sigdelay(3) suspend/resume signal delivery /* LICENSE @@ -61,6 +88,7 @@ /* Utility library. */ #include +#include #include #include #include @@ -72,27 +100,23 @@ #include #include -#ifdef USE_DYNAMIC_LIBS -#include -#endif - /* Global library. */ #include "mkmap.h" /* * Information about available database types. Here, we list only those map - * types that support "create" operations. + * types that support "bulk create" operations. * - * We use a different table (in dict_open.c) when querying maps. + * We use a different table (in dict_open.c and mail_dict.c) when querying maps + * or when making incremental updates. */ typedef struct { const char *type; - MKMAP *(*before_open) (const char *); + MKMAP_OPEN_FN before_open; } MKMAP_OPEN_INFO; -static const MKMAP_OPEN_INFO mkmap_types[] = { - DICT_TYPE_PROXY, mkmap_proxy_open, +static const MKMAP_OPEN_INFO mkmap_open_info[] = { #ifdef HAS_CDB DICT_TYPE_CDB, mkmap_cdb_open, #endif @@ -113,6 +137,54 @@ static const MKMAP_OPEN_INFO mkmap_types[] = { 0, }; +static HTABLE *mkmap_open_hash; + +static MKMAP_OPEN_EXTEND_FN mkmap_open_extend_hook = 0; + +/* mkmap_open_init - one-off initialization */ + +static void mkmap_open_init(void) +{ + const char myname[] = "mkmap_open_init"; + const MKMAP_OPEN_INFO *mp; + + if (mkmap_open_hash != 0) + msg_panic("%s: multiple initialization", myname); + mkmap_open_hash = htable_create(10); + + for (mp = mkmap_open_info; mp->type; mp++) + htable_enter(mkmap_open_hash, mp->type, (char *) mp); +} + +/* mkmap_open_register - register dictionary type */ + +void mkmap_open_register(const char *type, MKMAP_OPEN_FN open_fn) +{ + const char myname[] = "mkmap_open_register"; + MKMAP_OPEN_INFO *mp; + HTABLE_INFO *ht; + + if (mkmap_open_hash == 0) + mkmap_open_init(); + if (htable_find(mkmap_open_hash, type)) + msg_panic("%s: database type exists: %s", myname, type); + mp = (MKMAP_OPEN_INFO *) mymalloc(sizeof(*mp)); + mp->before_open = open_fn; + ht = htable_enter(mkmap_open_hash, type, (char *) mp); + mp->type = ht->key; +} + +/* mkmap_open_extend - register alternate lookup function */ + +MKMAP_OPEN_EXTEND_FN mkmap_open_extend(MKMAP_OPEN_EXTEND_FN new_cb) +{ + MKMAP_OPEN_EXTEND_FN old_cb; + + old_cb = mkmap_open_extend_hook; + mkmap_open_extend_hook = new_cb; + return (old_cb); +} + /* mkmap_append - append entry to map */ #undef mkmap_append @@ -164,30 +236,21 @@ MKMAP *mkmap_open(const char *type, const char *path, { MKMAP *mkmap; const MKMAP_OPEN_INFO *mp; - -#ifdef USE_DYNAMIC_LIBS - MKMAP_OPEN_INFO oi; - -#endif + MKMAP_OPEN_FN open_fn; /* * Find out what map type to use. */ - for (mp = mkmap_types; /* void */ ; mp++) { - if (mp->type == 0) { -#ifdef USE_DYNAMIC_LIBS - /* Either returns a handle, or raises a fatal error */ - oi.before_open = - (MKMAP *(*) (const char *)) dymap_get_mkmap_fn(type); - oi.type = type; - mp = &oi; - break; -#else - msg_fatal("unsupported map type for this operation: %s", type); -#endif + if (mkmap_open_hash == 0) + mkmap_open_init(); + if ((mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type)) == 0) { + if (mkmap_open_extend_hook != 0 && + (open_fn = mkmap_open_extend_hook(type)) != 0) { + mkmap_open_register(type, open_fn); + mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type); } - if (strcmp(type, mp->type) == 0) - break; + if (mp == 0) + msg_fatal("unsupported map type for this operation: %s", type); } if (msg_verbose) msg_info("open %s %s", type, path); diff --git a/postfix/src/pipe/pipe.c b/postfix/src/pipe/pipe.c index d63aca845..954fecfaf 100644 --- a/postfix/src/pipe/pipe.c +++ b/postfix/src/pipe/pipe.c @@ -1341,6 +1341,7 @@ int main(int argc, char **argv) single_server_main(argc, argv, pipe_service, MAIL_SERVER_TIME_TABLE, time_table, + MAIL_SERVER_STR_TABLE, str_table, MAIL_SERVER_PRE_INIT, pre_init, MAIL_SERVER_POST_INIT, drop_privileges, MAIL_SERVER_PRE_ACCEPT, pre_accept, diff --git a/postfix/src/smtpstone/Makefile.in b/postfix/src/smtpstone/Makefile.in index e589503c3..1dec35497 100644 --- a/postfix/src/smtpstone/Makefile.in +++ b/postfix/src/smtpstone/Makefile.in @@ -21,16 +21,16 @@ Makefile: Makefile.in cat ../../conf/makedefs.out $? >$@ smtp-sink: smtp-sink.o $(LIBS) - $(CC) $(CFLAGS) -o $@ smtp-sink.o $(LIBS) $(SYSLIBS) + $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ smtp-sink.o $(LIBS) $(SYSLIBS) smtp-source: smtp-source.o $(LIBS) - $(CC) $(CFLAGS) -o $@ smtp-source.o $(LIBS) $(SYSLIBS) + $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ smtp-source.o $(LIBS) $(SYSLIBS) qmqp-sink: qmqp-sink.o $(LIBS) - $(CC) $(CFLAGS) -o $@ qmqp-sink.o $(LIBS) $(SYSLIBS) + $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ qmqp-sink.o $(LIBS) $(SYSLIBS) qmqp-source: qmqp-source.o $(LIBS) - $(CC) $(CFLAGS) -o $@ qmqp-source.o $(LIBS) $(SYSLIBS) + $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ qmqp-source.o $(LIBS) $(SYSLIBS) test: $(TESTPROG) diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index b1e1e84d1..c50a450b4 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -21,7 +21,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ readlline.c ring.c safe_getenv.c safe_open.c \ sane_accept.c sane_connect.c sane_link.c sane_rename.c \ sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \ - load_lib.c dynamicmaps.c \ + load_lib.c \ sigdelay.c skipblanks.c sock_addr.c spawn_command.c split_at.c \ split_nameval.c stat_as.c strcasecmp.c stream_connect.c \ stream_listen.c stream_recv_fd.c stream_send_fd.c stream_trigger.c \ @@ -52,7 +52,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.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 dynamicmaps.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 \ @@ -91,7 +91,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ mymalloc.h myrand.h name_code.h name_mask.h netstring.h nvtable.h \ open_as.h open_lock.h percentm.h posix_signals.h readlline.h ring.h \ safe.h safe_open.h sane_accept.h sane_connect.h sane_fsops.h \ - load_lib.h dynamicmaps.h \ + load_lib.h \ sane_socketpair.h sane_time.h scan_dir.h set_eugid.h set_ugid.h \ sigdelay.h sock_addr.h spawn_command.h split_at.h stat_as.h \ stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \ @@ -1454,6 +1454,10 @@ load_file.o: sys_defs.h load_file.o: vbuf.h load_file.o: vstream.h load_file.o: warn_stat.h +load_lib.o: load_lib.c +load_lib.o: load_lib.h +load_lib.o: msg.h +load_lib.o: sys_defs.h lowercase.o: lowercase.c lowercase.o: stringops.h lowercase.o: sys_defs.h diff --git a/postfix/src/util/dict.h b/postfix/src/util/dict.h index a217603e6..c705eb668 100644 --- a/postfix/src/util/dict.h +++ b/postfix/src/util/dict.h @@ -165,6 +165,9 @@ extern DICT *dict_debug(DICT *); * Interface for dictionary types. */ extern ARGV *dict_mapnames(void); +typedef ARGV *(*DICT_MAPNAMES_EXTEND_FN) (ARGV *); +extern DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend(DICT_MAPNAMES_EXTEND_FN); + /* * High-level interface, with logical dictionary names. @@ -184,9 +187,12 @@ extern int dict_error(const char *); /* * Low-level interface, with physical dictionary handles. */ +typedef DICT *(*DICT_OPEN_FN) (const char *, int, int); +typedef DICT_OPEN_FN (*DICT_OPEN_EXTEND_FN) (const char *); 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)); +extern void dict_open_register(const char *, DICT_OPEN_FN); +extern DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN); #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/postfix/src/util/dict_db.c b/postfix/src/util/dict_db.c index 93ee48098..4a09939a5 100644 --- a/postfix/src/util/dict_db.c +++ b/postfix/src/util/dict_db.c @@ -89,7 +89,7 @@ #define DONT_CLOBBER DB_NOOVERWRITE #endif -#if (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6) +#if (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR <= 6) #define DICT_DB_CURSOR(db, curs) (db)->cursor((db), NULL, (curs)) #else #define DICT_DB_CURSOR(db, curs) (db)->cursor((db), NULL, (curs), 0) @@ -693,7 +693,8 @@ 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 DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0) +#if DB_VERSION_MAJOR == 6 || 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) FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags, "open database %s: %m", db_path)); diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c index 3dfff403c..cb9f4b75c 100644 --- a/postfix/src/util/dict_open.c +++ b/postfix/src/util/dict_open.c @@ -39,12 +39,24 @@ /* void dict_close(dict) /* DICT *dict; /* +/* typedef DICT *(*DICT_OPEN_FN) (const char *, int, int); +/* /* dict_open_register(type, open) -/* char *type; -/* DICT *(*open) (const char *, int, int); +/* const char *type; +/* DICT_OPEN_FN open; +/* +/* typedef DICT_OPEN_FN (*DICT_OPEN_EXTEND_FN)(const char *type); +/* +/* DICT_OPEN_EXTEND_FN dict_open_extend(call_back) +/* DICT_OPEN_EXTEND_FN call_back; /* /* ARGV *dict_mapnames() /* +/* typedef ARGV *(*DICT_MAPNAMES_EXTEND_FN)(ARGV *names); +/* +/* DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend(call_back) +/* DICT_MAPNAMES_EXTEND_FN call_back; +/* /* int dict_isjmp(dict) /* DICT *dict; /* @@ -190,9 +202,19 @@ /* /* dict_open_register() adds support for a new dictionary type. /* +/* dict_open_extend() registers a call-back function that looks +/* up the dictionary open() function for a type that is not +/* registered, or null in case of error. The result value is +/* the last previously-registered call-back or null. +/* /* dict_mapnames() returns a sorted list with the names of all available /* dictionary types. /* +/* dict_mapnames_extend() registers a call-back function that +/* enumerates additional dictionary type names. The result +/* will be sorted by dict_mapnames(). The result value +/* is the last previously-registered call-back or null. +/* /* dict_setjmp() saves processing context and makes that context /* available for use with dict_longjmp(). Normally, dict_setjmp() /* returns zero. A non-zero result means that dict_setjmp() @@ -280,14 +302,13 @@ #include #include #include -#include /* * lookup table for available map types. */ typedef struct { char *type; - struct DICT *(*open) (const char *, int, int); + DICT_OPEN_FN open; } DICT_OPEN_INFO; static const DICT_OPEN_INFO dict_open_info[] = { @@ -336,6 +357,12 @@ static const DICT_OPEN_INFO dict_open_info[] = { static HTABLE *dict_open_hash; + /* + * Extension hooks. + */ +static DICT_OPEN_EXTEND_FN dict_open_extend_hook; +static DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend_hook; + /* dict_open_init - one-off initialization */ static void dict_open_init(void) @@ -376,6 +403,7 @@ DICT *dict_open3(const char *dict_type, const char *dict_name, { const char *myname = "dict_open"; DICT_OPEN_INFO *dp; + DICT_OPEN_FN open_fn; DICT *dict; if (*dict_type == 0 || *dict_name == 0) @@ -384,18 +412,14 @@ DICT *dict_open3(const char *dict_type, const char *dict_name, if (dict_open_hash == 0) dict_open_init(); if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) { -#ifdef USE_DYNAMIC_LIBS - dymap_open_t open_fn; - - if ((open_fn = dymap_get_open_fn(dict_type)) == 0) + if (dict_open_extend_hook != 0 + && (open_fn = dict_open_extend_hook(dict_type)) != 0) { + dict_open_register(dict_type, open_fn); + dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type); + } + if (dp == 0) return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, "unsupported dictionary type: %s", dict_type)); - dict_open_register(dict_type, open_fn); - dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type); -#else - return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, - "unsupported dictionary type: %s", dict_type)); -#endif } if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0) return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, @@ -422,20 +446,31 @@ DICT *dict_open3(const char *dict_type, const char *dict_name, /* dict_open_register - register dictionary type */ -void dict_open_register(const char *type, - DICT *(*open) (const char *, int, int)) +void dict_open_register(const char *type, DICT_OPEN_FN open) { const char *myname = "dict_open_register"; DICT_OPEN_INFO *dp; + HTABLE_INFO *ht; if (dict_open_hash == 0) dict_open_init(); if (htable_find(dict_open_hash, type)) msg_panic("%s: dictionary type exists: %s", myname, type); dp = (DICT_OPEN_INFO *) mymalloc(sizeof(*dp)); - dp->type = mystrdup(type); dp->open = open; - htable_enter(dict_open_hash, dp->type, (char *) dp); + ht = htable_enter(dict_open_hash, type, (char *) dp); + dp->type = ht->key; +} + +/* dict_open_extend - register alternate dictionary search routine */ + +DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN new_cb) +{ + DICT_OPEN_EXTEND_FN old_cb; + + old_cb = dict_open_extend_hook; + dict_open_extend_hook = new_cb; + return (old_cb); } /* dict_sort_alpha_cpp - qsort() callback */ @@ -461,9 +496,8 @@ ARGV *dict_mapnames() dp = (DICT_OPEN_INFO *) ht[0]->value; argv_add(mapnames, dp->type, ARGV_END); } -#ifdef USE_DYNAMIC_LIBS - dymap_list(mapnames); -#endif + if (dict_mapnames_extend_hook != 0) + (void) dict_mapnames_extend_hook(mapnames); qsort((void *) mapnames->argv, mapnames->argc, sizeof(mapnames->argv[0]), dict_sort_alpha_cpp); myfree((char *) ht_info); @@ -471,6 +505,17 @@ ARGV *dict_mapnames() return mapnames; } +/* dict_mapnames_extend - register alternate dictionary type list routine */ + +DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend(DICT_MAPNAMES_EXTEND_FN new_cb) +{ + DICT_MAPNAMES_EXTEND_FN old_cb; + + old_cb = dict_mapnames_extend_hook; + dict_mapnames_extend_hook = new_cb; + return (old_cb); +} + #ifdef TEST /* diff --git a/postfix/src/util/dynamicmaps.c b/postfix/src/util/dynamicmaps.c deleted file mode 100644 index 5221b3c0a..000000000 --- a/postfix/src/util/dynamicmaps.c +++ /dev/null @@ -1,248 +0,0 @@ -/*++ -/* NAME -/* dynamicmaps 3 -/* SUMMARY -/* load dictionaries dynamically -/* SYNOPSIS -/* #include -/* -/* typedef void *(*dymap_mkmap_t) (const char *) -/* typedef DICT *(*dymap_open_t) (const char *, int, int) -/* -/* void dymap_init(const char *path) -/* -/* ARGV *dymap_list(ARGV *map_names) -/* -/* dymap_open_t dymap_get_open_fn(const char *dict_type) -/* -/* dymap_mkmap_t dymap_get_mkmap_fn(const char *dict_type) -/* DESCRIPTION -/* This module reads the dynamicmaps.cf file and performs -/* run-time loading of Postfix dictionaries. Each dynamicmaps.cf -/* entry specifies the name of a dictionary type, the pathname -/* of a shared-library object, the name of an "open" function -/* for access to individual dictionary entries, and optionally -/* the name of a "mkmap" function for bulk-mode dictionary -/* creation. -/* -/* dymap_init() must be called at least once before any other -/* functions in this module. This function reads the specified -/* configuration file which is in dynamicmaps.cf format, and -/* may be called multiple times during a process lifetime. -/* -/* dymap_list() appends to its argument the names of dictionary -/* types available in dynamicmaps.cf. -/* -/* dymap_get_open_fn() loads the specified dictionary and -/* returns a function pointer to its "open" function. -/* -/* dymap_get_mkmap_fn() loads the specified dictionary and -/* returns a function pointer to its "mkmap" function. -/* SEE ALSO -/* load_lib(3) low-level run-time linker adapter -/* DIAGNOSTICS -/* Fatal errors: memory allocation problem, dictionary or -/* dictionary function not available. Panic: invalid use. -/* 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 library. - */ -#include -#include -#include - - /* - * Utility library. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef USE_DYNAMIC_LIBS - - /* - * Contents of one dynamicmaps.cf entry. - */ -typedef struct { - const char *dict_type; - const char *soname; - const char *open_name; - const char *mkmap_name; -} DICT_DL_INFO; - -static DICT_DL_INFO *dict_dlinfo; - -#define STREQ(x, y) (strcmp((x), (y)) == 0) - -/* dymap_init - initialize dictionary type to soname etc. mapping */ - -void dymap_init(const char *path) -{ - VSTREAM *conf_fp; - VSTRING *buf; - char *cp; - ARGV *argv; - static MVECT vector; - int nelm = 0; - int linenum = 0; - - if (dict_dlinfo != 0) - mvect_free(&vector); - - dict_dlinfo = - (DICT_DL_INFO *) mvect_alloc(&vector, sizeof(DICT_DL_INFO), 3, 0, 0); - - /* Silently ignore missing dynamic maps file. */ - if ((conf_fp = vstream_fopen(path, O_RDONLY, 0)) != 0) { - buf = vstring_alloc(100); - 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 \"dict_type .so-name open-function" - " [mkmap-function]\" at line %d", path, linenum); - } - if (STREQ(argv->argv[0], "*")) { - msg_warn("%s: wildcard dynamic map entry no longer supported.", - path); - continue; - } - if (argv->argv[1][0] != '/') { - msg_fatal("%s: .so name must begin with a \"/\" at line %d", - path, linenum); - } - if (nelm >= vector.nelm) { - dict_dlinfo = (DICT_DL_INFO *) mvect_realloc(&vector, vector.nelm + 3); - } - dict_dlinfo[nelm].dict_type = mystrdup(argv->argv[0]); - dict_dlinfo[nelm].soname = mystrdup(argv->argv[1]); - dict_dlinfo[nelm].open_name = mystrdup(argv->argv[2]); - if (argv->argc == 4) - dict_dlinfo[nelm].mkmap_name = mystrdup(argv->argv[3]); - else - dict_dlinfo[nelm].mkmap_name = NULL; - nelm++; - argv_free(argv); - } - vstring_free(buf); - vstream_fclose(conf_fp); - } - if (nelm >= vector.nelm) { - dict_dlinfo = (DICT_DL_INFO *) mvect_realloc(&vector, vector.nelm + 1); - } - dict_dlinfo[nelm].dict_type = NULL; - dict_dlinfo[nelm].soname = NULL; - dict_dlinfo[nelm].open_name = NULL; - dict_dlinfo[nelm].mkmap_name = NULL; -} - -/* dymap_list - enumerate dynamically-linked database type names */ - -ARGV *dymap_list(ARGV *map_names) -{ - static const char myname[] = "dymap_list"; - DICT_DL_INFO *dl; - - if (!dict_dlinfo) - msg_panic("%s: dlinfo==NULL", myname); - if (map_names == 0) - map_names = argv_alloc(2); - for (dl = dict_dlinfo; dl->dict_type; dl++) { - argv_add(map_names, dl->dict_type, ARGV_END); - } - return (map_names); -} - -/* dymap_find - find dynamically-linked database metadata */ - -static DICT_DL_INFO *dymap_find(const char *dict_type) -{ - static const char myname[] = "dymap_find"; - DICT_DL_INFO *dp; - - if (!dict_dlinfo) - msg_panic("%s: dlinfo==NULL", myname); - - for (dp = dict_dlinfo; dp->dict_type; dp++) { - if (STREQ(dp->dict_type, dict_type)) - return dp; - } - return (0); -} - -/* dymap_get_open_fn - look up "dict_foo_open" function */ - -dymap_open_t dymap_get_open_fn(const char *dict_type) -{ - struct stat st; - LIB_FN fn[2]; - dymap_open_t open_fn; - DICT_DL_INFO *dl; - - if ((dl = dymap_find(dict_type)) == 0 - || stat(dl->soname, &st) < 0 - || dl->open_name == 0) - return (0); - fn[0].name = dl->open_name; - fn[0].ptr = (void **) &open_fn; - fn[1].name = NULL; - load_library_symbols(dl->soname, fn, NULL); - return (open_fn); -} - -/* dymap_get_mkmap_fn - look up "mkmap_foo_open" function */ - -dymap_mkmap_t dymap_get_mkmap_fn(const char *dict_type) -{ - struct stat st; - LIB_FN fn[2]; - dymap_mkmap_t mkmap_fn; - DICT_DL_INFO *dl; - - dl = dymap_find(dict_type); - if (!dl) - msg_fatal("unsupported dictionary type: %s. " - "Is the postfix-%s package installed?", - dict_type, dict_type); - if (stat(dl->soname, &st) < 0) { - msg_fatal("unsupported dictionary type: %s (%s not found). " - "Is the postfix-%s package installed?", - dict_type, dl->soname, dict_type); - } - if (!dl->mkmap_name) - msg_fatal("unsupported dictionary type: %s does not support " - "bulk-mode creation.", dict_type); - fn[0].name = dl->mkmap_name; - fn[0].ptr = (void **) &mkmap_fn; - fn[1].name = NULL; - load_library_symbols(dl->soname, fn, NULL); - return (mkmap_fn); -} - -#endif -- 2.47.3