2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 21:55:20 +00:00

snapshot-19990329

This commit is contained in:
Wietse Venema
1999-03-29 00:00:00 -05:00
parent 9f9836bab2
commit 089fe6b742
30 changed files with 364 additions and 141 deletions

View File

@@ -2458,11 +2458,41 @@ Apologies for any names omitted.
Cleanup: the dictionary routines now take an extra flag Cleanup: the dictionary routines now take an extra flag
argument to control such things as warning about duplicates, argument to control such things as warning about duplicates,
and appending null bytes to key/value. This was needed for and appending null bytes to key/value. The latter was needed
a clean implementation of NIS master alias maps support. for a clean implementation of NIS master alias maps support.
Feature: POSIX regular expressions by Lamont Jones. Feature: POSIX regular expressions by Lamont Jones.
19990328
Code cleanup: dictionaries now have flags that say whether
lookup keys are fixed strings or whether keys are subjected
to pattern matching. This is needed to avoid passing partial
addresses to regexp-based lookup tables (user, @domain,
user@, domain). Files: util/dict*.c.
Bugfix: fixed memory leaks and core dumps in the regexp
and pcre routines (neither handled an empty pattern file).
19990329
Code cleanup: the dictionary I/O routines now do their own
locking depending on dictionary flag settings. This means
that the low-level dict_get() interface can now be used
for safe dictionary lookups. This is needed for 19990328's
partial lookup key support. Files: util/dict*.c. global/maps.c.
Feature: regular expression matches are no longer limited
to user@domain address forms in access/canonical/virtual
maps, but can also be used for domains in transport maps.
This needed the partial lookup key support to avoid passing
partial addresses to regexp-based lookup tables (user,
@domain, user@, domain). Files: global/maps.c
globl/mail_addr_find.c.
Feature: new dictionary types can be registered with
dict_open_register(). File: util/dict_open.c.
Future: Future:
Planned: must be able to list the same hash table in Planned: must be able to list the same hash table in

View File

@@ -81,6 +81,7 @@ cleanup.o: ../include/mail_server.h
cleanup.o: cleanup.h cleanup.o: cleanup.h
cleanup.o: ../include/argv.h cleanup.o: ../include/argv.h
cleanup.o: ../include/maps.h cleanup.o: ../include/maps.h
cleanup.o: ../include/dict.h
cleanup.o: ../include/tok822.h cleanup.o: ../include/tok822.h
cleanup.o: ../include/resolve_clnt.h cleanup.o: ../include/resolve_clnt.h
cleanup.o: ../include/been_here.h cleanup.o: ../include/been_here.h
@@ -100,6 +101,7 @@ cleanup_envelope.o: ../include/mail_params.h
cleanup_envelope.o: cleanup.h cleanup_envelope.o: cleanup.h
cleanup_envelope.o: ../include/argv.h cleanup_envelope.o: ../include/argv.h
cleanup_envelope.o: ../include/maps.h cleanup_envelope.o: ../include/maps.h
cleanup_envelope.o: ../include/dict.h
cleanup_envelope.o: ../include/been_here.h cleanup_envelope.o: ../include/been_here.h
cleanup_envelope.o: ../include/mail_stream.h cleanup_envelope.o: ../include/mail_stream.h
cleanup_extracted.o: cleanup_extracted.c cleanup_extracted.o: cleanup_extracted.c
@@ -115,6 +117,7 @@ cleanup_extracted.o: ../include/record.h
cleanup_extracted.o: ../include/rec_type.h cleanup_extracted.o: ../include/rec_type.h
cleanup_extracted.o: cleanup.h cleanup_extracted.o: cleanup.h
cleanup_extracted.o: ../include/maps.h cleanup_extracted.o: ../include/maps.h
cleanup_extracted.o: ../include/dict.h
cleanup_extracted.o: ../include/tok822.h cleanup_extracted.o: ../include/tok822.h
cleanup_extracted.o: ../include/resolve_clnt.h cleanup_extracted.o: ../include/resolve_clnt.h
cleanup_extracted.o: ../include/been_here.h cleanup_extracted.o: ../include/been_here.h
@@ -171,6 +174,7 @@ cleanup_masquerade.o: ../include/quote_822_local.h
cleanup_masquerade.o: cleanup.h cleanup_masquerade.o: cleanup.h
cleanup_masquerade.o: ../include/vstream.h cleanup_masquerade.o: ../include/vstream.h
cleanup_masquerade.o: ../include/maps.h cleanup_masquerade.o: ../include/maps.h
cleanup_masquerade.o: ../include/dict.h
cleanup_masquerade.o: ../include/been_here.h cleanup_masquerade.o: ../include/been_here.h
cleanup_masquerade.o: ../include/mail_stream.h cleanup_masquerade.o: ../include/mail_stream.h
cleanup_message.o: cleanup_message.c cleanup_message.o: cleanup_message.c
@@ -195,6 +199,7 @@ cleanup_message.o: ../include/mail_addr.h
cleanup_message.o: ../include/is_header.h cleanup_message.o: ../include/is_header.h
cleanup_message.o: cleanup.h cleanup_message.o: cleanup.h
cleanup_message.o: ../include/maps.h cleanup_message.o: ../include/maps.h
cleanup_message.o: ../include/dict.h
cleanup_message.o: ../include/been_here.h cleanup_message.o: ../include/been_here.h
cleanup_message.o: ../include/mail_stream.h cleanup_message.o: ../include/mail_stream.h
cleanup_out.o: cleanup_out.c cleanup_out.o: cleanup_out.c
@@ -209,6 +214,7 @@ cleanup_out.o: ../include/cleanup_user.h
cleanup_out.o: cleanup.h cleanup_out.o: cleanup.h
cleanup_out.o: ../include/argv.h cleanup_out.o: ../include/argv.h
cleanup_out.o: ../include/maps.h cleanup_out.o: ../include/maps.h
cleanup_out.o: ../include/dict.h
cleanup_out.o: ../include/tok822.h cleanup_out.o: ../include/tok822.h
cleanup_out.o: ../include/resolve_clnt.h cleanup_out.o: ../include/resolve_clnt.h
cleanup_out.o: ../include/been_here.h cleanup_out.o: ../include/been_here.h
@@ -224,6 +230,7 @@ cleanup_out_recipient.o: ../include/vstring.h
cleanup_out_recipient.o: ../include/vbuf.h cleanup_out_recipient.o: ../include/vbuf.h
cleanup_out_recipient.o: ../include/vstream.h cleanup_out_recipient.o: ../include/vstream.h
cleanup_out_recipient.o: ../include/maps.h cleanup_out_recipient.o: ../include/maps.h
cleanup_out_recipient.o: ../include/dict.h
cleanup_out_recipient.o: ../include/tok822.h cleanup_out_recipient.o: ../include/tok822.h
cleanup_out_recipient.o: ../include/resolve_clnt.h cleanup_out_recipient.o: ../include/resolve_clnt.h
cleanup_out_recipient.o: ../include/mail_stream.h cleanup_out_recipient.o: ../include/mail_stream.h
@@ -240,6 +247,7 @@ cleanup_rewrite.o: cleanup.h
cleanup_rewrite.o: ../include/vstream.h cleanup_rewrite.o: ../include/vstream.h
cleanup_rewrite.o: ../include/argv.h cleanup_rewrite.o: ../include/argv.h
cleanup_rewrite.o: ../include/maps.h cleanup_rewrite.o: ../include/maps.h
cleanup_rewrite.o: ../include/dict.h
cleanup_rewrite.o: ../include/been_here.h cleanup_rewrite.o: ../include/been_here.h
cleanup_rewrite.o: ../include/mail_stream.h cleanup_rewrite.o: ../include/mail_stream.h
cleanup_skip.o: cleanup_skip.c cleanup_skip.o: cleanup_skip.c
@@ -253,6 +261,7 @@ cleanup_skip.o: ../include/rec_type.h
cleanup_skip.o: cleanup.h cleanup_skip.o: cleanup.h
cleanup_skip.o: ../include/argv.h cleanup_skip.o: ../include/argv.h
cleanup_skip.o: ../include/maps.h cleanup_skip.o: ../include/maps.h
cleanup_skip.o: ../include/dict.h
cleanup_skip.o: ../include/tok822.h cleanup_skip.o: ../include/tok822.h
cleanup_skip.o: ../include/resolve_clnt.h cleanup_skip.o: ../include/resolve_clnt.h
cleanup_skip.o: ../include/been_here.h cleanup_skip.o: ../include/been_here.h
@@ -268,6 +277,7 @@ cleanup_state.o: ../include/mail_params.h
cleanup_state.o: cleanup.h cleanup_state.o: cleanup.h
cleanup_state.o: ../include/argv.h cleanup_state.o: ../include/argv.h
cleanup_state.o: ../include/maps.h cleanup_state.o: ../include/maps.h
cleanup_state.o: ../include/dict.h
cleanup_state.o: ../include/tok822.h cleanup_state.o: ../include/tok822.h
cleanup_state.o: ../include/resolve_clnt.h cleanup_state.o: ../include/resolve_clnt.h
cleanup_state.o: ../include/mail_stream.h cleanup_state.o: ../include/mail_stream.h

View File

@@ -375,15 +375,18 @@ static void pre_jail_init(void)
{ {
if (*var_canonical_maps) if (*var_canonical_maps)
cleanup_comm_canon_maps = cleanup_comm_canon_maps =
maps_create(VAR_CANONICAL_MAPS, var_canonical_maps); maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, DICT_FLAG_LOCK);
if (*var_send_canon_maps) if (*var_send_canon_maps)
cleanup_send_canon_maps = cleanup_send_canon_maps =
maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps); maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps,
DICT_FLAG_LOCK);
if (*var_rcpt_canon_maps) if (*var_rcpt_canon_maps)
cleanup_rcpt_canon_maps = cleanup_rcpt_canon_maps =
maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps); maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps,
DICT_FLAG_LOCK);
if (*var_virtual_maps) if (*var_virtual_maps)
cleanup_virtual_maps = maps_create(VAR_VIRTUAL_MAPS, var_virtual_maps); cleanup_virtual_maps = maps_create(VAR_VIRTUAL_MAPS, var_virtual_maps,
DICT_FLAG_LOCK);
if (*var_masq_domains) if (*var_masq_domains)
cleanup_masq_domains = argv_split(var_masq_domains, " ,\t\r\n"); cleanup_masq_domains = argv_split(var_masq_domains, " ,\t\r\n");
} }

View File

@@ -127,9 +127,15 @@ const char *mail_addr_find(MAPS *path, const char *address, char **extp)
/* /*
* Try user+foo@domain and user@domain. * Try user+foo@domain and user@domain.
*
* Specify what keys are partial or full, to avoid matching partial
* addresses with regular expressions.
*/ */
if ((result = maps_find(path, full_key)) == 0 && dict_errno == 0 #define FULL 0
&& bare_key != 0 && (result = maps_find(path, bare_key)) != 0 #define PARTIAL DICT_FLAG_FIXED
if ((result = maps_find(path, full_key, FULL)) == 0 && dict_errno == 0
&& bare_key != 0 && (result = maps_find(path, bare_key, PARTIAL)) != 0
&& extp != 0) { && extp != 0) {
*extp = saved_ext; *extp = saved_ext;
saved_ext = 0; saved_ext = 0;
@@ -144,12 +150,12 @@ const char *mail_addr_find(MAPS *path, const char *address, char **extp)
&& (strcasecmp(ratsign + 1, var_myorigin) == 0 && (strcasecmp(ratsign + 1, var_myorigin) == 0
|| resolve_local(ratsign + 1))) { || resolve_local(ratsign + 1))) {
*ratsign = 0; *ratsign = 0;
result = maps_find(path, full_key); result = maps_find(path, full_key, PARTIAL);
if (result == 0 && dict_errno == 0 && bare_key != 0) { if (result == 0 && dict_errno == 0 && bare_key != 0) {
if ((ratsign = strrchr(bare_key, '@')) == 0) if ((ratsign = strrchr(bare_key, '@')) == 0)
msg_panic("%s: bare key botch", myname); msg_panic("%s: bare key botch", myname);
*ratsign = 0; *ratsign = 0;
if ((result = maps_find(path, bare_key)) != 0 && extp != 0) { if ((result = maps_find(path, bare_key, PARTIAL)) != 0 && extp != 0) {
*extp = saved_ext; *extp = saved_ext;
saved_ext = 0; saved_ext = 0;
} }
@@ -161,7 +167,7 @@ const char *mail_addr_find(MAPS *path, const char *address, char **extp)
* Try @domain. * Try @domain.
*/ */
if (result == 0 && dict_errno == 0 && ratsign) if (result == 0 && dict_errno == 0 && ratsign)
result = maps_find(path, ratsign); result = maps_find(path, ratsign, PARTIAL);
/* /*
* Clean up. * Clean up.
@@ -202,18 +208,19 @@ int main(int argc, char **argv)
*/ */
if (argc != 2) if (argc != 2)
msg_fatal("usage: %s database", argv[0]); msg_fatal("usage: %s database", argv[0]);
msg_verbose = 1;
/* /*
* Initialize. * Initialize.
*/ */
read_config(); read_config();
path = maps_create(argv[0], argv[1]); path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK);
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
extent = 0; extent = 0;
result = mail_addr_find(path, STR(buffer), &extent); result = mail_addr_find(path, STR(buffer), &extent);
vstream_printf("%s -> %s (%s)\n", STR(buffer), result ? result : vstream_printf("%s -> %s (%s)\n", STR(buffer), result ? result :
dict_errno ? "(try again)" : dict_errno ? "(try again)" :
"(not found)", extent ? extent : "null"); "(not found)", extent ? extent : "null extension");
vstream_fflush(VSTREAM_OUT); vstream_fflush(VSTREAM_OUT);
if (extent) if (extent)
myfree(extent); myfree(extent);

View File

@@ -159,7 +159,7 @@ int main(int argc, char **argv)
msg_verbose = 1; msg_verbose = 1;
if (chdir(var_queue_dir) < 0) if (chdir(var_queue_dir) < 0)
msg_fatal("chdir %s: %m", var_queue_dir); msg_fatal("chdir %s: %m", var_queue_dir);
path = maps_create(argv[0], argv[1]); path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK);
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
if ((result = mail_addr_map(path, STR(buffer))) != 0) if ((result = mail_addr_map(path, STR(buffer))) != 0)
argv_free(result); argv_free(result);

View File

@@ -15,7 +15,7 @@
* Version of this program. * Version of this program.
*/ */
#define VAR_MAIL_VERSION "mail_version" #define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-19990328" #define DEF_MAIL_VERSION "Snapshot-19990329"
extern char *var_mail_version; extern char *var_mail_version;
/* LICENSE /* LICENSE

View File

@@ -28,7 +28,7 @@
/* named dictionaries. /* named dictionaries.
/* The result is a handle that must be specified along with all /* The result is a handle that must be specified along with all
/* other maps_xxx() operations. /* other maps_xxx() operations.
/* see dict_open(3) for a description of flags. /* See dict_open(3) for a description of flags.
/* /*
/* maps_find() searches the specified list of dictionaries /* maps_find() searches the specified list of dictionaries
/* in the specified order for the named key. The result is in /* in the specified order for the named key. The result is in
@@ -102,7 +102,7 @@
/* maps_create - initialize */ /* maps_create - initialize */
MAPS *maps_create(const char *title, const char *map_names) MAPS *maps_create(const char *title, const char *map_names, int flags)
{ {
char *myname = "maps_create"; char *myname = "maps_create";
char *temp = mystrdup(map_names); char *temp = mystrdup(map_names);
@@ -127,7 +127,10 @@ MAPS *maps_create(const char *title, const char *map_names)
if (msg_verbose) if (msg_verbose)
msg_info("%s: %s", myname, map_type_name); msg_info("%s: %s", myname, map_type_name);
if ((dict = dict_handle(map_type_name)) == 0) if ((dict = dict_handle(map_type_name)) == 0)
dict = dict_open(map_type_name, O_RDONLY, 0); dict = dict_open(map_type_name, O_RDONLY, flags);
else if ((dict->flags & flags) != flags)
msg_warn("%s: map %s has flags 0%o, want flags 0%o",
myname, map_type_name, dict->flags, flags);
dict_register(map_type_name, dict); dict_register(map_type_name, dict);
argv_add(maps->argv, map_type_name, ARGV_END); argv_add(maps->argv, map_type_name, ARGV_END);
} }
@@ -138,14 +141,19 @@ MAPS *maps_create(const char *title, const char *map_names)
/* maps_find - search a list of dictionaries */ /* maps_find - search a list of dictionaries */
const char *maps_find(MAPS *maps, const char *name) const char *maps_find(MAPS *maps, const char *name, int flags)
{ {
char *myname = "maps_find"; char *myname = "maps_find";
char **map_name; char **map_name;
const char *expansion; const char *expansion;
DICT *dict;
for (map_name = maps->argv->argv; *map_name; map_name++) { for (map_name = maps->argv->argv; *map_name; map_name++) {
if ((expansion = dict_lookup(*map_name, name)) != 0) { if ((dict = dict_handle(*map_name)) == 0)
msg_panic("%s: dictionary not found: %s", myname, *map_name);
if (flags != 0 && (dict->flags & flags) == 0)
continue;
if ((expansion = dict_get(dict, name)) != 0) {
if (msg_verbose) if (msg_verbose)
msg_info("%s: %s: %s = %s", myname, *map_name, name, expansion); msg_info("%s: %s: %s = %s", myname, *map_name, name, expansion);
return (expansion); return (expansion);
@@ -191,10 +199,10 @@ main(int argc, char **argv)
if (argc != 2) if (argc != 2)
msg_fatal("usage: %s maps", argv[0]); msg_fatal("usage: %s maps", argv[0]);
msg_verbose = 2; msg_verbose = 2;
maps = maps_create("whatever", argv[1]); maps = maps_create("whatever", argv[1], DICT_FLAG_LOCK);
while (vstring_fgets_nonl(buf, VSTREAM_IN)) { while (vstring_fgets_nonl(buf, VSTREAM_IN)) {
if ((result = maps_find(maps, vstring_str(buf))) != 0) { if ((result = maps_find(maps, vstring_str(buf), 0)) != 0) {
vstream_printf("%s\n", result); vstream_printf("%s\n", result);
} else if (dict_errno != 0) { } else if (dict_errno != 0) {
msg_fatal("lookup error: %m"); msg_fatal("lookup error: %m");

View File

@@ -11,6 +11,11 @@
/* DESCRIPTION /* DESCRIPTION
/* .nf /* .nf
/*
* Utility library.
*/
#include <dict.h>
/* /*
* Dictionary name storage. We're borrowing from the argv(3) module. * Dictionary name storage. We're borrowing from the argv(3) module.
*/ */
@@ -19,8 +24,8 @@ typedef struct MAPS {
struct ARGV *argv; struct ARGV *argv;
} MAPS; } MAPS;
extern MAPS *maps_create(const char *, const char *); extern MAPS *maps_create(const char *, const char *, int);
extern const char *maps_find(MAPS *, const char *); extern const char *maps_find(MAPS *, const char *, int);
extern MAPS *maps_free(MAPS *); extern MAPS *maps_free(MAPS *);
/* LICENSE /* LICENSE

View File

@@ -142,7 +142,7 @@ int deliver_alias(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
* Do this only once. * Do this only once.
*/ */
if (maps == 0) if (maps == 0)
maps = maps_create("aliases", var_alias_maps); maps = maps_create("aliases", var_alias_maps, DICT_FLAG_LOCK);
/* /*
* DUPLICATE/LOOP ELIMINATION * DUPLICATE/LOOP ELIMINATION
@@ -235,7 +235,7 @@ int deliver_alias(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
concatenate("owner-", state.msg_attr.local, (char *) 0))) concatenate("owner-", state.msg_attr.local, (char *) 0)))
expansion = mystrdup(alias_result); expansion = mystrdup(alias_result);
if (OWNER_ASSIGN(owner) != 0 && maps_find(maps, owner)) { if (OWNER_ASSIGN(owner) != 0 && maps_find(maps, owner, 0)) {
canon_owner = canon_addr_internal(vstring_alloc(10), owner); canon_owner = canon_addr_internal(vstring_alloc(10), owner);
SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level); SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
} else { } else {

View File

@@ -76,6 +76,7 @@ qmgr.o: ../include/mail_server.h
qmgr.o: qmgr.h qmgr.o: qmgr.h
qmgr.o: ../include/scan_dir.h qmgr.o: ../include/scan_dir.h
qmgr.o: ../include/maps.h qmgr.o: ../include/maps.h
qmgr.o: ../include/dict.h
qmgr_active.o: qmgr_active.c qmgr_active.o: qmgr_active.c
qmgr_active.o: ../include/sys_defs.h qmgr_active.o: ../include/sys_defs.h
qmgr_active.o: ../include/msg.h qmgr_active.o: ../include/msg.h
@@ -94,6 +95,7 @@ qmgr_active.o: ../include/rec_type.h
qmgr_active.o: qmgr.h qmgr_active.o: qmgr.h
qmgr_active.o: ../include/scan_dir.h qmgr_active.o: ../include/scan_dir.h
qmgr_active.o: ../include/maps.h qmgr_active.o: ../include/maps.h
qmgr_active.o: ../include/dict.h
qmgr_bounce.o: qmgr_bounce.c qmgr_bounce.o: qmgr_bounce.c
qmgr_bounce.o: ../include/sys_defs.h qmgr_bounce.o: ../include/sys_defs.h
qmgr_bounce.o: ../include/bounce.h qmgr_bounce.o: ../include/bounce.h
@@ -103,6 +105,7 @@ qmgr_bounce.o: ../include/vbuf.h
qmgr_bounce.o: qmgr.h qmgr_bounce.o: qmgr.h
qmgr_bounce.o: ../include/scan_dir.h qmgr_bounce.o: ../include/scan_dir.h
qmgr_bounce.o: ../include/maps.h qmgr_bounce.o: ../include/maps.h
qmgr_bounce.o: ../include/dict.h
qmgr_defer.o: qmgr_defer.c qmgr_defer.o: qmgr_defer.c
qmgr_defer.o: ../include/sys_defs.h qmgr_defer.o: ../include/sys_defs.h
qmgr_defer.o: ../include/msg.h qmgr_defer.o: ../include/msg.h
@@ -113,6 +116,7 @@ qmgr_defer.o: ../include/bounce.h
qmgr_defer.o: qmgr.h qmgr_defer.o: qmgr.h
qmgr_defer.o: ../include/scan_dir.h qmgr_defer.o: ../include/scan_dir.h
qmgr_defer.o: ../include/maps.h qmgr_defer.o: ../include/maps.h
qmgr_defer.o: ../include/dict.h
qmgr_deliver.o: qmgr_deliver.c qmgr_deliver.o: qmgr_deliver.c
qmgr_deliver.o: ../include/sys_defs.h qmgr_deliver.o: ../include/sys_defs.h
qmgr_deliver.o: ../include/msg.h qmgr_deliver.o: ../include/msg.h
@@ -129,6 +133,7 @@ qmgr_deliver.o: ../include/mail_params.h
qmgr_deliver.o: qmgr.h qmgr_deliver.o: qmgr.h
qmgr_deliver.o: ../include/scan_dir.h qmgr_deliver.o: ../include/scan_dir.h
qmgr_deliver.o: ../include/maps.h qmgr_deliver.o: ../include/maps.h
qmgr_deliver.o: ../include/dict.h
qmgr_enable.o: qmgr_enable.c qmgr_enable.o: qmgr_enable.c
qmgr_enable.o: ../include/sys_defs.h qmgr_enable.o: ../include/sys_defs.h
qmgr_enable.o: ../include/msg.h qmgr_enable.o: ../include/msg.h
@@ -137,6 +142,7 @@ qmgr_enable.o: ../include/vbuf.h
qmgr_enable.o: qmgr.h qmgr_enable.o: qmgr.h
qmgr_enable.o: ../include/scan_dir.h qmgr_enable.o: ../include/scan_dir.h
qmgr_enable.o: ../include/maps.h qmgr_enable.o: ../include/maps.h
qmgr_enable.o: ../include/dict.h
qmgr_entry.o: qmgr_entry.c qmgr_entry.o: qmgr_entry.c
qmgr_entry.o: ../include/sys_defs.h qmgr_entry.o: ../include/sys_defs.h
qmgr_entry.o: ../include/msg.h qmgr_entry.o: ../include/msg.h
@@ -148,6 +154,7 @@ qmgr_entry.o: ../include/mail_params.h
qmgr_entry.o: qmgr.h qmgr_entry.o: qmgr.h
qmgr_entry.o: ../include/scan_dir.h qmgr_entry.o: ../include/scan_dir.h
qmgr_entry.o: ../include/maps.h qmgr_entry.o: ../include/maps.h
qmgr_entry.o: ../include/dict.h
qmgr_message.o: qmgr_message.c qmgr_message.o: qmgr_message.c
qmgr_message.o: ../include/sys_defs.h qmgr_message.o: ../include/sys_defs.h
qmgr_message.o: ../include/msg.h qmgr_message.o: ../include/msg.h
@@ -185,6 +192,7 @@ qmgr_move.o: ../include/vstream.h
qmgr_move.o: ../include/mail_scan_dir.h qmgr_move.o: ../include/mail_scan_dir.h
qmgr_move.o: qmgr.h qmgr_move.o: qmgr.h
qmgr_move.o: ../include/maps.h qmgr_move.o: ../include/maps.h
qmgr_move.o: ../include/dict.h
qmgr_queue.o: qmgr_queue.c qmgr_queue.o: qmgr_queue.c
qmgr_queue.o: ../include/sys_defs.h qmgr_queue.o: ../include/sys_defs.h
qmgr_queue.o: ../include/msg.h qmgr_queue.o: ../include/msg.h
@@ -198,6 +206,7 @@ qmgr_queue.o: ../include/vstream.h
qmgr_queue.o: ../include/vbuf.h qmgr_queue.o: ../include/vbuf.h
qmgr_queue.o: ../include/scan_dir.h qmgr_queue.o: ../include/scan_dir.h
qmgr_queue.o: ../include/maps.h qmgr_queue.o: ../include/maps.h
qmgr_queue.o: ../include/dict.h
qmgr_rcpt_list.o: qmgr_rcpt_list.c qmgr_rcpt_list.o: qmgr_rcpt_list.c
qmgr_rcpt_list.o: ../include/sys_defs.h qmgr_rcpt_list.o: ../include/sys_defs.h
qmgr_rcpt_list.o: ../include/mymalloc.h qmgr_rcpt_list.o: ../include/mymalloc.h
@@ -206,6 +215,7 @@ qmgr_rcpt_list.o: ../include/vstream.h
qmgr_rcpt_list.o: ../include/vbuf.h qmgr_rcpt_list.o: ../include/vbuf.h
qmgr_rcpt_list.o: ../include/scan_dir.h qmgr_rcpt_list.o: ../include/scan_dir.h
qmgr_rcpt_list.o: ../include/maps.h qmgr_rcpt_list.o: ../include/maps.h
qmgr_rcpt_list.o: ../include/dict.h
qmgr_scan.o: qmgr_scan.c qmgr_scan.o: qmgr_scan.c
qmgr_scan.o: ../include/sys_defs.h qmgr_scan.o: ../include/sys_defs.h
qmgr_scan.o: ../include/msg.h qmgr_scan.o: ../include/msg.h
@@ -216,6 +226,7 @@ qmgr_scan.o: qmgr.h
qmgr_scan.o: ../include/vstream.h qmgr_scan.o: ../include/vstream.h
qmgr_scan.o: ../include/vbuf.h qmgr_scan.o: ../include/vbuf.h
qmgr_scan.o: ../include/maps.h qmgr_scan.o: ../include/maps.h
qmgr_scan.o: ../include/dict.h
qmgr_transport.o: qmgr_transport.c qmgr_transport.o: qmgr_transport.c
qmgr_transport.o: ../include/sys_defs.h qmgr_transport.o: ../include/sys_defs.h
qmgr_transport.o: ../include/msg.h qmgr_transport.o: ../include/msg.h
@@ -232,3 +243,4 @@ qmgr_transport.o: ../include/mail_params.h
qmgr_transport.o: qmgr.h qmgr_transport.o: qmgr.h
qmgr_transport.o: ../include/scan_dir.h qmgr_transport.o: ../include/scan_dir.h
qmgr_transport.o: ../include/maps.h qmgr_transport.o: ../include/maps.h
qmgr_transport.o: ../include/dict.h

View File

@@ -392,9 +392,11 @@ static int qmgr_loop(void)
static void qmgr_pre_init(void) static void qmgr_pre_init(void)
{ {
if (*var_relocated_maps) if (*var_relocated_maps)
qmgr_relocated = maps_create("relocated", var_relocated_maps); qmgr_relocated = maps_create("relocated", var_relocated_maps,
DICT_FLAG_LOCK);
if (*var_virtual_maps) if (*var_virtual_maps)
qmgr_virtual = maps_create("virtual", var_virtual_maps); qmgr_virtual = maps_create("virtual", var_virtual_maps,
DICT_FLAG_LOCK);
} }
/* qmgr_post_init - post-jail initialization */ /* qmgr_post_init - post-jail initialization */

View File

@@ -478,7 +478,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
&& qmgr_virtual != 0 && qmgr_virtual != 0
&& (at = strrchr(recipient->address, '@')) != 0) { && (at = strrchr(recipient->address, '@')) != 0) {
domain = lowercase(mystrdup(at + 1)); domain = lowercase(mystrdup(at + 1));
junk = maps_find(qmgr_virtual, domain); junk = maps_find(qmgr_virtual, domain, 0);
myfree(domain); myfree(domain);
if (junk) { if (junk) {
qmgr_bounce_recipient(message, recipient, qmgr_bounce_recipient(message, recipient,

View File

@@ -312,7 +312,7 @@ static ARGV *smtpd_check_parse(char *checks)
while ((name = mystrtok(&bp, " \t\r\n,")) != 0) { while ((name = mystrtok(&bp, " \t\r\n,")) != 0) {
argv_add(argv, name, (char *) 0); argv_add(argv, name, (char *) 0);
if (strchr(name, ':') && dict_handle(name) == 0) if (strchr(name, ':') && dict_handle(name) == 0)
dict_register(name, dict_open(name, 0, 0)); dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK));
} }
argv_terminate(argv); argv_terminate(argv);
@@ -877,33 +877,42 @@ static int check_table_result(SMTPD_STATE *state, char *table,
/* check_access - table lookup without substring magic */ /* check_access - table lookup without substring magic */
static int check_access(SMTPD_STATE *state, char *table, char *name) static int check_access(SMTPD_STATE *state, char *table, char *name, int flags)
{ {
char *myname = "check_access"; char *myname = "check_access";
char *low_name = lowercase(mystrdup(name)); char *low_name = lowercase(mystrdup(name));
const char *value; const char *value;
DICT *dict;
#define CHK_ACCESS_RETURN(x) { myfree(low_name); return(x); } #define CHK_ACCESS_RETURN(x) { myfree(low_name); return(x); }
#define FULL 0
#define PARTIAL DICT_FLAG_FIXED
if (msg_verbose) if (msg_verbose)
msg_info("%s: %s", myname, name); msg_info("%s: %s", myname, name);
if ((value = dict_lookup(table, low_name)) != 0) if ((dict = dict_handle(table)) == 0)
CHK_ACCESS_RETURN(check_table_result(state, table, value, name)); msg_panic("%s: dictionary not found: %s", myname, table);
if (dict_errno != 0) if (flags == 0 || (flags & dict->flags) != 0) {
msg_fatal("%s: table lookup problem", table); if ((value = dict_get(dict, low_name)) != 0)
CHK_ACCESS_RETURN(check_table_result(state, table, value, name));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO); CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO);
} }
/* check_domain_access - domainname-based table lookup */ /* check_domain_access - domainname-based table lookup */
static int check_domain_access(SMTPD_STATE *state, char *table, char *domain) static int check_domain_access(SMTPD_STATE *state, char *table,
char *domain, int flags)
{ {
char *myname = "check_domain_access"; char *myname = "check_domain_access";
char *low_domain = lowercase(mystrdup(domain)); char *low_domain = lowercase(mystrdup(domain));
char *name; char *name;
char *next; char *next;
const char *value; const char *value;
DICT *dict;
if (msg_verbose) if (msg_verbose)
msg_info("%s: %s", myname, domain); msg_info("%s: %s", myname, domain);
@@ -914,21 +923,28 @@ static int check_domain_access(SMTPD_STATE *state, char *table, char *domain)
#define CHK_DOMAIN_RETURN(x) { myfree(low_domain); return(x); } #define CHK_DOMAIN_RETURN(x) { myfree(low_domain); return(x); }
for (name = low_domain; (next = strchr(name, '.')) != 0; name = next + 1) { for (name = low_domain; (next = strchr(name, '.')) != 0; name = next + 1) {
if ((value = dict_lookup(table, name)) != 0) if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
if (flags != 0 && (flags & dict->flags) == 0)
continue;
if ((value = dict_get(dict, name)) != 0)
CHK_DOMAIN_RETURN(check_table_result(state, table, value, domain)); CHK_DOMAIN_RETURN(check_table_result(state, table, value, domain));
if (dict_errno != 0) if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table); msg_fatal("%s: table lookup problem", table);
flags = PARTIAL;
} }
CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO); CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO);
} }
/* check_addr_access - address-based table lookup */ /* check_addr_access - address-based table lookup */
static int check_addr_access(SMTPD_STATE *state, char *table, char *address) static int check_addr_access(SMTPD_STATE *state, char *table, char *address,
int flags)
{ {
char *myname = "check_addr_access"; char *myname = "check_addr_access";
char *addr; char *addr;
const char *value; const char *value;
DICT *dict;
if (msg_verbose) if (msg_verbose)
msg_info("%s: %s", myname, address); msg_info("%s: %s", myname, address);
@@ -939,10 +955,15 @@ static int check_addr_access(SMTPD_STATE *state, char *table, char *address)
addr = STR(vstring_strcpy(error_text, address)); addr = STR(vstring_strcpy(error_text, address));
do { do {
if ((value = dict_lookup(table, addr)) != 0) if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
if (flags != 0 && (flags & dict->flags) == 0)
continue;
if ((value = dict_get(dict, addr)) != 0)
return (check_table_result(state, table, value, address)); return (check_table_result(state, table, value, address));
if (dict_errno != 0) if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table); msg_fatal("%s: table lookup problem", table);
flags = PARTIAL;
} while (split_at_right(addr, '.')); } while (split_at_right(addr, '.'));
return (SMTPD_CHECK_DUNNO); return (SMTPD_CHECK_DUNNO);
@@ -951,7 +972,7 @@ static int check_addr_access(SMTPD_STATE *state, char *table, char *address)
/* check_namadr_access - OK/FAIL based on host name/address lookup */ /* check_namadr_access - OK/FAIL based on host name/address lookup */
static int check_namadr_access(SMTPD_STATE *state, char *table, static int check_namadr_access(SMTPD_STATE *state, char *table,
char *name, char *addr) char *name, char *addr, int flags)
{ {
char *myname = "check_namadr_access"; char *myname = "check_namadr_access";
int status; int status;
@@ -963,13 +984,13 @@ static int check_namadr_access(SMTPD_STATE *state, char *table,
* Look up the host name, or parent domains thereof. XXX A domain * Look up the host name, or parent domains thereof. XXX A domain
* wildcard may pre-empt a more specific address table entry. * wildcard may pre-empt a more specific address table entry.
*/ */
if ((status = check_domain_access(state, table, name)) != 0) if ((status = check_domain_access(state, table, name, flags)) != 0)
return (status); return (status);
/* /*
* Look up the network address, or parent networks thereof. * Look up the network address, or parent networks thereof.
*/ */
if ((status = check_addr_access(state, table, addr)) != 0) if ((status = check_addr_access(state, table, addr, flags)) != 0)
return (status); return (status);
/* /*
@@ -1008,13 +1029,13 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr)
/* /*
* Look up the full address. * Look up the full address.
*/ */
if ((status = check_access(state, table, STR(reply.recipient))) != 0) if ((status = check_access(state, table, STR(reply.recipient), FULL)) != 0)
return (status); return (status);
/* /*
* Look up the domain name, or parent domains thereof. * Look up the domain name, or parent domains thereof.
*/ */
if ((status = check_domain_access(state, table, ratsign + 1)) != 0) if ((status = check_domain_access(state, table, ratsign + 1, PARTIAL)) != 0)
return (status); return (status);
/* /*
@@ -1022,7 +1043,7 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr)
*/ */
local_at = mystrndup(STR(reply.recipient), local_at = mystrndup(STR(reply.recipient),
ratsign - STR(reply.recipient) + 1); ratsign - STR(reply.recipient) + 1);
status = check_access(state, table, local_at); status = check_access(state, table, local_at, PARTIAL);
myfree(local_at); myfree(local_at);
if (status != 0) if (status != 0)
return (status); return (status);
@@ -1147,7 +1168,7 @@ static int generic_checks(SMTPD_STATE *state, char *name,
return (1); return (1);
} }
if (is_map_command(name, CHECK_CLIENT_ACL, cpp)) { if (is_map_command(name, CHECK_CLIENT_ACL, cpp)) {
*status = check_namadr_access(state, **cpp, state->name, state->addr); *status = check_namadr_access(state, **cpp, state->name, state->addr, FULL);
return (1); return (1);
} }
if (strcasecmp(name, REJECT_MAPS_RBL) == 0) { if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
@@ -1160,7 +1181,7 @@ static int generic_checks(SMTPD_STATE *state, char *name,
*/ */
if (state->helo_name) { if (state->helo_name) {
if (is_map_command(name, CHECK_HELO_ACL, cpp) && state->helo_name) { if (is_map_command(name, CHECK_HELO_ACL, cpp) && state->helo_name) {
*status = check_domain_access(state, **cpp, state->helo_name); *status = check_domain_access(state, **cpp, state->helo_name, FULL);
return (1); return (1);
} }
if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) { if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
@@ -1237,7 +1258,7 @@ char *smtpd_check_client(SMTPD_STATE *state)
*/ */
for (cpp = client_restrctions->argv; (name = *cpp) != 0; cpp++) { for (cpp = client_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) { if (strchr(name, ':') != 0) {
status = check_namadr_access(state, name, state->name, state->addr); status = check_namadr_access(state, name, state->name, state->addr, FULL);
} else if (generic_checks(state, name, &cpp, &status, state->addr) == 0) { } else if (generic_checks(state, name, &cpp, &status, state->addr) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_CLIENT_CHECKS, name); msg_warn("unknown %s check: \"%s\"", VAR_CLIENT_CHECKS, name);
break; break;
@@ -1271,7 +1292,7 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
state->helo_name = mystrdup(helohost); state->helo_name = mystrdup(helohost);
for (cpp = helo_restrctions->argv; (name = *cpp) != 0; cpp++) { for (cpp = helo_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) { if (strchr(name, ':') != 0) {
status = check_domain_access(state, name, helohost); status = check_domain_access(state, name, helohost, FULL);
} else if (generic_checks(state, name, &cpp, &status, helohost) == 0) { } else if (generic_checks(state, name, &cpp, &status, helohost) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_HELO_CHECKS, name); msg_warn("unknown %s check: \"%s\"", VAR_HELO_CHECKS, name);
break; break;
@@ -1381,9 +1402,9 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
*/ */
for (cpp = etrn_restrctions->argv; (name = *cpp) != 0; cpp++) { for (cpp = etrn_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) { if (strchr(name, ':') != 0) {
status = check_domain_access(state, name, domain); status = check_domain_access(state, name, domain, FULL);
} else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) { } else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) {
status = check_domain_access(state, *cpp, domain); status = check_domain_access(state, *cpp, domain, FULL);
} else if (generic_checks(state, name, &cpp, &status, domain) == 0) { } else if (generic_checks(state, name, &cpp, &status, domain) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_RCPT_CHECKS, name); msg_warn("unknown %s check: \"%s\"", VAR_RCPT_CHECKS, name);
break; break;

View File

@@ -75,7 +75,8 @@ void transport_init(void)
{ {
if (transport_path) if (transport_path)
msg_panic("transport_init: repeated call"); msg_panic("transport_init: repeated call");
transport_path = maps_create("transport", var_transport_maps); transport_path = maps_create("transport", var_transport_maps,
DICT_FLAG_LOCK);
} }
/* transport_lookup - map a transport domain */ /* transport_lookup - map a transport domain */
@@ -90,6 +91,11 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
char *transport; char *transport;
int found = 0; int found = 0;
#define FULL 0
#define PARTIAL DICT_FLAG_FIXED
int maps_flag = FULL;
if (transport_path == 0) if (transport_path == 0)
msg_panic("transport_lookup: missing initialization"); msg_panic("transport_lookup: missing initialization");
@@ -103,9 +109,12 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
* *
* Before changing the DB lookup result, make a copy first, in order to * Before changing the DB lookup result, make a copy first, in order to
* avoid DB cache corruption. * avoid DB cache corruption.
*
* Specify if a key is partial or full, to avoid matching partial keys with
* regular expressions.
*/ */
for (name = low_domain; name != 0; name = strchr(name + 1, '.')) { for (name = low_domain; name != 0; name = strchr(name + 1, '.')) {
if ((value = maps_find(transport_path, name)) != 0) { if ((value = maps_find(transport_path, name, maps_flag)) != 0) {
saved_value = mystrdup(value); saved_value = mystrdup(value);
if ((host = split_at(saved_value, ':')) == 0 || *host == 0) if ((host = split_at(saved_value, ':')) == 0 || *host == 0)
host = domain; host = domain;
@@ -119,6 +128,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
} else if (dict_errno != 0) { } else if (dict_errno != 0) {
msg_fatal("transport table lookup problem"); msg_fatal("transport table lookup problem");
} }
maps_flag = PARTIAL;
} }
myfree(low_domain); myfree(low_domain);
return (found); return (found);

View File

@@ -291,7 +291,6 @@ dict.o: vstream.h
dict.o: vbuf.h dict.o: vbuf.h
dict.o: vstring.h dict.o: vstring.h
dict.o: readline.h dict.o: readline.h
dict.o: myflock.h
dict.o: mac_parse.h dict.o: mac_parse.h
dict.o: dict.h dict.o: dict.h
dict.o: dict_ht.h dict.o: dict_ht.h
@@ -303,6 +302,7 @@ dict_db.o: vstring.h
dict_db.o: vbuf.h dict_db.o: vbuf.h
dict_db.o: stringops.h dict_db.o: stringops.h
dict_db.o: iostuff.h dict_db.o: iostuff.h
dict_db.o: myflock.h
dict_db.o: dict.h dict_db.o: dict.h
dict_db.o: vstream.h dict_db.o: vstream.h
dict_db.o: dict_db.h dict_db.o: dict_db.h

View File

@@ -78,20 +78,11 @@
/* /*
/* dict_update() updates the value of the named dictionary member. /* dict_update() updates the value of the named dictionary member.
/* The dictionary member and the named dictionary are instantiated /* The dictionary member and the named dictionary are instantiated
/* on the fly. During the update, a file-based dictionary is locked /* on the fly.
/* for exclusive access. With file-based dictionaries, duplicate
/* of duplicate entries depends on dictionary flag settings:
/* .IP DICT_FLAG_DUP_WARN
/* Log a warning and ignore the duplicate.
/* .IP DICT_FLAG_DUP_IGNORE
/* Silently ignore the duplicate.
/* .PP
/* The default is to terminate the program with a fatal error.
/* /*
/* dict_lookup() returns the value of the named member (i.e. without /* dict_lookup() returns the value of the named member (i.e. without
/* expanding macros in the member value). The \fIdict_name\fR argument /* expanding macros in the member value). The \fIdict_name\fR argument
/* specifies the dictionary to search. The dictionary is locked for /* specifies the dictionary to search. The result is a null pointer
/* shared access, when it is file based. The result is a null pointer
/* when no value is found, otherwise the result is owned by the /* when no value is found, otherwise the result is owned by the
/* underlying dictionary method. Make a copy if the result is to be /* underlying dictionary method. Make a copy if the result is to be
/* modified, or if the result is to survive multiple dict_lookup() calls. /* modified, or if the result is to survive multiple dict_lookup() calls.
@@ -149,7 +140,6 @@
#include "vstream.h" #include "vstream.h"
#include "vstring.h" #include "vstring.h"
#include "readline.h" #include "readline.h"
#include "myflock.h"
#include "mac_parse.h" #include "mac_parse.h"
#include "dict.h" #include "dict.h"
#include "dict_ht.h" #include "dict_ht.h"
@@ -252,11 +242,7 @@ void dict_update(const char *dict_name, const char *member, const char *value
dict = node->dict; dict = node->dict;
if (msg_verbose > 1) if (msg_verbose > 1)
msg_info("%s: %s = %s", myname, member, value); msg_info("%s: %s = %s", myname, member, value);
if (dict->fd >= 0 && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary %s: %m", myname, dict_name);
dict->update(dict, member, value); dict->update(dict, member, value);
if (dict->fd >= 0 && myflock(dict->fd, MYFLOCK_NONE) < 0)
msg_fatal("%s: unlock dictionary %s: %m", myname, dict_name);
} }
/* dict_lookup - look up dictionary entry */ /* dict_lookup - look up dictionary entry */
@@ -268,18 +254,12 @@ const char *dict_lookup(const char *dict_name, const char *member)
DICT *dict; DICT *dict;
const char *ret = 0; const char *ret = 0;
dict_errno = 0;
if ((node = dict_node(dict_name)) == 0) { if ((node = dict_node(dict_name)) == 0) {
if (dict_unknown_allowed == 0) if (dict_unknown_allowed == 0)
msg_fatal("%s: unknown dictionary: %s", myname, dict_name); msg_fatal("%s: unknown dictionary: %s", myname, dict_name);
} else { } else {
dict = node->dict; dict = node->dict;
if (dict->fd >= 0 && myflock(dict->fd, MYFLOCK_SHARED) < 0)
msg_fatal("%s: lock dictionary %s: %m", myname, dict_name);
ret = dict->lookup(dict, member); ret = dict->lookup(dict, member);
if (dict->fd >= 0 && myflock(dict->fd, MYFLOCK_NONE) < 0)
msg_fatal("%s: unlock dictionary %s: %m", myname, dict_name);
if (ret == 0 && dict_unknown_allowed == 0) if (ret == 0 && dict_unknown_allowed == 0)
msg_fatal("dictionary %s: unknown member: %s", dict_name, member); msg_fatal("dictionary %s: unknown member: %s", dict_name, member);
} }

View File

@@ -39,6 +39,7 @@ typedef struct DICT {
#define DICT_FLAG_TRY1NULL (1<<3) /* append 0 to key/value */ #define DICT_FLAG_TRY1NULL (1<<3) /* append 0 to key/value */
#define DICT_FLAG_FIXED (1<<4) /* fixed key map */ #define DICT_FLAG_FIXED (1<<4) /* fixed key map */
#define DICT_FLAG_PATTERN (1<<5) /* keys are patterns */ #define DICT_FLAG_PATTERN (1<<5) /* keys are patterns */
#define DICT_FLAG_LOCK (1<<6) /* lock before access */
extern int dict_unknown_allowed; extern int dict_unknown_allowed;
extern int dict_errno; extern int dict_errno;
@@ -64,7 +65,7 @@ extern const char *dict_eval(const char *, const char *, int);
*/ */
extern DICT *dict_open(const char *, int, int); extern DICT *dict_open(const char *, int, int);
extern DICT *dict_open3(const char *, 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));
#define dict_get(dp, key) (dp)->lookup((dp), (key)) #define dict_get(dp, key) (dp)->lookup((dp), (key))
#define dict_put(dp, key, val) (dp)->update((dp), (key), (val)) #define dict_put(dp, key, val) (dp)->update((dp), (key), (val))
#define dict_close(dp) (dp)->close(dp) #define dict_close(dp) (dp)->close(dp)

View File

@@ -63,6 +63,7 @@
#include "vstring.h" #include "vstring.h"
#include "stringops.h" #include "stringops.h"
#include "iostuff.h" #include "iostuff.h"
#include "myflock.h"
#include "dict.h" #include "dict.h"
#include "dict_db.h" #include "dict_db.h"
@@ -70,7 +71,6 @@
typedef struct { typedef struct {
DICT dict; /* generic members */ DICT dict; /* generic members */
int flags; /* see below */
DB *db; /* open db file */ DB *db; /* open db file */
char *path; /* pathname */ char *path; /* pathname */
} DICT_DB; } DICT_DB;
@@ -88,19 +88,28 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
DBT db_value; DBT db_value;
int status; int status;
static VSTRING *buf; static VSTRING *buf;
const char *result = 0;
dict_errno = 0;
/*
* Acquire a shared lock.
*/
if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_SHARED) < 0)
msg_fatal("%s: lock dictionary: %m", dict_db->path);
/* /*
* See if this DB file was written with one null byte appended to key and * See if this DB file was written with one null byte appended to key and
* value. * value.
*/ */
if (dict_db->flags & DICT_FLAG_TRY1NULL) { if (dict->flags & DICT_FLAG_TRY1NULL) {
db_key.data = (void *) name; db_key.data = (void *) name;
db_key.size = strlen(name) + 1; db_key.size = strlen(name) + 1;
if ((status = db->get(db, &db_key, &db_value, 0)) < 0) if ((status = db->get(db, &db_key, &db_value, 0)) < 0)
msg_fatal("error reading %s: %m", dict_db->path); msg_fatal("error reading %s: %m", dict_db->path);
if (status == 0) { if (status == 0) {
dict_db->flags &= ~DICT_FLAG_TRY0NULL; dict->flags &= ~DICT_FLAG_TRY0NULL;
return (db_value.data); result = db_value.data;
} }
} }
@@ -108,7 +117,7 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
* See if this DB file was written with no null byte appended to key and * See if this DB file was written with no null byte appended to key and
* value. * value.
*/ */
if (dict_db->flags & DICT_FLAG_TRY0NULL) { if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
db_key.data = (void *) name; db_key.data = (void *) name;
db_key.size = strlen(name); db_key.size = strlen(name);
if ((status = db->get(db, &db_key, &db_value, 0)) < 0) if ((status = db->get(db, &db_key, &db_value, 0)) < 0)
@@ -117,11 +126,18 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
if (buf == 0) if (buf == 0)
buf = vstring_alloc(10); buf = vstring_alloc(10);
vstring_strncpy(buf, db_value.data, db_value.size); vstring_strncpy(buf, db_value.data, db_value.size);
dict_db->flags &= ~DICT_FLAG_TRY1NULL; dict->flags &= ~DICT_FLAG_TRY1NULL;
return (vstring_str(buf)); result = vstring_str(buf);
} }
} }
return (0);
/*
* Release the shared lock.
*/
if ((dict->fd & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_db->path);
return (result);
} }
/* dict_db_update - add or update database entry */ /* dict_db_update - add or update database entry */
@@ -143,23 +159,31 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
* If undecided about appending a null byte to key and value, choose a * If undecided about appending a null byte to key and value, choose a
* default depending on the platform. * default depending on the platform.
*/ */
if ((dict_db->flags & DICT_FLAG_TRY1NULL) if ((dict->flags & DICT_FLAG_TRY1NULL)
&& (dict_db->flags & DICT_FLAG_TRY0NULL)) { && (dict->flags & DICT_FLAG_TRY0NULL)) {
#ifdef DB_NO_TRAILING_NULL #ifdef DB_NO_TRAILING_NULL
dict_db->flags = DICT_FLAG_TRY0NULL; dict->flags &= ~DICT_FLAG_TRY1NULL;
dict->flags |= DICT_FLAG_TRY0NULL;
#else #else
dict_db->flags = DICT_FLAG_TRY1NULL; dict->flags &= ~DICT_FLAG_TRY0NULL;
dict->flags |= DICT_FLAG_TRY1NULL;
#endif #endif
} }
/* /*
* Optionally append a null byte to key and value. * Optionally append a null byte to key and value.
*/ */
if (dict_db->flags & DICT_FLAG_TRY1NULL) { if (dict->flags & DICT_FLAG_TRY1NULL) {
db_key.size++; db_key.size++;
db_value.size++; db_value.size++;
} }
/*
* Acquire an exclusive lock.
*/
if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_db->path);
/* /*
* Do the update. * Do the update.
*/ */
@@ -173,6 +197,12 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
else else
msg_fatal("%s: duplicate entry: \"%s\"", dict_db->path, name); msg_fatal("%s: duplicate entry: \"%s\"", dict_db->path, name);
} }
/*
* Release the exclusive lock.
*/
if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_db->path);
} }
/* dict_db_close - close data base */ /* dict_db_close - close data base */
@@ -237,5 +267,6 @@ DICT *dict_btree_open(const char *path, int open_flags, int dict_flags)
return (dict_db_open(path, open_flags, DB_BTREE, (void *) &tweak, dict_flags)); return (dict_db_open(path, open_flags, DB_BTREE, (void *) &tweak, dict_flags));
} }
/**INDENT** Error@188: Unmatched #endif */
#endif #endif

View File

@@ -46,6 +46,7 @@
#include "htable.h" #include "htable.h"
#include "iostuff.h" #include "iostuff.h"
#include "vstring.h" #include "vstring.h"
#include "myflock.h"
#include "dict.h" #include "dict.h"
#include "dict_dbm.h" #include "dict_dbm.h"
@@ -53,7 +54,6 @@
typedef struct { typedef struct {
DICT dict; /* generic members */ DICT dict; /* generic members */
int flags; /* see below */
DBM *dbm; /* open database */ DBM *dbm; /* open database */
char *path; /* pathname */ char *path; /* pathname */
} DICT_DBM; } DICT_DBM;
@@ -66,18 +66,27 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
datum dbm_key; datum dbm_key;
datum dbm_value; datum dbm_value;
static VSTRING *buf; static VSTRING *buf;
const char *result = 0;
dict_errno = 0;
/*
* Acquire an exclusive lock.
*/
if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_SHARED) < 0)
msg_fatal("%s: lock dictionary: %m", dict_dbm->path);
/* /*
* See if this DBM file was written with one null byte appended to key * See if this DBM file was written with one null byte appended to key
* and value. * and value.
*/ */
if (dict_dbm->flags & DICT_FLAG_TRY1NULL) { if (dict->flags & DICT_FLAG_TRY1NULL) {
dbm_key.dptr = (void *) name; dbm_key.dptr = (void *) name;
dbm_key.dsize = strlen(name) + 1; dbm_key.dsize = strlen(name) + 1;
dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key); dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
if (dbm_value.dptr != 0) { if (dbm_value.dptr != 0) {
dict_dbm->flags &= ~DICT_FLAG_TRY0NULL; dict->flags &= ~DICT_FLAG_TRY0NULL;
return (dbm_value.dptr); result = dbm_value.dptr;
} }
} }
@@ -85,7 +94,7 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
* See if this DBM file was written with no null byte appended to key and * See if this DBM file was written with no null byte appended to key and
* value. * value.
*/ */
if (dict_dbm->flags & DICT_FLAG_TRY0NULL) { if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
dbm_key.dptr = (void *) name; dbm_key.dptr = (void *) name;
dbm_key.dsize = strlen(name); dbm_key.dsize = strlen(name);
dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key); dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
@@ -93,11 +102,18 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
if (buf == 0) if (buf == 0)
buf = vstring_alloc(10); buf = vstring_alloc(10);
vstring_strncpy(buf, dbm_value.dptr, dbm_value.dsize); vstring_strncpy(buf, dbm_value.dptr, dbm_value.dsize);
dict_dbm->flags &= ~DICT_FLAG_TRY1NULL; dict->flags &= ~DICT_FLAG_TRY1NULL;
return (vstring_str(buf)); result = vstring_str(buf);
} }
} }
return (0);
/*
* Release the exclusive lock.
*/
if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_dbm->path);
return (result);
} }
/* dict_dbm_update - add or update database entry */ /* dict_dbm_update - add or update database entry */
@@ -118,23 +134,31 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
* If undecided about appending a null byte to key and value, choose a * If undecided about appending a null byte to key and value, choose a
* default depending on the platform. * default depending on the platform.
*/ */
if ((dict_dbm->flags & DICT_FLAG_TRY1NULL) if ((dict->flags & DICT_FLAG_TRY1NULL)
&& (dict_dbm->flags & DICT_FLAG_TRY0NULL)) { && (dict->flags & DICT_FLAG_TRY0NULL)) {
#ifdef DBM_NO_TRAILING_NULL #ifdef DBM_NO_TRAILING_NULL
dict_dbm->flags = DICT_FLAG_TRY0NULL; dict->flags &= ~DICT_FLAG_TRY1NULL;
dict->flags |= DICT_FLAG_TRY0NULL;
#else #else
dict_dbm->flags = DICT_FLAG_TRY1NULL; dict->flags &= ~DICT_FLAG_TRY0NULL;
dict->flags |= DICT_FLAG_TRY1NULL;
#endif #endif
} }
/* /*
* Optionally append a null byte to key and value. * Optionally append a null byte to key and value.
*/ */
if (dict_dbm->flags & DICT_FLAG_TRY1NULL) { if (dict->flags & DICT_FLAG_TRY1NULL) {
dbm_key.dsize++; dbm_key.dsize++;
dbm_value.dsize++; dbm_value.dsize++;
} }
/*
* Acquire an exclusive lock.
*/
if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("%s: lock dictionary: %m", dict_dbm->path);
/* /*
* Do the update. * Do the update.
*/ */
@@ -148,6 +172,12 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
else else
msg_fatal("%s: duplicate entry: \"%s\"", dict_dbm->path, name); msg_fatal("%s: duplicate entry: \"%s\"", dict_dbm->path, name);
} }
/*
* Release the exclusive lock.
*/
if ((dict->flags & DICT_FLAG_LOCK) && myflock(dict->fd, MYFLOCK_NONE) < 0)
msg_fatal("%s: unlock dictionary: %m", dict_dbm->path);
} }
/* dict_dbm_close - disassociate from data base */ /* dict_dbm_close - disassociate from data base */

View File

@@ -57,6 +57,8 @@ static void dict_env_update(DICT *unused_dict, const char *name, const char *val
static const char *dict_env_lookup(DICT *unused_dict, const char *name) static const char *dict_env_lookup(DICT *unused_dict, const char *name)
{ {
dict_errno = 0;
return (safe_getenv(name)); return (safe_getenv(name));
} }

View File

@@ -54,6 +54,8 @@ static const char *dict_ht_lookup(DICT *dict, const char *name)
{ {
DICT_HT *dict_ht = (DICT_HT *) dict; DICT_HT *dict_ht = (DICT_HT *) dict;
dict_errno = 0;
return (htable_find(dict_ht->table, name)); return (htable_find(dict_ht->table, name));
} }

View File

@@ -143,6 +143,8 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
int rc = 0; int rc = 0;
void (*saved_alarm) (int); void (*saved_alarm) (int);
dict_errno = 0;
/* /*
* Initialize. * Initialize.
*/ */

View File

@@ -79,6 +79,8 @@ static const char *dict_ni_do_lookup(char *path, char *key_prop,
ni_status r; ni_status r;
ni_id dir; ni_id dir;
dict_errno = 0;
if (msg_verbose) if (msg_verbose)
msg_info("ni_lookup %s %s=%s", path, key_prop, key_value); msg_info("ni_lookup %s %s=%s", path, key_prop, key_value);

View File

@@ -51,6 +51,7 @@ typedef struct {
static const char *dict_nisplus_lookup(DICT *unused_dict, const char *unused_name) static const char *dict_nisplus_lookup(DICT *unused_dict, const char *unused_name)
{ {
dict_errno = 0;
msg_warn("dict_nisplus_lookup: NISPLUS lookup not implemented"); msg_warn("dict_nisplus_lookup: NISPLUS lookup not implemented");
return (0); return (0);
} }

View File

@@ -28,6 +28,10 @@
/* /*
/* void dict_close(dict) /* void dict_close(dict)
/* DICT *dict; /* DICT *dict;
/*
/* dict_open_register(type, open)
/* char *type;
/* DICT *(*open) (const char *, int, int);
/* DESCRIPTION /* DESCRIPTION
/* This module implements a low-level interface to multiple /* This module implements a low-level interface to multiple
/* physical dictionary types. /* physical dictionary types.
@@ -44,6 +48,23 @@
/* Ignore duplicate keys if the underlying database does not /* Ignore duplicate keys if the underlying database does not
/* support duplicate keys. The default is to terminate with a fatal /* support duplicate keys. The default is to terminate with a fatal
/* error. /* error.
/* .IP DICT_FLAG_TRY0NULL
/* With maps where this is appropriate, append no null byte to
/* keys and values.
/* When neither DICT_FLAG_TRY0NULL nor DICT_FLAG_TRY1NULL are
/* specified, the software guesses what format to use for reading;
/* and in the absence of definite information, a system-dependent
/* default is chosen for writing.
/* .IP DICT_FLAG_TRY1NULL
/* With maps where this is appropriate, append one null byte to
/* keys and values.
/* When neither DICT_FLAG_TRY0NULL nor DICT_FLAG_TRY1NULL are
/* specified, the software guesses what format to use for reading;
/* and in the absence of definite information, a system-dependent
/* default is chosen for writing.
/* .IP DICT_FLAG_LOCK
/* With maps where this is appropriate, acquire an exclusive lock
/* before writing, and acquire a shared lock before reading.
/* .PP /* .PP
/* The dictionary types are as follows: /* The dictionary types are as follows:
/* .IP environ /* .IP environ
@@ -72,13 +93,14 @@
/* /*
/* dict_get() retrieves the value stored in the named dictionary /* dict_get() retrieves the value stored in the named dictionary
/* under the given key. A null pointer means the value was not found. /* under the given key. A null pointer means the value was not found.
/* This routine does not manipulate any locks.
/* /*
/* dict_put() stores the specified key and value into the named /* dict_put() stores the specified key and value into the named
/* dictionary. This routine does not manipulate any locks. /* dictionary.
/* /*
/* dict_close() closes the specified dictionary and cleans up the /* dict_close() closes the specified dictionary and cleans up the
/* associated data structures. /* associated data structures.
/*
/* dict_open_register() adds support for a new dictionary type.
/* DIAGNOSTICS /* DIAGNOSTICS
/* Fatal error: open error, unsupported dictionary type, attempt to /* Fatal error: open error, unsupported dictionary type, attempt to
/* update non-writable dictionary. /* update non-writable dictionary.
@@ -120,6 +142,7 @@
#include <dict_regexp.h> #include <dict_regexp.h>
#include <stringops.h> #include <stringops.h>
#include <split_at.h> #include <split_at.h>
#include <htable.h>
/* /*
* lookup table for available map types. * lookup table for available map types.
@@ -160,6 +183,23 @@ static DICT_OPEN_INFO dict_open_info[] = {
0, 0,
}; };
static HTABLE *dict_open_hash;
/* dict_open_init - one-off initialization */
static void dict_open_init(void)
{
char *myname = "dict_open_init";
DICT_OPEN_INFO *dp;
if (dict_open_hash != 0)
msg_panic("%s: multiple initialization", myname);
dict_open_hash = htable_create(10);
for (dp = dict_open_info; dp->type; dp++)
htable_enter(dict_open_hash, dp->type, (char *) dp);
}
/* dict_open - open dictionary */ /* dict_open - open dictionary */
DICT *dict_open(const char *dict_spec, int open_flags, int dict_flags) DICT *dict_open(const char *dict_spec, int open_flags, int dict_flags)
@@ -184,22 +224,37 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
{ {
char *myname = "dict_open"; char *myname = "dict_open";
DICT_OPEN_INFO *dp; DICT_OPEN_INFO *dp;
DICT *dict = 0; DICT *dict;
for (dp = dict_open_info; dp->type; dp++) { if (dict_open_hash == 0)
if (strcasecmp(dp->type, dict_type) == 0) { dict_open_init();
if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0) if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0)
msg_fatal("opening %s:%s %m", dict_type, dict_name);
if (msg_verbose)
msg_info("%s: %s:%s", myname, dict_type, dict_name);
break;
}
}
if (dp->type == 0)
msg_fatal("unsupported dictionary type: %s", dict_type); msg_fatal("unsupported dictionary type: %s", 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)
msg_info("%s: %s:%s", myname, dict_type, dict_name);
return (dict); return (dict);
} }
/* dict_open_register - register dictionary type */
void dict_open_register(const char *type,
DICT *(*open) (const char *, int, int))
{
char *myname = "dict_open_register";
DICT_OPEN_INFO *dp;
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);
}
#ifdef TEST #ifdef TEST
/* /*
@@ -221,6 +276,11 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
#include "msg_vstream.h" #include "msg_vstream.h"
#include "vstring_vstream.h" #include "vstring_vstream.h"
static NORETURN usage(char *myname)
{
msg_fatal("usage: %s type:file read|write|create", myname);
}
main(int argc, char **argv) main(int argc, char **argv)
{ {
VSTRING *keybuf = vstring_alloc(1); VSTRING *keybuf = vstring_alloc(1);
@@ -229,19 +289,30 @@ main(int argc, char **argv)
int open_flags; int open_flags;
char *key; char *key;
const char *value; const char *value;
int ch;
msg_vstream_init(argv[0], VSTREAM_ERR); msg_vstream_init(argv[0], VSTREAM_ERR);
if (argc != 3) while ((ch = GETOPT(argc, argv, "v")) > 0) {
msg_fatal("usage: %s type:file read|write|create", argv[0]); switch (ch) {
if (strcasecmp(argv[2], "create") == 0) default:
usage(argv[0]);
case 'v':
msg_verbose++;
break;
}
}
optind = OPTIND;
if (argc - optind != 2)
usage(argv[0]);
if (strcasecmp(argv[optind + 1], "create") == 0)
open_flags = O_CREAT | O_RDWR | O_TRUNC; open_flags = O_CREAT | O_RDWR | O_TRUNC;
else if (strcasecmp(argv[2], "write") == 0) else if (strcasecmp(argv[optind + 1], "write") == 0)
open_flags = O_RDWR; open_flags = O_RDWR;
else if (strcasecmp(argv[2], "read") == 0) else if (strcasecmp(argv[optind + 1], "read") == 0)
open_flags = O_RDONLY; open_flags = O_RDONLY;
else else
msg_fatal("unknown access mode: %s", argv[2]); msg_fatal("unknown access mode: %s", argv[2]);
dict_name = argv[1]; dict_name = argv[optind];
dict = dict_open(dict_name, open_flags, 0); dict = dict_open(dict_name, open_flags, 0);
while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) { while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) {
if ((key = strtok(vstring_str(keybuf), " =")) == 0) if ((key = strtok(vstring_str(keybuf), " =")) == 0)

View File

@@ -146,16 +146,10 @@ static const char *dict_pcre_lookup(DICT *dict, const char *name)
static VSTRING *buf; static VSTRING *buf;
char *at; char *at;
/* msg_info("dict_pcre_lookup: %s: %s", dict_pcre->map, name );*/ dict_errno = 0;
/* if (msg_verbose)
* XXX Require user@domain, to defeat partial address matching for smtp msg_info("dict_pcre_lookup: %s: %s", dict_pcre->map, name);
* access control, canonical and virtual mappings, and to prevent regexps
* from being used as alias databases because one might inadvertantly
* copy "|command" or /file/name or :include: to the result.
*/
if (name[0] == '@' || (at = strrchr(name, '@')) == 0 || at[1] == 0)
return (0);
/* Search for a matching expression */ /* Search for a matching expression */
ctxt.matches = 0; ctxt.matches = 0;

View File

@@ -139,16 +139,10 @@ static const char *dict_regexp_lookup(DICT *dict, const char *name)
char *at; char *at;
int error; int error;
/* msg_info("dict_regexp_lookup: %s: %s", dict_regexp->map, name ); */ dict_errno = 0;
/* if (msg_verbose)
* XXX Require user@domain, to defeat partial address matching for smtp msg_info("dict_regexp_lookup: %s: %s", dict_regexp->map, name);
* access control, canonical and virtual mappings, and to prevent regexps
* from being used as alias databases because one might inadvertently
* copy "|command" or /file/name or :include: to the result.
*/
if (name[0] == '@' || (at = strrchr(name, '@')) == 0 || at[1] == 0)
return (0);
/* Search for a matching expression */ /* Search for a matching expression */
for (rule = dict_regexp->head; rule; rule = rule->next) { for (rule = dict_regexp->head; rule; rule = rule->next) {

View File

@@ -110,6 +110,8 @@ DICT *dict_unix_open(const char *map, int unused_flags, int dict_flags)
}; };
struct dict_unix_lookup *lp; struct dict_unix_lookup *lp;
dict_errno = 0;
dict_unix = (DICT_UNIX *) mymalloc(sizeof(*dict_unix)); dict_unix = (DICT_UNIX *) mymalloc(sizeof(*dict_unix));
for (lp = dict_unix_lookup; /* void */ ; lp++) { for (lp = dict_unix_lookup; /* void */ ; lp++) {
if (lp->name == 0) if (lp->name == 0)

View File

@@ -109,7 +109,9 @@ static ARGV *match_list_parse(ARGV *list, char *string)
} else if (strchr(pattern, ':') != 0) { /* type:table */ } else if (strchr(pattern, ':') != 0) { /* type:table */
for (cp = pattern; *cp == '!'; cp++) for (cp = pattern; *cp == '!'; cp++)
/* void */ ; /* void */ ;
dict_register(pattern, dict_open(pattern, 0, 0)); if (dict_handle(pattern) == 0)
dict_register(pattern,
dict_open(pattern, O_RDONLY, DICT_FLAG_LOCK));
argv_add(list, pattern, (char *) 0); argv_add(list, pattern, (char *) 0);
} else { /* other pattern */ } else { /* other pattern */
argv_add(list, pattern, (char *) 0); argv_add(list, pattern, (char *) 0);

View File

@@ -484,6 +484,7 @@ extern int opterr;
#else #else
#define GETOPT(argc, argv, str) getopt((argc), (argv), (str)) #define GETOPT(argc, argv, str) getopt((argc), (argv), (str))
#endif #endif
#define OPTIND (optind > 0 ? optind : 1)
#if defined(USE_FCNTL_LOCK) && defined(USE_FLOCK_LOCK) #if defined(USE_FCNTL_LOCK) && defined(USE_FLOCK_LOCK)
#error "define USE_FCNTL_LOCK or USE_FLOCK_LOCK, not both" #error "define USE_FCNTL_LOCK or USE_FLOCK_LOCK, not both"