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
argument to control such things as warning about duplicates,
and appending null bytes to key/value. This was needed for
a clean implementation of NIS master alias maps support.
and appending null bytes to key/value. The latter was needed
for a clean implementation of NIS master alias maps support.
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:
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: ../include/argv.h
cleanup.o: ../include/maps.h
cleanup.o: ../include/dict.h
cleanup.o: ../include/tok822.h
cleanup.o: ../include/resolve_clnt.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: ../include/argv.h
cleanup_envelope.o: ../include/maps.h
cleanup_envelope.o: ../include/dict.h
cleanup_envelope.o: ../include/been_here.h
cleanup_envelope.o: ../include/mail_stream.h
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: cleanup.h
cleanup_extracted.o: ../include/maps.h
cleanup_extracted.o: ../include/dict.h
cleanup_extracted.o: ../include/tok822.h
cleanup_extracted.o: ../include/resolve_clnt.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: ../include/vstream.h
cleanup_masquerade.o: ../include/maps.h
cleanup_masquerade.o: ../include/dict.h
cleanup_masquerade.o: ../include/been_here.h
cleanup_masquerade.o: ../include/mail_stream.h
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: cleanup.h
cleanup_message.o: ../include/maps.h
cleanup_message.o: ../include/dict.h
cleanup_message.o: ../include/been_here.h
cleanup_message.o: ../include/mail_stream.h
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: ../include/argv.h
cleanup_out.o: ../include/maps.h
cleanup_out.o: ../include/dict.h
cleanup_out.o: ../include/tok822.h
cleanup_out.o: ../include/resolve_clnt.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/vstream.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/resolve_clnt.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/argv.h
cleanup_rewrite.o: ../include/maps.h
cleanup_rewrite.o: ../include/dict.h
cleanup_rewrite.o: ../include/been_here.h
cleanup_rewrite.o: ../include/mail_stream.h
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: ../include/argv.h
cleanup_skip.o: ../include/maps.h
cleanup_skip.o: ../include/dict.h
cleanup_skip.o: ../include/tok822.h
cleanup_skip.o: ../include/resolve_clnt.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: ../include/argv.h
cleanup_state.o: ../include/maps.h
cleanup_state.o: ../include/dict.h
cleanup_state.o: ../include/tok822.h
cleanup_state.o: ../include/resolve_clnt.h
cleanup_state.o: ../include/mail_stream.h

View File

@@ -375,15 +375,18 @@ static void pre_jail_init(void)
{
if (*var_canonical_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)
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)
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)
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)
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.
*
* 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
&& bare_key != 0 && (result = maps_find(path, bare_key)) != 0
#define FULL 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 = saved_ext;
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
|| resolve_local(ratsign + 1))) {
*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 ((ratsign = strrchr(bare_key, '@')) == 0)
msg_panic("%s: bare key botch", myname);
*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;
saved_ext = 0;
}
@@ -161,7 +167,7 @@ const char *mail_addr_find(MAPS *path, const char *address, char **extp)
* Try @domain.
*/
if (result == 0 && dict_errno == 0 && ratsign)
result = maps_find(path, ratsign);
result = maps_find(path, ratsign, PARTIAL);
/*
* Clean up.
@@ -202,18 +208,19 @@ int main(int argc, char **argv)
*/
if (argc != 2)
msg_fatal("usage: %s database", argv[0]);
msg_verbose = 1;
/*
* Initialize.
*/
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)) {
extent = 0;
result = mail_addr_find(path, STR(buffer), &extent);
vstream_printf("%s -> %s (%s)\n", STR(buffer), result ? result :
dict_errno ? "(try again)" :
"(not found)", extent ? extent : "null");
"(not found)", extent ? extent : "null extension");
vstream_fflush(VSTREAM_OUT);
if (extent)
myfree(extent);

View File

@@ -159,7 +159,7 @@ int main(int argc, char **argv)
msg_verbose = 1;
if (chdir(var_queue_dir) < 0)
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)) {
if ((result = mail_addr_map(path, STR(buffer))) != 0)
argv_free(result);

View File

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

View File

@@ -28,7 +28,7 @@
/* named dictionaries.
/* The result is a handle that must be specified along with all
/* 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
/* in the specified order for the named key. The result is in
@@ -102,7 +102,7 @@
/* 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 *temp = mystrdup(map_names);
@@ -127,7 +127,10 @@ MAPS *maps_create(const char *title, const char *map_names)
if (msg_verbose)
msg_info("%s: %s", myname, map_type_name);
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);
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 */
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 **map_name;
const char *expansion;
DICT *dict;
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)
msg_info("%s: %s: %s = %s", myname, *map_name, name, expansion);
return (expansion);
@@ -191,10 +199,10 @@ main(int argc, char **argv)
if (argc != 2)
msg_fatal("usage: %s maps", argv[0]);
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)) {
if ((result = maps_find(maps, vstring_str(buf))) != 0) {
if ((result = maps_find(maps, vstring_str(buf), 0)) != 0) {
vstream_printf("%s\n", result);
} else if (dict_errno != 0) {
msg_fatal("lookup error: %m");

View File

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

View File

@@ -142,7 +142,7 @@ int deliver_alias(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
* Do this only once.
*/
if (maps == 0)
maps = maps_create("aliases", var_alias_maps);
maps = maps_create("aliases", var_alias_maps, DICT_FLAG_LOCK);
/*
* 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)))
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);
SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
} else {

View File

@@ -76,6 +76,7 @@ qmgr.o: ../include/mail_server.h
qmgr.o: qmgr.h
qmgr.o: ../include/scan_dir.h
qmgr.o: ../include/maps.h
qmgr.o: ../include/dict.h
qmgr_active.o: qmgr_active.c
qmgr_active.o: ../include/sys_defs.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: ../include/scan_dir.h
qmgr_active.o: ../include/maps.h
qmgr_active.o: ../include/dict.h
qmgr_bounce.o: qmgr_bounce.c
qmgr_bounce.o: ../include/sys_defs.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: ../include/scan_dir.h
qmgr_bounce.o: ../include/maps.h
qmgr_bounce.o: ../include/dict.h
qmgr_defer.o: qmgr_defer.c
qmgr_defer.o: ../include/sys_defs.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: ../include/scan_dir.h
qmgr_defer.o: ../include/maps.h
qmgr_defer.o: ../include/dict.h
qmgr_deliver.o: qmgr_deliver.c
qmgr_deliver.o: ../include/sys_defs.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: ../include/scan_dir.h
qmgr_deliver.o: ../include/maps.h
qmgr_deliver.o: ../include/dict.h
qmgr_enable.o: qmgr_enable.c
qmgr_enable.o: ../include/sys_defs.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: ../include/scan_dir.h
qmgr_enable.o: ../include/maps.h
qmgr_enable.o: ../include/dict.h
qmgr_entry.o: qmgr_entry.c
qmgr_entry.o: ../include/sys_defs.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: ../include/scan_dir.h
qmgr_entry.o: ../include/maps.h
qmgr_entry.o: ../include/dict.h
qmgr_message.o: qmgr_message.c
qmgr_message.o: ../include/sys_defs.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: qmgr.h
qmgr_move.o: ../include/maps.h
qmgr_move.o: ../include/dict.h
qmgr_queue.o: qmgr_queue.c
qmgr_queue.o: ../include/sys_defs.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/scan_dir.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: ../include/sys_defs.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/scan_dir.h
qmgr_rcpt_list.o: ../include/maps.h
qmgr_rcpt_list.o: ../include/dict.h
qmgr_scan.o: qmgr_scan.c
qmgr_scan.o: ../include/sys_defs.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/vbuf.h
qmgr_scan.o: ../include/maps.h
qmgr_scan.o: ../include/dict.h
qmgr_transport.o: qmgr_transport.c
qmgr_transport.o: ../include/sys_defs.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: ../include/scan_dir.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)
{
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)
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 */

View File

@@ -478,7 +478,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
&& qmgr_virtual != 0
&& (at = strrchr(recipient->address, '@')) != 0) {
domain = lowercase(mystrdup(at + 1));
junk = maps_find(qmgr_virtual, domain);
junk = maps_find(qmgr_virtual, domain, 0);
myfree(domain);
if (junk) {
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) {
argv_add(argv, name, (char *) 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);
@@ -877,33 +877,42 @@ static int check_table_result(SMTPD_STATE *state, char *table,
/* 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 *low_name = lowercase(mystrdup(name));
const char *value;
DICT *dict;
#define CHK_ACCESS_RETURN(x) { myfree(low_name); return(x); }
#define FULL 0
#define PARTIAL DICT_FLAG_FIXED
if (msg_verbose)
msg_info("%s: %s", myname, name);
if ((value = dict_lookup(table, low_name)) != 0)
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
if (flags == 0 || (flags & dict->flags) != 0) {
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);
}
/* 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 *low_domain = lowercase(mystrdup(domain));
char *name;
char *next;
const char *value;
DICT *dict;
if (msg_verbose)
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); }
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));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
flags = PARTIAL;
}
CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO);
}
/* 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 *addr;
const char *value;
DICT *dict;
if (msg_verbose)
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));
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));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
flags = PARTIAL;
} while (split_at_right(addr, '.'));
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 */
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";
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
* 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);
/*
* 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);
/*
@@ -1008,13 +1029,13 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr)
/*
* 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);
/*
* 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);
/*
@@ -1022,7 +1043,7 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr)
*/
local_at = mystrndup(STR(reply.recipient),
ratsign - STR(reply.recipient) + 1);
status = check_access(state, table, local_at);
status = check_access(state, table, local_at, PARTIAL);
myfree(local_at);
if (status != 0)
return (status);
@@ -1147,7 +1168,7 @@ static int generic_checks(SMTPD_STATE *state, char *name,
return (1);
}
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);
}
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 (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);
}
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++) {
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) {
msg_warn("unknown %s check: \"%s\"", VAR_CLIENT_CHECKS, name);
break;
@@ -1271,7 +1292,7 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
state->helo_name = mystrdup(helohost);
for (cpp = helo_restrctions->argv; (name = *cpp) != 0; cpp++) {
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) {
msg_warn("unknown %s check: \"%s\"", VAR_HELO_CHECKS, name);
break;
@@ -1381,9 +1402,9 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
*/
for (cpp = etrn_restrctions->argv; (name = *cpp) != 0; cpp++) {
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)) {
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) {
msg_warn("unknown %s check: \"%s\"", VAR_RCPT_CHECKS, name);
break;

View File

@@ -75,7 +75,8 @@ void transport_init(void)
{
if (transport_path)
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 */
@@ -90,6 +91,11 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
char *transport;
int found = 0;
#define FULL 0
#define PARTIAL DICT_FLAG_FIXED
int maps_flag = FULL;
if (transport_path == 0)
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
* 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, '.')) {
if ((value = maps_find(transport_path, name)) != 0) {
if ((value = maps_find(transport_path, name, maps_flag)) != 0) {
saved_value = mystrdup(value);
if ((host = split_at(saved_value, ':')) == 0 || *host == 0)
host = domain;
@@ -119,6 +128,7 @@ int transport_lookup(const char *domain, VSTRING *channel, VSTRING *nexthop)
} else if (dict_errno != 0) {
msg_fatal("transport table lookup problem");
}
maps_flag = PARTIAL;
}
myfree(low_domain);
return (found);

View File

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

View File

@@ -78,20 +78,11 @@
/*
/* dict_update() updates the value of the named dictionary member.
/* The dictionary member and the named dictionary are instantiated
/* on the fly. During the update, a file-based dictionary is locked
/* 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.
/* on the fly.
/*
/* dict_lookup() returns the value of the named member (i.e. without
/* expanding macros in the member value). The \fIdict_name\fR argument
/* specifies the dictionary to search. The dictionary is locked for
/* shared access, when it is file based. The result is a null pointer
/* specifies the dictionary to search. The result is a null pointer
/* when no value is found, otherwise the result is owned by the
/* underlying dictionary method. Make a copy if the result is to be
/* modified, or if the result is to survive multiple dict_lookup() calls.
@@ -149,7 +140,6 @@
#include "vstream.h"
#include "vstring.h"
#include "readline.h"
#include "myflock.h"
#include "mac_parse.h"
#include "dict.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;
if (msg_verbose > 1)
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);
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 */
@@ -268,18 +254,12 @@ const char *dict_lookup(const char *dict_name, const char *member)
DICT *dict;
const char *ret = 0;
dict_errno = 0;
if ((node = dict_node(dict_name)) == 0) {
if (dict_unknown_allowed == 0)
msg_fatal("%s: unknown dictionary: %s", myname, dict_name);
} else {
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);
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)
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_FIXED (1<<4) /* fixed key map */
#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_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_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_put(dp, key, val) (dp)->update((dp), (key), (val))
#define dict_close(dp) (dp)->close(dp)

View File

@@ -63,6 +63,7 @@
#include "vstring.h"
#include "stringops.h"
#include "iostuff.h"
#include "myflock.h"
#include "dict.h"
#include "dict_db.h"
@@ -70,7 +71,6 @@
typedef struct {
DICT dict; /* generic members */
int flags; /* see below */
DB *db; /* open db file */
char *path; /* pathname */
} DICT_DB;
@@ -88,19 +88,28 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
DBT db_value;
int status;
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
* value.
*/
if (dict_db->flags & DICT_FLAG_TRY1NULL) {
if (dict->flags & DICT_FLAG_TRY1NULL) {
db_key.data = (void *) name;
db_key.size = strlen(name) + 1;
if ((status = db->get(db, &db_key, &db_value, 0)) < 0)
msg_fatal("error reading %s: %m", dict_db->path);
if (status == 0) {
dict_db->flags &= ~DICT_FLAG_TRY0NULL;
return (db_value.data);
dict->flags &= ~DICT_FLAG_TRY0NULL;
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
* value.
*/
if (dict_db->flags & DICT_FLAG_TRY0NULL) {
if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
db_key.data = (void *) name;
db_key.size = strlen(name);
if ((status = db->get(db, &db_key, &db_value, 0)) < 0)
@@ -117,11 +126,18 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
if (buf == 0)
buf = vstring_alloc(10);
vstring_strncpy(buf, db_value.data, db_value.size);
dict_db->flags &= ~DICT_FLAG_TRY1NULL;
return (vstring_str(buf));
dict->flags &= ~DICT_FLAG_TRY1NULL;
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 */
@@ -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
* default depending on the platform.
*/
if ((dict_db->flags & DICT_FLAG_TRY1NULL)
&& (dict_db->flags & DICT_FLAG_TRY0NULL)) {
if ((dict->flags & DICT_FLAG_TRY1NULL)
&& (dict->flags & DICT_FLAG_TRY0NULL)) {
#ifdef DB_NO_TRAILING_NULL
dict_db->flags = DICT_FLAG_TRY0NULL;
dict->flags &= ~DICT_FLAG_TRY1NULL;
dict->flags |= DICT_FLAG_TRY0NULL;
#else
dict_db->flags = DICT_FLAG_TRY1NULL;
dict->flags &= ~DICT_FLAG_TRY0NULL;
dict->flags |= DICT_FLAG_TRY1NULL;
#endif
}
/*
* 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_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.
*/
@@ -173,6 +197,12 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
else
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 */
@@ -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));
}
/**INDENT** Error@188: Unmatched #endif */
#endif

View File

@@ -46,6 +46,7 @@
#include "htable.h"
#include "iostuff.h"
#include "vstring.h"
#include "myflock.h"
#include "dict.h"
#include "dict_dbm.h"
@@ -53,7 +54,6 @@
typedef struct {
DICT dict; /* generic members */
int flags; /* see below */
DBM *dbm; /* open database */
char *path; /* pathname */
} DICT_DBM;
@@ -66,18 +66,27 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
datum dbm_key;
datum dbm_value;
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
* and value.
*/
if (dict_dbm->flags & DICT_FLAG_TRY1NULL) {
if (dict->flags & DICT_FLAG_TRY1NULL) {
dbm_key.dptr = (void *) name;
dbm_key.dsize = strlen(name) + 1;
dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
if (dbm_value.dptr != 0) {
dict_dbm->flags &= ~DICT_FLAG_TRY0NULL;
return (dbm_value.dptr);
dict->flags &= ~DICT_FLAG_TRY0NULL;
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
* value.
*/
if (dict_dbm->flags & DICT_FLAG_TRY0NULL) {
if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
dbm_key.dptr = (void *) name;
dbm_key.dsize = strlen(name);
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)
buf = vstring_alloc(10);
vstring_strncpy(buf, dbm_value.dptr, dbm_value.dsize);
dict_dbm->flags &= ~DICT_FLAG_TRY1NULL;
return (vstring_str(buf));
dict->flags &= ~DICT_FLAG_TRY1NULL;
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 */
@@ -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
* default depending on the platform.
*/
if ((dict_dbm->flags & DICT_FLAG_TRY1NULL)
&& (dict_dbm->flags & DICT_FLAG_TRY0NULL)) {
if ((dict->flags & DICT_FLAG_TRY1NULL)
&& (dict->flags & DICT_FLAG_TRY0NULL)) {
#ifdef DBM_NO_TRAILING_NULL
dict_dbm->flags = DICT_FLAG_TRY0NULL;
dict->flags &= ~DICT_FLAG_TRY1NULL;
dict->flags |= DICT_FLAG_TRY0NULL;
#else
dict_dbm->flags = DICT_FLAG_TRY1NULL;
dict->flags &= ~DICT_FLAG_TRY0NULL;
dict->flags |= DICT_FLAG_TRY1NULL;
#endif
}
/*
* 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_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.
*/
@@ -148,6 +172,12 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
else
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 */

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)
{
dict_errno = 0;
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_errno = 0;
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;
void (*saved_alarm) (int);
dict_errno = 0;
/*
* Initialize.
*/

View File

@@ -79,6 +79,8 @@ static const char *dict_ni_do_lookup(char *path, char *key_prop,
ni_status r;
ni_id dir;
dict_errno = 0;
if (msg_verbose)
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)
{
dict_errno = 0;
msg_warn("dict_nisplus_lookup: NISPLUS lookup not implemented");
return (0);
}

View File

@@ -28,6 +28,10 @@
/*
/* void dict_close(dict)
/* DICT *dict;
/*
/* dict_open_register(type, open)
/* char *type;
/* DICT *(*open) (const char *, int, int);
/* DESCRIPTION
/* This module implements a low-level interface to multiple
/* physical dictionary types.
@@ -44,6 +48,23 @@
/* Ignore duplicate keys if the underlying database does not
/* support duplicate keys. The default is to terminate with a fatal
/* 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
/* The dictionary types are as follows:
/* .IP environ
@@ -72,13 +93,14 @@
/*
/* dict_get() retrieves the value stored in the named dictionary
/* 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
/* dictionary. This routine does not manipulate any locks.
/* dictionary.
/*
/* dict_close() closes the specified dictionary and cleans up the
/* associated data structures.
/*
/* dict_open_register() adds support for a new dictionary type.
/* DIAGNOSTICS
/* Fatal error: open error, unsupported dictionary type, attempt to
/* update non-writable dictionary.
@@ -120,6 +142,7 @@
#include <dict_regexp.h>
#include <stringops.h>
#include <split_at.h>
#include <htable.h>
/*
* lookup table for available map types.
@@ -160,6 +183,23 @@ static DICT_OPEN_INFO dict_open_info[] = {
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 *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";
DICT_OPEN_INFO *dp;
DICT *dict = 0;
DICT *dict;
for (dp = dict_open_info; dp->type; dp++) {
if (strcasecmp(dp->type, dict_type) == 0) {
if (dict_open_hash == 0)
dict_open_init();
if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0)
msg_fatal("unsupported dictionary type: %s", dict_type);
if ((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);
break;
}
}
if (dp->type == 0)
msg_fatal("unsupported dictionary type: %s", dict_type);
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
/*
@@ -221,6 +276,11 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
#include "msg_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)
{
VSTRING *keybuf = vstring_alloc(1);
@@ -229,19 +289,30 @@ main(int argc, char **argv)
int open_flags;
char *key;
const char *value;
int ch;
msg_vstream_init(argv[0], VSTREAM_ERR);
if (argc != 3)
msg_fatal("usage: %s type:file read|write|create", argv[0]);
if (strcasecmp(argv[2], "create") == 0)
while ((ch = GETOPT(argc, argv, "v")) > 0) {
switch (ch) {
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;
else if (strcasecmp(argv[2], "write") == 0)
else if (strcasecmp(argv[optind + 1], "write") == 0)
open_flags = O_RDWR;
else if (strcasecmp(argv[2], "read") == 0)
else if (strcasecmp(argv[optind + 1], "read") == 0)
open_flags = O_RDONLY;
else
msg_fatal("unknown access mode: %s", argv[2]);
dict_name = argv[1];
dict_name = argv[optind];
dict = dict_open(dict_name, open_flags, 0);
while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) {
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;
char *at;
/* msg_info("dict_pcre_lookup: %s: %s", dict_pcre->map, name );*/
dict_errno = 0;
/*
* XXX Require user@domain, to defeat partial address matching for smtp
* 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);
if (msg_verbose)
msg_info("dict_pcre_lookup: %s: %s", dict_pcre->map, name);
/* Search for a matching expression */
ctxt.matches = 0;

View File

@@ -139,16 +139,10 @@ static const char *dict_regexp_lookup(DICT *dict, const char *name)
char *at;
int error;
/* msg_info("dict_regexp_lookup: %s: %s", dict_regexp->map, name ); */
dict_errno = 0;
/*
* XXX Require user@domain, to defeat partial address matching for smtp
* 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);
if (msg_verbose)
msg_info("dict_regexp_lookup: %s: %s", dict_regexp->map, name);
/* Search for a matching expression */
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;
dict_errno = 0;
dict_unix = (DICT_UNIX *) mymalloc(sizeof(*dict_unix));
for (lp = dict_unix_lookup; /* void */ ; lp++) {
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 */
for (cp = pattern; *cp == '!'; cp++)
/* 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);
} else { /* other pattern */
argv_add(list, pattern, (char *) 0);

View File

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