diff --git a/conf/postfix-files b/conf/postfix-files index 90ef957..c4c522a 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..e14c6fe 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) @@ -31,12 +31,10 @@ tests: test dns_rr_to_pa_test dns_rr_to_sa_test dns_sa_to_rr_test \ 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 d8fb3db..0b26b6f 100644 --- a/src/global/Makefile.in +++ b/src/global/Makefile.in @@ -37,8 +37,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 \ @@ -112,10 +112,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 @@ -125,14 +129,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); \ @@ -577,7 +603,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 ae0ae98..f414c47 100644 --- a/src/global/mail_conf.c +++ b/src/global/mail_conf.c @@ -190,6 +190,12 @@ void mail_conf_suck(void) if (dict_load_file_xt(CONFIG_DICT, path) == 0) msg_fatal("open %s: %m", 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 6dbf6ee..ff0eee6 100644 --- a/src/global/mail_dict.c +++ b/src/global/mail_dict.c @@ -47,6 +47,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 @@ -59,6 +60,7 @@ static const DICT_OPEN_INFO dict_open_info[] = { #ifdef HAS_SQLITE DICT_TYPE_SQLITE, dict_sqlite_open, #endif +#endif /* NO_DYNAMIC_MAPS */ DICT_TYPE_MEMCACHE, dict_memcache_open, 0, }; diff --git a/src/global/mail_params.c b/src/global/mail_params.c index 0e098b3..dac095d 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; @@ -268,6 +270,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; @@ -279,6 +282,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 d939d44..b2e729e 100644 --- a/src/global/mkmap_open.c +++ b/src/global/mkmap_open.c @@ -82,7 +82,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; @@ -161,7 +161,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 f1a59f6..0eb5d2d 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_other.c b/src/postconf/postconf_other.c index 04f9404..1752450 100644 --- a/src/postconf/postconf_other.c +++ b/src/postconf/postconf_other.c @@ -55,6 +55,10 @@ #include +/* Global library. */ + +#include +#include /* Application-specific. */ #include @@ -65,7 +69,16 @@ void show_maps(void) { ARGV *maps_argv; int i; - +#ifndef NO_DYNAMIC_MAPS + char *path; + char *config_dir; + + if (var_config_dir == 0) + set_config_dir(); + 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++) vstream_printf("%s\n", maps_argv->argv[i]); diff --git a/src/postmap/postmap.c b/src/postmap/postmap.c index 8249d79..8833dc4 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. @@ -748,6 +750,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) @@ -768,6 +782,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; @@ -817,7 +832,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]); @@ -834,8 +849,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': @@ -861,8 +876,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': @@ -870,10 +885,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; @@ -944,6 +964,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 dc7a4bb..4454085 100644 --- a/src/util/Makefile.in +++ b/src/util/Makefile.in @@ -1,5 +1,6 @@ SHELL = /bin/sh SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ + load_lib.c \ attr_print64.c attr_print_plain.c attr_scan0.c attr_scan64.c \ attr_scan_plain.c auto_clnt.c base64_code.c basename.c binhash.c \ chroot_uid.c cidr_match.c clean_env.c close_on_exec.c concatenate.c \ @@ -36,13 +37,14 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ ip_match.c nbbio.c stream_pass_connect.c base32_code.c dict_test.c \ dict_fail.c msg_rate_delay.c dict_surrogate.c warn_stat.c OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ + load_lib.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 \ @@ -72,6 +74,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ ip_match.o nbbio.o stream_pass_connect.o base32_code.o dict_test.o \ dict_fail.o msg_rate_delay.o dict_surrogate.o warn_stat.o HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ + load_lib.h \ chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \ dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \ dict_ni.h dict_nis.h dict_nisplus.h dict_pcre.h dict_regexp.h \ @@ -98,6 +101,7 @@ 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 \ @@ -113,10 +117,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 @@ -125,15 +130,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); \ @@ -155,7 +164,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 f8e91a4..d7ae8fe 100644 --- a/src/util/dict.h +++ b/src/util/dict.h @@ -80,6 +80,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) #define DICT_FLAG_OPEN_LOCK (1<<16) /* open file with exclusive lock */ @@ -166,6 +167,11 @@ extern int dict_error(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)); +#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 93ee480..cf382e3 100644 --- a/src/util/dict_db.c +++ b/src/util/dict_db.c @@ -693,6 +693,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) FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags, diff --git a/src/util/dict_dbm.c b/src/util/dict_dbm.c index 37e1463..56fd3dc 100644 --- a/src/util/dict_dbm.c +++ b/src/util/dict_dbm.c @@ -417,6 +417,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 7b7c0c5..241c337 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. @@ -166,6 +168,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. @@ -213,6 +218,9 @@ #include #endif +#include +#include + /* Utility library. */ #include @@ -241,6 +249,27 @@ #include #include +#ifndef NO_DYNAMIC_MAPS +#include +#include +#include +#include +#include + + /* + * 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. */ @@ -256,7 +285,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 @@ -276,9 +307,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 @@ -338,9 +371,28 @@ 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) + if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) { +#ifdef NO_DYNAMIC_MAPS return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, "unsupported dictionary type: %s", 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) || (stat(dl->soname, &st) < 0)) + return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, + "unsupported dictionary type: %s: " + "Is the postfix-%s package installed?", + dict_type, 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 ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0) return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, "cannot open %s:%s: %m", dict_type, dict_name)); @@ -359,6 +411,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, @@ -392,6 +474,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(); @@ -400,6 +485,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); @@ -407,6 +499,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 +/* +/* 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 +#include +#include +#if defined(HAS_DLOPEN) +#include +#elif defined(HAS_SHL_LOAD) +#include +#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