mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
snapshot-19990329
This commit is contained in:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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");
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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");
|
||||||
|
@@ -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
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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,
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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;
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
@@ -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"
|
||||||
|
Reference in New Issue
Block a user