mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 13:18:12 +00:00
snapshot-19990327
This commit is contained in:
parent
a5534e6452
commit
702954b400
2
postfix/.indent.pro
vendored
2
postfix/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@ -2429,7 +2429,8 @@ Apologies for any names omitted.
|
||||
Workaround: Solaris NIS alias maps need special entries
|
||||
(YP_MASTER_NAME, YP_LAST_MODIFIED). What's worse, normal
|
||||
keys/values include a null byte at the end, but the YP_XXX
|
||||
ones don't. File: postalias/postalias.c.
|
||||
ones don't. Problem reported by Walcir Fontanini, state
|
||||
university of Campinas, Brazil. File: postalias/postalias.c.
|
||||
|
||||
Compatibility: Solaris NIS apparently does include a null
|
||||
byte at the end of keys and values. File: util/sys_defs.h.
|
||||
@ -2442,6 +2443,26 @@ Apologies for any names omitted.
|
||||
Bugfix: pcre didn't handle \\ right. Lamont Jones, Hewlett-
|
||||
Packard. File: util/dict_pcre.c.
|
||||
|
||||
19990326
|
||||
|
||||
Compatibility: Postfix now puts to spaces after the sender
|
||||
in a "From sender date..." header. Found by John A. Martin,
|
||||
fixed by Lamont Jones, Hewlett-Packard.
|
||||
|
||||
Bugfix: when a recipient appeared multiple times in a local
|
||||
alias or include expansion, the delivery status could be
|
||||
left uninitialized, causing the mail to be deferred and
|
||||
delivered again. File: local/recipient.c.
|
||||
|
||||
19990327
|
||||
|
||||
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.
|
||||
|
||||
Feature: POSIX regular expressions by Lamont Jones.
|
||||
|
||||
Future:
|
||||
|
||||
Planned: must be able to list the same hash table in
|
||||
|
2
postfix/bounce/.indent.pro
vendored
2
postfix/bounce/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/cleanup/.indent.pro
vendored
2
postfix/cleanup/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
17
postfix/conf/sample-regexp.cf
Normal file
17
postfix/conf/sample-regexp.cf
Normal file
@ -0,0 +1,17 @@
|
||||
# Sample regexp lookup "table".
|
||||
#
|
||||
# Format is /regexp/flags or /regexp/flags!/regexp/flags
|
||||
# where regexp is a regular expression as found in regexp(5), and flags are
|
||||
# i: toggle ignore case (REG_ICASE - default is to ignore case)
|
||||
# x: toggle extended expression (REG_EXTENDED - default is extended)
|
||||
# m: toggle multiline mode (REG_NEWLINE - default is non-multiline mode)
|
||||
#
|
||||
# In order for a line to match, the first regexp must match, and the
|
||||
# second (if present) must not match. The first matching line wins,
|
||||
# terminating processing of the ruleset.
|
||||
|
||||
# Postmaster is OK, that way they can talk to us about how to fix their problem.
|
||||
/^postmaster@.*$/ OK
|
||||
|
||||
# Protect your outgoing majordomo exploders
|
||||
/^(.*)-outgoing@(.*)$/!/^owner-.*/ 550 Use ${1}@${2} instead
|
2
postfix/dns/.indent.pro
vendored
2
postfix/dns/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/fsstone/.indent.pro
vendored
2
postfix/fsstone/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/global/.indent.pro
vendored
2
postfix/global/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Version of this program.
|
||||
*/
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "Snapshot-19990325"
|
||||
#define DEF_MAIL_VERSION "Snapshot-19990327"
|
||||
extern char *var_mail_version;
|
||||
|
||||
/* LICENSE
|
||||
|
@ -121,7 +121,7 @@ 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);
|
||||
dict = dict_open(map_type_name, O_RDONLY, 0);
|
||||
dict_register(map_type_name, dict);
|
||||
argv_add(maps->argv, map_type_name, ARGV_END);
|
||||
}
|
||||
|
@ -11,18 +11,23 @@
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <dict.h>
|
||||
|
||||
/*
|
||||
* A database handle is an opaque structure. The user is not supposed to
|
||||
* know its implementation.
|
||||
*/
|
||||
typedef struct MKMAP {
|
||||
struct DICT *(*open) (const char *, int);
|
||||
struct DICT *(*open) (const char *, int, int);
|
||||
struct DICT *dict;
|
||||
char *lock_file;
|
||||
int lock_fd;
|
||||
} MKMAP;
|
||||
|
||||
extern MKMAP *mkmap_open(const char *, const char *, int);
|
||||
extern MKMAP *mkmap_open(const char *, const char *, int, int);
|
||||
extern void mkmap_append(MKMAP *, const char *, const char *);
|
||||
extern void mkmap_close(MKMAP *);
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
||||
/* mkmap_db_open - create or open database */
|
||||
|
||||
static MKMAP *mkmap_db_open(const char *path,
|
||||
DICT *(*db_open) (const char *, int))
|
||||
DICT *(*db_open) (const char *, int, int))
|
||||
{
|
||||
MKMAP *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
|
||||
|
||||
|
@ -6,10 +6,11 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <mkmap.h>
|
||||
/*
|
||||
/* MKMAP *mkmap_open(type, path, flags)
|
||||
/* MKMAP *mkmap_open(type, path, open_flags, dict_flags)
|
||||
/* char *type;
|
||||
/* char *path;
|
||||
/* int flags;
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/*
|
||||
/* void mkmap_append(mkmap, key, value, lineno)
|
||||
/* MKMAP *mkmap;
|
||||
@ -26,11 +27,13 @@
|
||||
/* appending the appropriate suffixes to the specified filename.
|
||||
/* Before the database is updated, it is locked for exclusive
|
||||
/* access, and signal delivery is suspended.
|
||||
/* See dict(3) for a description of \fBopen_flags\fR and \fBdict_flags\fR.
|
||||
/* All errors are fatal.
|
||||
/*
|
||||
/* mkmap_append() appends the named (key, value) pair to the
|
||||
/* database. Update errors are fatal; duplicate keys are ignored
|
||||
/* (but a warning is issued).
|
||||
/* \fBlineno\fR is used for diagnostics.
|
||||
/*
|
||||
/* mkmap_close() closes the database, releases any locks,
|
||||
/* and resumes signal delivery. All errors are fatal.
|
||||
@ -118,7 +121,8 @@ void mkmap_close(MKMAP *mkmap)
|
||||
|
||||
/* mkmap_open - create or truncate database */
|
||||
|
||||
MKMAP *mkmap_open(const char *type, const char *path, int flags)
|
||||
MKMAP *mkmap_open(const char *type, const char *path,
|
||||
int open_flags, int dict_flags)
|
||||
{
|
||||
MKMAP *mkmap;
|
||||
MKMAP_OPEN_INFO *mp;
|
||||
@ -157,7 +161,7 @@ MKMAP *mkmap_open(const char *type, const char *path, int flags)
|
||||
* Truncate the database upon open, and update it. Read-write mode is
|
||||
* needed because the underlying routines read as well as write.
|
||||
*/
|
||||
mkmap->dict = mkmap->open(path, flags);
|
||||
mkmap->dict = mkmap->open(path, open_flags, dict_flags);
|
||||
mkmap->dict->fd = -1; /* XXX just in case */
|
||||
mkmap->dict->flags |= DICT_FLAG_DUP_WARN;
|
||||
return (mkmap);
|
||||
|
2
postfix/local/.indent.pro
vendored
2
postfix/local/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@ -102,6 +102,9 @@ static void dotforward_parse_callback(int type, VSTRING *buf, char *context)
|
||||
FW_CONTEXT *fw_context = (FW_CONTEXT *) context;
|
||||
char *ptr;
|
||||
|
||||
if (fw_context->failures)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Find out what data to substitute.
|
||||
*/
|
||||
|
@ -91,7 +91,7 @@
|
||||
static int deliver_switch(LOCAL_STATE state, USER_ATTR usr_attr)
|
||||
{
|
||||
char *myname = "deliver_switch";
|
||||
int status;
|
||||
int status = 0;
|
||||
|
||||
/*
|
||||
* Make verbose logging easier to understand.
|
||||
|
2
postfix/master/.indent.pro
vendored
2
postfix/master/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/pickup/.indent.pro
vendored
2
postfix/pickup/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/pipe/.indent.pro
vendored
2
postfix/pipe/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postalias/.indent.pro
vendored
2
postfix/postalias/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@ -70,3 +70,4 @@ postalias.o: ../include/resolve_clnt.h
|
||||
postalias.o: ../include/config.h
|
||||
postalias.o: ../include/mail_params.h
|
||||
postalias.o: ../include/mkmap.h
|
||||
postalias.o: ../include/dict.h
|
||||
|
@ -121,7 +121,8 @@
|
||||
|
||||
/* postalias - create or update alias database */
|
||||
|
||||
static void postalias(char *map_type, char *path_name, int incremental)
|
||||
static void postalias(char *map_type, char *path_name,
|
||||
int open_flags, int dict_flags)
|
||||
{
|
||||
VSTREAM *source_fp;
|
||||
VSTRING *line_buffer;
|
||||
@ -140,7 +141,7 @@ static void postalias(char *map_type, char *path_name, int incremental)
|
||||
line_buffer = vstring_alloc(100);
|
||||
key_buffer = vstring_alloc(100);
|
||||
value_buffer = vstring_alloc(100);
|
||||
if (incremental) {
|
||||
if ((open_flags & O_TRUNC) == 0) {
|
||||
source_fp = VSTREAM_IN;
|
||||
vstream_control(source_fp, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END);
|
||||
} else if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0) {
|
||||
@ -151,8 +152,7 @@ static void postalias(char *map_type, char *path_name, int incremental)
|
||||
* Open the database, create it when it does not exist, truncate it when
|
||||
* it does exist, and lock out any spectators.
|
||||
*/
|
||||
mkmap = mkmap_open(map_type, path_name, incremental ?
|
||||
O_RDWR | O_CREAT : O_RDWR | O_CREAT | O_TRUNC);
|
||||
mkmap = mkmap_open(map_type, path_name, open_flags, dict_flags);
|
||||
|
||||
/*
|
||||
* Add records to the database.
|
||||
@ -245,8 +245,12 @@ static void postalias(char *map_type, char *path_name, int incremental)
|
||||
mkmap_append(mkmap, "@", "@");
|
||||
|
||||
/*
|
||||
* NIS compatibility: add time and master info.
|
||||
* NIS compatibility: add time and master info. Unlike other information,
|
||||
* this information MUST be written without a trailing null appended to
|
||||
* key or value.
|
||||
*/
|
||||
mkmap->dict->flags &= ~DICT_FLAG_TRY1NULL;
|
||||
mkmap->dict->flags |= DICT_FLAG_TRY0NULL;
|
||||
vstring_sprintf(value_buffer, "%010ld", (long) time((time_t *) 0));
|
||||
mkmap_append(mkmap, "YP_LAST_MODIFIED", STR(value_buffer));
|
||||
mkmap_append(mkmap, "YP_MASTER_NAME", get_hostname());
|
||||
@ -270,7 +274,7 @@ static void postalias(char *map_type, char *path_name, int incremental)
|
||||
|
||||
static NORETURN usage(char *myname)
|
||||
{
|
||||
msg_fatal("usage: %s [-c config_directory] [-i] [-v] [output_type:]file...",
|
||||
msg_fatal("usage: %s [-c config_directory] [-i] [-v] [-w] [output_type:]file...",
|
||||
myname);
|
||||
}
|
||||
|
||||
@ -281,7 +285,8 @@ int main(int argc, char **argv)
|
||||
int fd;
|
||||
char *slash;
|
||||
struct stat st;
|
||||
int incremental = 0;
|
||||
int open_flags = O_RDWR | O_CREAT | O_TRUNC;
|
||||
int dict_flags = DICT_FLAG_DUP_WARN;
|
||||
|
||||
/*
|
||||
* Be consistent with file permissions.
|
||||
@ -316,7 +321,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Parse JCL.
|
||||
*/
|
||||
while ((ch = GETOPT(argc, argv, "c:iv")) > 0) {
|
||||
while ((ch = GETOPT(argc, argv, "c:ivw")) > 0) {
|
||||
switch (ch) {
|
||||
default:
|
||||
usage(argv[0]);
|
||||
@ -326,11 +331,15 @@ int main(int argc, char **argv)
|
||||
msg_fatal("out of memory");
|
||||
break;
|
||||
case 'i':
|
||||
incremental = 1;
|
||||
open_flags &= ~O_TRUNC;
|
||||
break;
|
||||
case 'v':
|
||||
msg_verbose++;
|
||||
break;
|
||||
case 'w':
|
||||
dict_flags &= ~DICT_FLAG_DUP_WARN;
|
||||
dict_flags |= DICT_FLAG_DUP_IGNORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_config();
|
||||
@ -343,9 +352,9 @@ int main(int argc, char **argv)
|
||||
usage(argv[0]);
|
||||
while (optind < argc) {
|
||||
if ((path_name = split_at(argv[optind], ':')) != 0) {
|
||||
postalias(argv[optind], path_name, incremental);
|
||||
postalias(argv[optind], path_name, open_flags, dict_flags);
|
||||
} else {
|
||||
postalias(var_db_type, argv[optind], incremental);
|
||||
postalias(var_db_type, argv[optind], open_flags, dict_flags);
|
||||
}
|
||||
optind++;
|
||||
}
|
||||
|
2
postfix/postcat/.indent.pro
vendored
2
postfix/postcat/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postconf/.indent.pro
vendored
2
postfix/postconf/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postdrop/.indent.pro
vendored
2
postfix/postdrop/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postfix/.indent.pro
vendored
2
postfix/postfix/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postkick/.indent.pro
vendored
2
postfix/postkick/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postlock/.indent.pro
vendored
2
postfix/postlock/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postlog/.indent.pro
vendored
2
postfix/postlog/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/postmap/.indent.pro
vendored
2
postfix/postmap/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@ -67,3 +67,4 @@ postmap.o: ../include/split_at.h
|
||||
postmap.o: ../include/config.h
|
||||
postmap.o: ../include/mail_params.h
|
||||
postmap.o: ../include/mkmap.h
|
||||
postmap.o: ../include/dict.h
|
||||
|
@ -130,7 +130,8 @@
|
||||
|
||||
/* postmap - create or update mapping database */
|
||||
|
||||
static void postmap(char *map_type, char *path_name, int incremental)
|
||||
static void postmap(char *map_type, char *path_name,
|
||||
int open_flags, int dict_flags)
|
||||
{
|
||||
VSTREAM *source_fp;
|
||||
VSTRING *line_buffer;
|
||||
@ -143,7 +144,7 @@ static void postmap(char *map_type, char *path_name, int incremental)
|
||||
* Initialize.
|
||||
*/
|
||||
line_buffer = vstring_alloc(100);
|
||||
if (incremental) {
|
||||
if ((open_flags & O_TRUNC) == 0) {
|
||||
source_fp = VSTREAM_IN;
|
||||
vstream_control(source_fp, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END);
|
||||
} else if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0) {
|
||||
@ -151,11 +152,11 @@ static void postmap(char *map_type, char *path_name, int incremental)
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the database, create it when it does not exist, truncate it when
|
||||
* it does exist, and lock out any spectators.
|
||||
* Open the database, optionally create it when it does not exist,
|
||||
* optionally truncate it when it does exist, and lock out any
|
||||
* spectators.
|
||||
*/
|
||||
mkmap = mkmap_open(map_type, path_name, incremental ?
|
||||
O_RDWR | O_CREAT : O_RDWR | O_CREAT | O_TRUNC);
|
||||
mkmap = mkmap_open(map_type, path_name, open_flags, dict_flags);
|
||||
|
||||
/*
|
||||
* Add records to the database.
|
||||
@ -227,7 +228,7 @@ static void postmap(char *map_type, char *path_name, int incremental)
|
||||
|
||||
static NORETURN usage(char *myname)
|
||||
{
|
||||
msg_fatal("usage: %s [-c config_directory] [-i] [-v] [output_type:]file...",
|
||||
msg_fatal("usage: %s [-c config_directory] [-i] [-v] [-w] [output_type:]file...",
|
||||
myname);
|
||||
}
|
||||
|
||||
@ -238,7 +239,8 @@ int main(int argc, char **argv)
|
||||
int fd;
|
||||
char *slash;
|
||||
struct stat st;
|
||||
int incremental = 0;
|
||||
int open_flags = O_RDWR | O_CREAT | O_TRUNC;
|
||||
int dict_flags = DICT_FLAG_DUP_WARN;
|
||||
|
||||
/*
|
||||
* Be consistent with file permissions.
|
||||
@ -273,7 +275,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Parse JCL.
|
||||
*/
|
||||
while ((ch = GETOPT(argc, argv, "c:iv")) > 0) {
|
||||
while ((ch = GETOPT(argc, argv, "c:ivw")) > 0) {
|
||||
switch (ch) {
|
||||
default:
|
||||
usage(argv[0]);
|
||||
@ -283,11 +285,15 @@ int main(int argc, char **argv)
|
||||
msg_fatal("out of memory");
|
||||
break;
|
||||
case 'i':
|
||||
incremental = 1;
|
||||
open_flags &= ~O_TRUNC;
|
||||
break;
|
||||
case 'v':
|
||||
msg_verbose++;
|
||||
break;
|
||||
case 'w':
|
||||
dict_flags &= ~DICT_FLAG_DUP_WARN;
|
||||
dict_flags |= DICT_FLAG_DUP_IGNORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_config();
|
||||
@ -300,9 +306,9 @@ int main(int argc, char **argv)
|
||||
usage(argv[0]);
|
||||
while (optind < argc) {
|
||||
if ((path_name = split_at(argv[optind], ':')) != 0) {
|
||||
postmap(argv[optind], path_name, incremental);
|
||||
postmap(argv[optind], path_name, open_flags, dict_flags);
|
||||
} else {
|
||||
postmap(var_db_type, argv[optind], incremental);
|
||||
postmap(var_db_type, argv[optind], open_flags, dict_flags);
|
||||
}
|
||||
optind++;
|
||||
}
|
||||
|
2
postfix/postsuper/.indent.pro
vendored
2
postfix/postsuper/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/qmgr/.indent.pro
vendored
2
postfix/qmgr/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/sendmail/.indent.pro
vendored
2
postfix/sendmail/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/showq/.indent.pro
vendored
2
postfix/showq/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/smtp/.indent.pro
vendored
2
postfix/smtp/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/smtpd/.indent.pro
vendored
2
postfix/smtpd/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@ -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));
|
||||
dict_register(name, dict_open(name, 0, 0));
|
||||
}
|
||||
argv_terminate(argv);
|
||||
|
||||
|
2
postfix/smtpstone/.indent.pro
vendored
2
postfix/smtpstone/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/trivial-rewrite/.indent.pro
vendored
2
postfix/trivial-rewrite/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
2
postfix/util/.indent.pro
vendored
2
postfix/util/.indent.pro
vendored
@ -27,6 +27,8 @@
|
||||
-TDICT_NODE
|
||||
-TDICT_OPEN_INFO
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_LINE
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@ -19,7 +19,7 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
|
||||
unsafe.c username.c valid_hostname.c vbuf.c vbuf_print.c \
|
||||
vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \
|
||||
write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
|
||||
stream_connect.c stream_trigger.c
|
||||
stream_connect.c stream_trigger.c dict_regexp.c
|
||||
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
|
||||
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
|
||||
dict_env.o dict_ht.o dict_ldap.o dict_ni.o dict_nis.o \
|
||||
@ -40,7 +40,7 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
|
||||
unsafe.o username.o valid_hostname.o vbuf.o vbuf_print.o \
|
||||
vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \
|
||||
write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
|
||||
stream_connect.o stream_trigger.o
|
||||
stream_connect.o stream_trigger.o dict_regexp.o
|
||||
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
|
||||
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_ni.h dict_nis.h \
|
||||
dict_nisplus.h dir_forest.h events.h exec_command.h find_inet.h \
|
||||
@ -54,7 +54,7 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
|
||||
sigdelay.h split_at.h stat_as.h stringops.h sys_defs.h \
|
||||
timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \
|
||||
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
|
||||
dict_unix.h dict_pcre.h
|
||||
dict_unix.h dict_pcre.h dict_regexp.h
|
||||
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
|
||||
stream_test.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
@ -364,10 +364,24 @@ dict_open.o: dict_nisplus.h
|
||||
dict_open.o: dict_ni.h
|
||||
dict_open.o: dict_ldap.h
|
||||
dict_open.o: dict_pcre.h
|
||||
dict_open.o: dict_regexp.h
|
||||
dict_open.o: stringops.h
|
||||
dict_open.o: split_at.h
|
||||
dict_pcre.o: dict_pcre.c
|
||||
dict_pcre.o: sys_defs.h
|
||||
dict_regexp.o: dict_regexp.c
|
||||
dict_regexp.o: sys_defs.h
|
||||
dict_regexp.o: mymalloc.h
|
||||
dict_regexp.o: msg.h
|
||||
dict_regexp.o: safe.h
|
||||
dict_regexp.o: vstream.h
|
||||
dict_regexp.o: vbuf.h
|
||||
dict_regexp.o: vstring.h
|
||||
dict_regexp.o: stringops.h
|
||||
dict_regexp.o: readline.h
|
||||
dict_regexp.o: dict.h
|
||||
dict_regexp.o: dict_regexp.h
|
||||
dict_regexp.o: mac_parse.h
|
||||
dict_unix.o: dict_unix.c
|
||||
dict_unix.o: sys_defs.h
|
||||
dict_unix.o: msg.h
|
||||
@ -622,6 +636,7 @@ percentm.o: vbuf.h
|
||||
percentm.o: percentm.h
|
||||
posix_signals.o: posix_signals.c
|
||||
posix_signals.o: sys_defs.h
|
||||
posix_signals.o: posix_signals.h
|
||||
printable.o: printable.c
|
||||
printable.o: sys_defs.h
|
||||
printable.o: stringops.h
|
||||
|
@ -35,6 +35,8 @@ typedef struct DICT {
|
||||
|
||||
#define DICT_FLAG_DUP_WARN (1<<0) /* if file, warn about dups */
|
||||
#define DICT_FLAG_DUP_IGNORE (1<<1) /* if file, ignore dups */
|
||||
#define DICT_FLAG_TRY0NULL (1<<2) /* do not append 0 to key/value */
|
||||
#define DICT_FLAG_TRY1NULL (1<<3) /* append 0 to key/value */
|
||||
|
||||
extern int dict_unknown_allowed;
|
||||
extern int dict_errno;
|
||||
@ -58,8 +60,8 @@ extern const char *dict_eval(const char *, const char *, int);
|
||||
* Low-level interface, with physical dictionary handles and no implied
|
||||
* locking.
|
||||
*/
|
||||
extern DICT *dict_open(const char *, int);
|
||||
extern DICT *dict_open3(const char *, const char *, int);
|
||||
extern DICT *dict_open(const char *, int, int);
|
||||
extern DICT *dict_open3(const char *, const char *, int, int);
|
||||
|
||||
#define dict_get(dp, key) (dp)->lookup((dp), (key))
|
||||
#define dict_put(dp, key, val) (dp)->update((dp), (key), (val))
|
||||
|
@ -6,13 +6,15 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_db.h>
|
||||
/*
|
||||
/* DICT *dict_hash_open(path, flags)
|
||||
/* DICT *dict_hash_open(path, open_flags, dict_flags)
|
||||
/* const char *path;
|
||||
/* int flags;
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/*
|
||||
/* DICT *dict_btree_open(path, flags)
|
||||
/* DICT *dict_btree_open(path, open_flags, dict_flags)
|
||||
/* const char *path;
|
||||
/* int flags;
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_XXX_open() opens the specified DB database. The result is
|
||||
/* a pointer to a structure that can be used to access the dictionary
|
||||
@ -21,8 +23,10 @@
|
||||
/* Arguments:
|
||||
/* .IP path
|
||||
/* The database pathname, not including the ".db" suffix.
|
||||
/* .IP flags
|
||||
/* flags passed to dbopen().
|
||||
/* .IP open_flags
|
||||
/* Flags passed to dbopen().
|
||||
/* .IP dict_flags
|
||||
/* Flags used by the dictionary interface.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* DIAGNOSTICS
|
||||
@ -71,9 +75,6 @@ typedef struct {
|
||||
char *path; /* pathname */
|
||||
} DICT_DB;
|
||||
|
||||
#define DICT_DB_TRY0NULL (1<<0)
|
||||
#define DICT_DB_TRY1NULL (1<<1)
|
||||
|
||||
#define DICT_DB_CACHE_SIZE (1024 * 1024)
|
||||
#define DICT_DB_NELM 4096
|
||||
|
||||
@ -92,13 +93,13 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
|
||||
* See if this DB file was written with one null byte appended to key and
|
||||
* value.
|
||||
*/
|
||||
if (dict_db->flags & DICT_DB_TRY1NULL) {
|
||||
if (dict_db->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_DB_TRY0NULL;
|
||||
dict_db->flags &= ~DICT_FLAG_TRY0NULL;
|
||||
return (db_value.data);
|
||||
}
|
||||
}
|
||||
@ -107,7 +108,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_DB_TRY0NULL) {
|
||||
if (dict_db->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)
|
||||
@ -116,7 +117,7 @@ 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_DB_TRY1NULL;
|
||||
dict_db->flags &= ~DICT_FLAG_TRY1NULL;
|
||||
return (vstring_str(buf));
|
||||
}
|
||||
}
|
||||
@ -142,19 +143,19 @@ 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_DB_TRY1NULL)
|
||||
&& (dict_db->flags & DICT_DB_TRY0NULL)) {
|
||||
if ((dict_db->flags & DICT_FLAG_TRY1NULL)
|
||||
&& (dict_db->flags & DICT_FLAG_TRY0NULL)) {
|
||||
#ifdef DB_NO_TRAILING_NULL
|
||||
dict_db->flags = DICT_DB_TRY0NULL;
|
||||
dict_db->flags = DICT_FLAG_TRY0NULL;
|
||||
#else
|
||||
dict_db->flags = DICT_DB_TRY1NULL;
|
||||
dict_db->flags = DICT_FLAG_TRY1NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionally append a null byte to key and value.
|
||||
*/
|
||||
if (dict_db->flags & DICT_DB_TRY1NULL) {
|
||||
if (dict_db->flags & DICT_FLAG_TRY1NULL) {
|
||||
db_key.size++;
|
||||
db_value.size++;
|
||||
}
|
||||
@ -188,7 +189,8 @@ static void dict_db_close(DICT *dict)
|
||||
|
||||
/* dict_db_open - open data base */
|
||||
|
||||
static DICT *dict_db_open(const char *path, int flags, int type, void *tweak)
|
||||
static DICT *dict_db_open(const char *path, int flags, int type,
|
||||
void *tweak, int dict_flags)
|
||||
{
|
||||
DICT_DB *dict_db;
|
||||
DB *db;
|
||||
@ -204,7 +206,9 @@ static DICT *dict_db_open(const char *path, int flags, int type, void *tweak)
|
||||
dict_db->dict.close = dict_db_close;
|
||||
dict_db->dict.fd = db->fd(db);
|
||||
close_on_exec(dict_db->dict.fd, CLOSE_ON_EXEC);
|
||||
dict_db->flags = DICT_DB_TRY1NULL | DICT_DB_TRY0NULL;
|
||||
dict_db->dict.flags = dict_flags;
|
||||
if ((flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
|
||||
dict_db->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
|
||||
dict_db->db = db;
|
||||
dict_db->path = db_path;
|
||||
return (&dict_db->dict);
|
||||
@ -212,26 +216,26 @@ static DICT *dict_db_open(const char *path, int flags, int type, void *tweak)
|
||||
|
||||
/* dict_hash_open - create association with data base */
|
||||
|
||||
DICT *dict_hash_open(const char *path, int flags)
|
||||
DICT *dict_hash_open(const char *path, int open_flags, int dict_flags)
|
||||
{
|
||||
HASHINFO tweak;
|
||||
|
||||
memset((char *) &tweak, 0, sizeof(tweak));
|
||||
tweak.nelem = DICT_DB_NELM;
|
||||
tweak.cachesize = DICT_DB_CACHE_SIZE;
|
||||
return (dict_db_open(path, flags, DB_HASH, (void *) &tweak));
|
||||
return (dict_db_open(path, open_flags, DB_HASH, (void *) &tweak, dict_flags));
|
||||
}
|
||||
|
||||
/* dict_btree_open - create association with data base */
|
||||
|
||||
DICT *dict_btree_open(const char *path, int flags)
|
||||
DICT *dict_btree_open(const char *path, int open_flags, int dict_flags)
|
||||
{
|
||||
BTREEINFO tweak;
|
||||
|
||||
memset((char *) &tweak, 0, sizeof(tweak));
|
||||
tweak.cachesize = DICT_DB_CACHE_SIZE;
|
||||
|
||||
return (dict_db_open(path, flags, DB_BTREE, (void *) &tweak));
|
||||
return (dict_db_open(path, open_flags, DB_BTREE, (void *) &tweak, dict_flags));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -19,8 +19,8 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_hash_open(const char *, int);
|
||||
extern DICT *dict_btree_open(const char *, int);
|
||||
extern DICT *dict_hash_open(const char *, int, int);
|
||||
extern DICT *dict_btree_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -6,10 +6,11 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_dbm.h>
|
||||
/*
|
||||
/* DICT *dict_dbm_open(path, flags)
|
||||
/* DICT *dict_dbm_open(path, open_flags, dict_flags)
|
||||
/* const char *name;
|
||||
/* const char *path;
|
||||
/* int flags;
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_dbm_open() opens the named DBM database and makes it available
|
||||
/* via the generic interface described in dict_open(3).
|
||||
@ -57,9 +58,6 @@ typedef struct {
|
||||
char *path; /* pathname */
|
||||
} DICT_DBM;
|
||||
|
||||
#define DICT_DBM_TRY0NULL (1<<0)
|
||||
#define DICT_DBM_TRY1NULL (1<<1)
|
||||
|
||||
/* dict_dbm_lookup - find database entry */
|
||||
|
||||
static const char *dict_dbm_lookup(DICT *dict, const char *name)
|
||||
@ -73,12 +71,12 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
|
||||
* See if this DBM file was written with one null byte appended to key
|
||||
* and value.
|
||||
*/
|
||||
if (dict_dbm->flags & DICT_DBM_TRY1NULL) {
|
||||
if (dict_dbm->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_DBM_TRY0NULL;
|
||||
dict_dbm->flags &= ~DICT_FLAG_TRY0NULL;
|
||||
return (dbm_value.dptr);
|
||||
}
|
||||
}
|
||||
@ -87,7 +85,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_DBM_TRY0NULL) {
|
||||
if (dict_dbm->flags & DICT_FLAG_TRY0NULL) {
|
||||
dbm_key.dptr = (void *) name;
|
||||
dbm_key.dsize = strlen(name);
|
||||
dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
|
||||
@ -95,7 +93,7 @@ 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_DBM_TRY1NULL;
|
||||
dict_dbm->flags &= ~DICT_FLAG_TRY1NULL;
|
||||
return (vstring_str(buf));
|
||||
}
|
||||
}
|
||||
@ -120,21 +118,19 @@ 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_DBM_TRY1NULL)
|
||||
&& (dict_dbm->flags & DICT_DBM_TRY0NULL)) {
|
||||
if ((dict_dbm->flags & DICT_FLAG_TRY1NULL)
|
||||
&& (dict_dbm->flags & DICT_FLAG_TRY0NULL)) {
|
||||
#ifdef DBM_NO_TRAILING_NULL
|
||||
dict_dbm->flags = DICT_DBM_TRY0NULL;
|
||||
dict_dbm->flags = DICT_FLAG_TRY0NULL;
|
||||
#else
|
||||
dict_dbm->flags = DICT_DBM_TRY1NULL;
|
||||
dict_dbm->flags = DICT_FLAG_TRY1NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionally append a null byte to key and value.
|
||||
*/
|
||||
if ((dict_dbm->flags & DICT_DBM_TRY1NULL)
|
||||
&& strcmp(name, "YP_MASTER_NAME") != 0
|
||||
&& strcmp(name, "YP_LAST_MODIFIED") != 0) {
|
||||
if (dict_dbm->flags & DICT_FLAG_TRY1NULL) {
|
||||
dbm_key.dsize++;
|
||||
dbm_value.dsize++;
|
||||
}
|
||||
@ -167,7 +163,7 @@ static void dict_dbm_close(DICT *dict)
|
||||
|
||||
/* dict_dbm_open - open DBM data base */
|
||||
|
||||
DICT *dict_dbm_open(const char *path, int flags)
|
||||
DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
|
||||
{
|
||||
DICT_DBM *dict_dbm;
|
||||
DBM *dbm;
|
||||
@ -175,7 +171,7 @@ DICT *dict_dbm_open(const char *path, int flags)
|
||||
/*
|
||||
* XXX SunOS 5.x has no const in dbm_open() prototype.
|
||||
*/
|
||||
if ((dbm = dbm_open((char *) path, flags, 0644)) == 0)
|
||||
if ((dbm = dbm_open((char *) path, open_flags, 0644)) == 0)
|
||||
msg_fatal("open database %s.{dir,pag}: %m", path);
|
||||
|
||||
dict_dbm = (DICT_DBM *) mymalloc(sizeof(*dict_dbm));
|
||||
@ -184,7 +180,9 @@ DICT *dict_dbm_open(const char *path, int flags)
|
||||
dict_dbm->dict.close = dict_dbm_close;
|
||||
dict_dbm->dict.fd = dbm_dirfno(dbm);
|
||||
close_on_exec(dict_dbm->dict.fd, CLOSE_ON_EXEC);
|
||||
dict_dbm->flags = DICT_DBM_TRY0NULL | DICT_DBM_TRY1NULL;
|
||||
dict_dbm->dict.flags = dict_flags;
|
||||
if (dict_flagsflags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
|
||||
dict_dbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
|
||||
dict_dbm->dbm = dbm;
|
||||
dict_dbm->path = mystrdup(path);
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_dbm_open(const char *, int);
|
||||
extern DICT *dict_dbm_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -6,13 +6,14 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_env.h>
|
||||
/*
|
||||
/* DICT *dict_env_open(name, flags)
|
||||
/* DICT *dict_env_open(name, dummy, dict_flags)
|
||||
/* const char *name;
|
||||
/* int flags;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_env_open() opens the environment variable array and
|
||||
/* makes it accessible via the generic operations documented
|
||||
/* in dict_open(3). The \fIname\fR and \fIflags\fR arguments
|
||||
/* in dict_open(3). The \fIname\fR and \fIdummy\fR arguments
|
||||
/* are ignored.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
@ -68,7 +69,7 @@ static void dict_env_close(DICT *dict)
|
||||
|
||||
/* dict_env_open - make association with environment array */
|
||||
|
||||
DICT *dict_env_open(const char *unused_name, int unused_flags)
|
||||
DICT *dict_env_open(const char *unused_name, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT *dict;
|
||||
|
||||
@ -76,6 +77,7 @@ DICT *dict_env_open(const char *unused_name, int unused_flags)
|
||||
dict->lookup = dict_env_lookup;
|
||||
dict->update = dict_env_update;
|
||||
dict->close = dict_env_close;
|
||||
dict->flags = dict_flags;
|
||||
dict->fd = -1;
|
||||
return (dict);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_env_open(const char *, int);
|
||||
extern DICT *dict_env_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -6,9 +6,10 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_ldap.h>
|
||||
/*
|
||||
/* DICT *dict_ldap_open(attribute, dummy)
|
||||
/* DICT *dict_ldap_open(attribute, dummy, dict_flags)
|
||||
/* const char *attribute;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_ldap_open() makes LDAP user information accessible via
|
||||
/* the generic dictionary operations described in dict_open(3).
|
||||
@ -307,7 +308,7 @@ static void dict_ldap_close(DICT *dict)
|
||||
|
||||
/* dict_ldap_open - create association with data base */
|
||||
|
||||
DICT *dict_ldap_open(const char *ldapsource, int flags)
|
||||
DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
|
||||
{
|
||||
char *myname = "dict_ldap_open";
|
||||
DICT_LDAP *dict_ldap;
|
||||
@ -320,6 +321,7 @@ DICT *dict_ldap_open(const char *ldapsource, int flags)
|
||||
dict_ldap->dict.update = dict_ldap_update;
|
||||
dict_ldap->dict.close = dict_ldap_close;
|
||||
dict_ldap->dict.fd = -1;
|
||||
dict_ldap->dict.flags = dict_flags;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: using LDAP source %s", myname, ldapsource);
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_ldap_open(const char *, int);
|
||||
extern DICT *dict_ldap_open(const char *, int, int);
|
||||
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
|
@ -1,9 +1,193 @@
|
||||
/*
|
||||
* The NetInfo software is not bundled with IBM's public release. It will be
|
||||
* made available as contributed software from http://www.postfix.org/
|
||||
*/
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_ni 3
|
||||
/* SUMMARY
|
||||
/* dictionary manager interface to NetInfo
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_ni.h>
|
||||
/*
|
||||
/* DICT *dict_ni_open(path, dummy, dict_flags)
|
||||
/* char *path;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_ni_open() `opens' the named NetInfo database. The result is
|
||||
/* a pointer to a structure that can be used to access the dictionary
|
||||
/* using the generic methods documented in dict_open(3).
|
||||
/* DIAGNOSTICS
|
||||
/* dict_ni_register() returns 0 in case of success, -1 in case
|
||||
/* of problems.
|
||||
/* Fatal errors: NetInfo errors, out of memory.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* netinfo(3N) data base subroutines
|
||||
/* AUTHOR(S)
|
||||
/* Pieter Schoenmakers
|
||||
/* Eindhoven University of Technology
|
||||
/* P.O. Box 513
|
||||
/* 5600 MB Eindhoven
|
||||
/* The Netherlands
|
||||
/*--*/
|
||||
|
||||
#include "sys_defs.h"
|
||||
|
||||
#ifdef HAS_NETINFO
|
||||
#error "This requires contributed software from http://www.postfix.org/"
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netinfo/ni.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include "dict.h"
|
||||
#include "dict_ni.h"
|
||||
#include "msg.h"
|
||||
#include "mymalloc.h"
|
||||
|
||||
typedef struct {
|
||||
DICT dict; /* my super */
|
||||
char *path; /* directory path */
|
||||
} DICT_NI;
|
||||
|
||||
/*
|
||||
* We'd like other possibilities, but that is not possible in the current
|
||||
* dictionary setup... An example of a different setup: use `members' for
|
||||
* multi-valued lookups (to be compatible with /aliases), and `value' for
|
||||
* single-valued tables.
|
||||
*/
|
||||
#define NETINFO_PROP_KEY "name"
|
||||
#define NETINFO_PROP_VALUE "members"
|
||||
#define NETINFO_VALUE_SEP ","
|
||||
|
||||
#define NETINFO_MAX_DOMAIN_DEPTH 100
|
||||
|
||||
/* Hard worker doing lookups. Returned value is statically allocated and
|
||||
reused each call. */
|
||||
static const char *dict_ni_do_lookup(char *path, char *key_prop,
|
||||
const char *key_value, char *val_prop)
|
||||
{
|
||||
unsigned int result_cap = 0;
|
||||
static char *result = 0;
|
||||
|
||||
char *return_val = 0;
|
||||
ni_namelist values;
|
||||
int depth = 0;
|
||||
void *domain;
|
||||
void *next_domain;
|
||||
char *query;
|
||||
ni_status r;
|
||||
ni_id dir;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("ni_lookup %s %s=%s", path, key_prop, key_value);
|
||||
|
||||
r = ni_open(NULL, ".", &domain);
|
||||
if (r != NI_OK) {
|
||||
msg_warn("ni_open `.': %d", r);
|
||||
return NULL;
|
||||
}
|
||||
query = alloca(strlen(path) + strlen(key_prop) + 3 + strlen(key_value));
|
||||
sprintf(query, "%s/%s=%s", path, key_prop, key_value);
|
||||
|
||||
for (;;) {
|
||||
|
||||
/*
|
||||
* What does it _mean_ if we find the directory but not the value?
|
||||
*/
|
||||
if (ni_pathsearch(domain, &dir, query) == NI_OK
|
||||
&& ni_lookupprop(domain, &dir, val_prop, &values) == NI_OK)
|
||||
if (values.ni_namelist_len <= 0)
|
||||
ni_namelist_free(&values);
|
||||
else {
|
||||
unsigned int i,
|
||||
l,
|
||||
n;
|
||||
|
||||
for (i = l = 0; i < values.ni_namelist_len; i++)
|
||||
l += 1 + strlen(values.ni_namelist_val[i]);
|
||||
if (result_cap < l) {
|
||||
if (result)
|
||||
myfree(result);
|
||||
result_cap = l + 100;
|
||||
result = mymalloc(result_cap);
|
||||
}
|
||||
for (i = l = 0; i < values.ni_namelist_len; i++) {
|
||||
n = strlen(values.ni_namelist_val[i]);
|
||||
memcpy(result + l, values.ni_namelist_val[i], n);
|
||||
l += n;
|
||||
if (i < values.ni_namelist_len - 1)
|
||||
result[l++] = ',';
|
||||
}
|
||||
result[l] = '\0';
|
||||
return_val = result;
|
||||
break;
|
||||
}
|
||||
|
||||
if (++depth >= NETINFO_MAX_DOMAIN_DEPTH) {
|
||||
msg_warn("ni_open: domain depth limit");
|
||||
break;
|
||||
}
|
||||
r = ni_open(domain, "..", &next_domain);
|
||||
if (r != NI_OK) {
|
||||
if (r != NI_FAILED)
|
||||
msg_warn("ni_open `..': %d", r);
|
||||
break;
|
||||
}
|
||||
ni_free(domain);
|
||||
domain = next_domain;
|
||||
}
|
||||
|
||||
ni_free(domain);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
/* dict_ni_lookup - find table entry */
|
||||
|
||||
static const char *dict_ni_lookup(DICT *dict, const char *key)
|
||||
{
|
||||
DICT_NI *d = (DICT_NI *) dict;
|
||||
|
||||
return dict_ni_do_lookup(d->path, NETINFO_PROP_KEY,
|
||||
key, NETINFO_PROP_VALUE);
|
||||
}
|
||||
|
||||
/* dict_ni_update - add or update table entry (not!) */
|
||||
|
||||
static void dict_ni_update(DICT *dict, const char *unused_name,
|
||||
const char *unused_value)
|
||||
{
|
||||
DICT_NI *d = (DICT_NI *) dict;
|
||||
|
||||
msg_fatal("dict_ni_update: unimplemented: update NetInfo directory %s",
|
||||
d->path);
|
||||
}
|
||||
|
||||
/* dict_ni_close - disassociate from NetInfo map */
|
||||
|
||||
static void dict_ni_close(DICT *dict)
|
||||
{
|
||||
DICT_NI *d = (DICT_NI *) dict;
|
||||
|
||||
myfree(d->path);
|
||||
myfree((char *) d);
|
||||
}
|
||||
|
||||
/* dict_ni_open - create association with NetInfo map */
|
||||
|
||||
DICT *dict_ni_open(const char *path, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT_NI *d = (void *) mymalloc(sizeof(*d));
|
||||
|
||||
d->dict.lookup = dict_ni_lookup;
|
||||
d->dict.update = dict_ni_update;
|
||||
d->dict.close = dict_ni_close;
|
||||
d->dict.fd = -1;
|
||||
d->dict.flags = dict_flags;
|
||||
d->path = mystrdup(path);
|
||||
|
||||
return &d->dict;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,32 @@
|
||||
#ifndef _DICT_NI_H_INCLUDED_
|
||||
#define _DICT_NI_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_ni 3h
|
||||
/* SUMMARY
|
||||
/* dictionary manager interface to NetInfo maps
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_ni.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* The NetInfo software is not bundled with IBM's public release. It will be
|
||||
* made available as contributed software from http://www.postfix.org/
|
||||
* Utility library.
|
||||
*/
|
||||
#include <dict.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_ni_open(const char *, int, int);
|
||||
|
||||
/* AUTHOR(S)
|
||||
/* Pieter Schoenmakers
|
||||
/* Eindhoven University of Technology
|
||||
/* P.O. Box 513
|
||||
/* 5600 MB Eindhoven
|
||||
/* The Netherlands
|
||||
/*--*/
|
||||
|
||||
#endif
|
||||
|
@ -6,9 +6,10 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_nis.h>
|
||||
/*
|
||||
/* DICT *dict_nis_open(map, dummy)
|
||||
/* DICT *dict_nis_open(map, dummy, dict_flags)
|
||||
/* const char *map;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_nis_open() makes the specified NIS map accessible via
|
||||
/* the generic dictionary operations described in dict_open(3).
|
||||
@ -67,9 +68,6 @@ typedef struct {
|
||||
int flags; /* see below */
|
||||
} DICT_NIS;
|
||||
|
||||
#define DICT_NIS_TRY0NULL (1<<0)
|
||||
#define DICT_NIS_TRY1NULL (1<<1)
|
||||
|
||||
/*
|
||||
* Class variables, so that multiple maps can share this info.
|
||||
*/
|
||||
@ -156,12 +154,12 @@ static const char *dict_nis_lookup(DICT *dict, const char *key)
|
||||
* See if this NIS map was written with one null byte appended to key and
|
||||
* value.
|
||||
*/
|
||||
if (dict_nis->flags & DICT_NIS_TRY1NULL) {
|
||||
if (dict_nis->flags & DICT_FLAG_TRY1NULL) {
|
||||
err = yp_match(dict_nis_domain, dict_nis->map,
|
||||
(void *) key, strlen(key) + 1,
|
||||
&result, &result_len);
|
||||
if (err == 0) {
|
||||
dict_nis->flags &= ~DICT_NIS_TRY0NULL;
|
||||
dict_nis->flags &= ~DICT_FLAG_TRY0NULL;
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
@ -170,12 +168,12 @@ static const char *dict_nis_lookup(DICT *dict, const char *key)
|
||||
* See if this NIS map was written with no null byte appended to key and
|
||||
* value. This should never be the case, but better play safe.
|
||||
*/
|
||||
if (dict_nis->flags & DICT_NIS_TRY0NULL) {
|
||||
if (dict_nis->flags & DICT_FLAG_TRY0NULL) {
|
||||
err = yp_match(dict_nis_domain, dict_nis->map,
|
||||
(void *) key, strlen(key),
|
||||
&result, &result_len);
|
||||
if (err == 0) {
|
||||
dict_nis->flags &= ~DICT_NIS_TRY1NULL;
|
||||
dict_nis->flags &= ~DICT_FLAG_TRY1NULL;
|
||||
if (buf == 0)
|
||||
buf = vstring_alloc(10);
|
||||
vstring_strncpy(buf, result, result_len);
|
||||
@ -218,7 +216,7 @@ static void dict_nis_close(DICT *dict)
|
||||
|
||||
/* dict_nis_open - open NIS map */
|
||||
|
||||
DICT *dict_nis_open(const char *map, int unused_flags)
|
||||
DICT *dict_nis_open(const char *map, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT_NIS *dict_nis;
|
||||
|
||||
@ -228,7 +226,9 @@ DICT *dict_nis_open(const char *map, int unused_flags)
|
||||
dict_nis->dict.close = dict_nis_close;
|
||||
dict_nis->dict.fd = -1;
|
||||
dict_nis->map = mystrdup(map);
|
||||
dict_nis->flags = (DICT_NIS_TRY1NULL | DICT_NIS_TRY0NULL);
|
||||
dict_nis->dict.flags = dict_flags;
|
||||
if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
|
||||
dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
|
||||
if (dict_nis_domain == 0)
|
||||
dict_nis_init();
|
||||
return (&dict_nis->dict);
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_nis_open(const char *, int);
|
||||
extern DICT *dict_nis_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -6,9 +6,10 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_nisplus.h>
|
||||
/*
|
||||
/* DICT *dict_nisplus_open(map, dummy)
|
||||
/* DICT *dict_nisplus_open(map, dummy, dict_flags)
|
||||
/* char *map;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_nisplus_open() makes the specified NIS+ map accessible via
|
||||
/* the generic dictionary operations described in dict_open(3).
|
||||
@ -76,7 +77,7 @@ static void dict_nisplus_close(DICT *dict)
|
||||
|
||||
/* dict_nisplus_open - open NISPLUS map */
|
||||
|
||||
DICT *dict_nisplus_open(const char *map, int unused_flags)
|
||||
DICT *dict_nisplus_open(const char *map, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT_NISPLUS *dict_nisplus;
|
||||
|
||||
@ -86,5 +87,6 @@ DICT *dict_nisplus_open(const char *map, int unused_flags)
|
||||
dict_nisplus->dict.close = dict_nisplus_close;
|
||||
dict_nisplus->dict.fd = -1;
|
||||
dict_nisplus->map = mystrdup(map);
|
||||
dict_nisplus->dict.flags = dict_flags;
|
||||
return (&dict_nisplus->dict);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_nisplus_open(const char *, int);
|
||||
extern DICT *dict_nisplus_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -6,14 +6,16 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict.h>
|
||||
/*
|
||||
/* DICT *dict_open(dict_spec, flags)
|
||||
/* DICT *dict_open(dict_spec, open_flags, dict_flags)
|
||||
/* const char *dict_spec;
|
||||
/* int flags;
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/*
|
||||
/* DICT *dict_open3(dict_type, dict_name, flags)
|
||||
/* DICT *dict_open3(dict_type, dict_name, open_flags, dict_flags)
|
||||
/* const char *dict_type;
|
||||
/* const char *dict_name;
|
||||
/* int flags;
|
||||
/* int open_flags;
|
||||
/* int dict_flags;
|
||||
/*
|
||||
/* void dict_put(dict, key, value)
|
||||
/* DICT *dict;
|
||||
@ -32,8 +34,18 @@
|
||||
/*
|
||||
/* dict_open() takes a type:name pair that specifies a dictionary type
|
||||
/* and dictionary name, opens the dictionary, and returns a dictionary
|
||||
/* handle. The \fIflags\fR arguments are as in open(2). The dictionary
|
||||
/* types are as follows:
|
||||
/* handle. The \fIopen_flags\fR arguments are as in open(2). The
|
||||
/* \fIdict_flags\fR are the bit-wise OR of zero or more of the following:
|
||||
/* .IP DICT_FLAG_DUP_WARN
|
||||
/* Warn about duplicate keys, if the underlying database does not
|
||||
/* support duplicate keys. The default is to terminate with a fatal
|
||||
/* error.
|
||||
/* .IP DICT_FLAG_DUP_IGNORE
|
||||
/* Ignore duplicate keys if the underlying database does not
|
||||
/* support duplicate keys. The default is to terminate with a fatal
|
||||
/* error.
|
||||
/* .PP
|
||||
/* The dictionary types are as follows:
|
||||
/* .IP environ
|
||||
/* The process environment array. The \fIdict_name\fR argument is ignored.
|
||||
/* .IP dbm
|
||||
@ -52,6 +64,8 @@
|
||||
/* LDAP ("light-weight" directory access protocol) database access.
|
||||
/* .IP pcre
|
||||
/* PERL-compatible regular expressions.
|
||||
/* .IP regexp
|
||||
/* POSIX-compatible regular expressions.
|
||||
/* .PP
|
||||
/* dict_open3() takes separate arguments for dictionary type and
|
||||
/* name, but otherwise performs the same functions as dict_open().
|
||||
@ -103,6 +117,7 @@
|
||||
#include <dict_ni.h>
|
||||
#include <dict_ldap.h>
|
||||
#include <dict_pcre.h>
|
||||
#include <dict_regexp.h>
|
||||
#include <stringops.h>
|
||||
#include <split_at.h>
|
||||
|
||||
@ -111,7 +126,7 @@
|
||||
*/
|
||||
typedef struct {
|
||||
char *type;
|
||||
struct DICT *(*open) (const char *, int);
|
||||
struct DICT *(*open) (const char *, int, int);
|
||||
} DICT_OPEN_INFO;
|
||||
|
||||
static DICT_OPEN_INFO dict_open_info[] = {
|
||||
@ -138,13 +153,16 @@ static DICT_OPEN_INFO dict_open_info[] = {
|
||||
#endif
|
||||
#ifdef HAS_PCRE
|
||||
"pcre", dict_pcre_open,
|
||||
#endif
|
||||
#ifdef HAS_POSIX_REGEXP
|
||||
"regexp", dict_regexp_open,
|
||||
#endif
|
||||
0,
|
||||
};
|
||||
|
||||
/* dict_open - open dictionary */
|
||||
|
||||
DICT *dict_open(const char *dict_spec, int flags)
|
||||
DICT *dict_open(const char *dict_spec, int open_flags, int dict_flags)
|
||||
{
|
||||
char *saved_dict_spec = mystrdup(dict_spec);
|
||||
char *dict_name;
|
||||
@ -153,7 +171,7 @@ DICT *dict_open(const char *dict_spec, int flags)
|
||||
if ((dict_name = split_at(saved_dict_spec, ':')) == 0)
|
||||
msg_fatal("open dictionary: need \"type:name\" form: %s", dict_spec);
|
||||
|
||||
dict = dict_open3(saved_dict_spec, dict_name, flags);
|
||||
dict = dict_open3(saved_dict_spec, dict_name, open_flags, dict_flags);
|
||||
myfree(saved_dict_spec);
|
||||
return (dict);
|
||||
}
|
||||
@ -161,7 +179,8 @@ DICT *dict_open(const char *dict_spec, int flags)
|
||||
|
||||
/* dict_open3 - open dictionary */
|
||||
|
||||
DICT *dict_open3(const char *dict_type, const char *dict_name, int flags)
|
||||
DICT *dict_open3(const char *dict_type, const char *dict_name,
|
||||
int open_flags, int dict_flags)
|
||||
{
|
||||
char *myname = "dict_open";
|
||||
DICT_OPEN_INFO *dp;
|
||||
@ -169,7 +188,7 @@ DICT *dict_open3(const char *dict_type, const char *dict_name, int flags)
|
||||
|
||||
for (dp = dict_open_info; dp->type; dp++) {
|
||||
if (strcasecmp(dp->type, dict_type) == 0) {
|
||||
if ((dict = dp->open(dict_name, flags)) == 0)
|
||||
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);
|
||||
@ -207,7 +226,7 @@ main(int argc, char **argv)
|
||||
VSTRING *keybuf = vstring_alloc(1);
|
||||
DICT *dict;
|
||||
char *dict_name;
|
||||
int dict_flags;
|
||||
int open_flags;
|
||||
char *key;
|
||||
const char *value;
|
||||
|
||||
@ -215,15 +234,15 @@ main(int argc, char **argv)
|
||||
if (argc != 3)
|
||||
msg_fatal("usage: %s type:file read|write|create", argv[0]);
|
||||
if (strcasecmp(argv[2], "create") == 0)
|
||||
dict_flags = O_CREAT | O_RDWR | O_TRUNC;
|
||||
open_flags = O_CREAT | O_RDWR | O_TRUNC;
|
||||
else if (strcasecmp(argv[2], "write") == 0)
|
||||
dict_flags = O_RDWR;
|
||||
open_flags = O_RDWR;
|
||||
else if (strcasecmp(argv[2], "read") == 0)
|
||||
dict_flags = O_RDONLY;
|
||||
open_flags = O_RDONLY;
|
||||
else
|
||||
msg_fatal("unknown access mode: %s", argv[2]);
|
||||
dict_name = argv[1];
|
||||
dict = dict_open(dict_name, dict_flags);
|
||||
dict = dict_open(dict_name, open_flags, 0);
|
||||
while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) {
|
||||
if ((key = strtok(vstring_str(keybuf), " =")) == 0)
|
||||
continue;
|
||||
|
@ -6,9 +6,10 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_pcre.h>
|
||||
/*
|
||||
/* DICT *dict_pcre_open(name, flags)
|
||||
/* DICT *dict_pcre_open(name, dummy, dict_flags)
|
||||
/* const char *name;
|
||||
/* int flags;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_pcre_open() opens the named file and compiles the contained
|
||||
/* regular expressions.
|
||||
@ -16,10 +17,6 @@
|
||||
/* The lookup interface will match only user@domain form addresses.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Andrew McNamara
|
||||
/* andrewm@connect.com.au
|
||||
@ -261,12 +258,12 @@ DICT *dict_pcre_open(const char *map, int unused_flags)
|
||||
dict_pcre->dict.close = dict_pcre_close;
|
||||
dict_pcre->dict.fd = -1;
|
||||
dict_pcre->map = mystrdup(map);
|
||||
dict_pcre->flags = 0;
|
||||
dict_pcre->dict.flags = dict_flags;
|
||||
dict_pcre->head = NULL;
|
||||
|
||||
if (dict_pcre_init == 0) {
|
||||
pcre_malloc = (void *(*)(size_t)) mymalloc;
|
||||
pcre_free = (void (*)(void *)) myfree;
|
||||
pcre_malloc = (void *(*) (size_t)) mymalloc;
|
||||
pcre_free = (void (*) (void *)) myfree;
|
||||
dict_pcre_init = 1;
|
||||
}
|
||||
if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) {
|
||||
@ -374,12 +371,12 @@ DICT *dict_pcre_open(const char *map, int unused_flags)
|
||||
else
|
||||
pcre_list->next = pl;
|
||||
pcre_list = pl;
|
||||
}
|
||||
}
|
||||
|
||||
vstring_free(line_buffer);
|
||||
vstream_fclose(map_fp);
|
||||
vstring_free(line_buffer);
|
||||
vstream_fclose(map_fp);
|
||||
|
||||
return (&dict_pcre->dict);
|
||||
return (&dict_pcre->dict);
|
||||
}
|
||||
|
||||
#endif /* HAS_PCRE */
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_pcre_open(const char *, int);
|
||||
extern DICT *dict_pcre_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
408
postfix/util/dict_regexp.c
Normal file
408
postfix/util/dict_regexp.c
Normal file
@ -0,0 +1,408 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_regexp 3
|
||||
/* SUMMARY
|
||||
/* dictionary manager interface to REGEXP regular expression library
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_regexp.h>
|
||||
/*
|
||||
/* DICT *dict_regexp_open(name, dummy, dict_flags)
|
||||
/* const char *name;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_regexp_open() opens the named file and compiles the contained
|
||||
/* regular expressions.
|
||||
/*
|
||||
/* The lookup interface will match only user@domain form addresses.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* AUTHOR(S)
|
||||
/* LaMont Jones
|
||||
/* lamont@hp.com
|
||||
/*
|
||||
/* Based on PCRE dictionary contributed by Andrew McNamara
|
||||
/* andrewm@connect.com.au
|
||||
/* connect.com.au Pty. Ltd.
|
||||
/* Level 3, 213 Miller St
|
||||
/* North Sydney, NSW, Australia
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include "sys_defs.h"
|
||||
|
||||
#ifdef HAS_POSIX_REGEXP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <regex.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include "mymalloc.h"
|
||||
#include "msg.h"
|
||||
#include "safe.h"
|
||||
#include "vstream.h"
|
||||
#include "vstring.h"
|
||||
#include "stringops.h"
|
||||
#include "readline.h"
|
||||
#include "dict.h"
|
||||
#include "dict_regexp.h"
|
||||
#include "mac_parse.h"
|
||||
|
||||
typedef struct dict_regexp_list {
|
||||
struct dict_regexp_list *next; /* Next regexp in dict */
|
||||
regex_t *expr[2]; /* The compiled pattern(s) */
|
||||
char *replace; /* Replacement string */
|
||||
int lineno; /* Source file line number */
|
||||
} DICT_REGEXP_RULE;
|
||||
|
||||
typedef struct {
|
||||
DICT dict; /* generic members */
|
||||
char *map; /* map name */
|
||||
int flags; /* unused at the moment */
|
||||
regmatch_t *pmatch; /* Cut substrings */
|
||||
int nmatch; /* number of elements in pmatch */
|
||||
DICT_REGEXP_RULE *head; /* first rule */
|
||||
} DICT_REGEXP;
|
||||
|
||||
/*
|
||||
* Context for macro expansion callback.
|
||||
*/
|
||||
struct dict_regexp_context {
|
||||
DICT_REGEXP *dict; /* the dictionary entry */
|
||||
DICT_REGEXP_RULE *rule; /* the rule we matched */
|
||||
VSTRING *buf; /* target string buffer */
|
||||
const char *subject; /* str against which we match */
|
||||
};
|
||||
|
||||
/*
|
||||
* dict_regexp_update - not supported
|
||||
*/
|
||||
static void dict_regexp_update(DICT *dict, const char *unused_name,
|
||||
const char *unused_value)
|
||||
{
|
||||
DICT_REGEXP *dict_regexp = (DICT_REGEXP *) dict;
|
||||
|
||||
msg_fatal("dict_regexp_update: attempt to update regexp map %s",
|
||||
dict_regexp->map);
|
||||
}
|
||||
|
||||
/*
|
||||
* Macro expansion callback - replace $0-${99} with strings cut from
|
||||
* matched string.
|
||||
*/
|
||||
static void dict_regexp_action(int type, VSTRING *buf, char *ptr)
|
||||
{
|
||||
struct dict_regexp_context *ctxt = (struct dict_regexp_context *) ptr;
|
||||
DICT_REGEXP_RULE *rule = ctxt->rule;
|
||||
DICT_REGEXP *dict = ctxt->dict;
|
||||
int n;
|
||||
|
||||
if (type == MAC_PARSE_VARNAME) {
|
||||
n = atoi(vstring_str(buf));
|
||||
if (n >= dict->nmatch) {
|
||||
msg_warn("regexp %s, line %d: replace index out of range",
|
||||
dict->map, rule->lineno);
|
||||
return;
|
||||
}
|
||||
if (dict->pmatch[n].rm_so < 0 ||
|
||||
dict->pmatch[n].rm_so == dict->pmatch[n].rm_eo) {
|
||||
return; /* empty string or not
|
||||
* matched */
|
||||
}
|
||||
vstring_strncat(ctxt->buf, ctxt->subject + dict->pmatch[n].rm_so,
|
||||
dict->pmatch[n].rm_eo - dict->pmatch[n].rm_so);
|
||||
} else
|
||||
/* Straight text - duplicate with no substitution */
|
||||
vstring_strcat(ctxt->buf, vstring_str(buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up regexp dict and perform string substitution on matched
|
||||
* strings.
|
||||
*/
|
||||
static const char *dict_regexp_lookup(DICT *dict, const char *name)
|
||||
{
|
||||
DICT_REGEXP *dict_regexp = (DICT_REGEXP *) dict;
|
||||
DICT_REGEXP_RULE *rule;
|
||||
struct dict_regexp_context ctxt;
|
||||
static VSTRING *buf;
|
||||
char *at;
|
||||
int error;
|
||||
|
||||
/* msg_info("dict_regexp_lookup: %s: %s", dict_regexp->map, name ); */
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* Search for a matching expression */
|
||||
for (rule = dict_regexp->head; rule; rule = rule->next) {
|
||||
error = regexec(rule->expr[0], name, rule->expr[0]->re_nsub + 1,
|
||||
dict_regexp->pmatch, 0);
|
||||
if (!error) {
|
||||
if (rule->expr[1]) {
|
||||
error = regexec(rule->expr[1], name, rule->expr[1]->re_nsub + 1,
|
||||
dict_regexp->pmatch + rule->expr[0]->re_nsub + 1, 0);
|
||||
if (!error) {
|
||||
continue;
|
||||
} else if (error != REG_NOMATCH) {
|
||||
char errbuf[256];
|
||||
|
||||
(void) regerror(error, rule->expr[1], errbuf, sizeof(errbuf));
|
||||
msg_fatal("regexp map %s, line %d: %s.",
|
||||
dict_regexp->map, rule->lineno, errbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We found a match. Do some final initialization on the
|
||||
* subexpression fields, and perform substitution on replacement
|
||||
* string
|
||||
*/
|
||||
if (!buf)
|
||||
buf = vstring_alloc(10);
|
||||
VSTRING_RESET(buf);
|
||||
ctxt.buf = buf;
|
||||
ctxt.subject = name;
|
||||
ctxt.rule = rule;
|
||||
ctxt.dict = dict_regexp;
|
||||
|
||||
mac_parse(rule->replace, dict_regexp_action, (char *) &ctxt);
|
||||
|
||||
VSTRING_TERMINATE(buf);
|
||||
return (vstring_str(buf));
|
||||
} else if (error && error != REG_NOMATCH) {
|
||||
char errbuf[256];
|
||||
|
||||
(void) regerror(error, rule->expr[0], errbuf, sizeof(errbuf));
|
||||
msg_fatal("regexp map %s, line %d: %s.",
|
||||
dict_regexp->map, rule->lineno, errbuf);
|
||||
return ((char *) 0);
|
||||
}
|
||||
}
|
||||
return ((char *) 0);
|
||||
}
|
||||
|
||||
/* dict_regexp_close - close regexp dictionary */
|
||||
|
||||
static void dict_regexp_close(DICT *dict)
|
||||
{
|
||||
DICT_REGEXP *dict_regexp = (DICT_REGEXP *) dict;
|
||||
DICT_REGEXP_RULE *rule,
|
||||
*next;
|
||||
int i;
|
||||
|
||||
for (rule = dict_regexp->head; rule; rule = next) {
|
||||
next = rule->next;
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (rule->expr[i]) {
|
||||
regfree(rule->expr[i]);
|
||||
myfree((char *) rule->expr[i]);
|
||||
}
|
||||
}
|
||||
myfree((char *) rule->replace);
|
||||
myfree((char *) rule);
|
||||
}
|
||||
myfree((char *) dict_regexp);
|
||||
}
|
||||
|
||||
static regex_t *dict_regexp_get_expr(int lineno, char **bufp, VSTREAM *map_fp)
|
||||
{
|
||||
char *p = *bufp,
|
||||
*regexp,
|
||||
re_delim;
|
||||
int re_options,
|
||||
error;
|
||||
regex_t *expr;
|
||||
|
||||
re_delim = *p++;
|
||||
regexp = p;
|
||||
|
||||
/* Search for second delimiter, handling backslash escape */
|
||||
while (*p) {
|
||||
if (*p == '\\') {
|
||||
if (p[1])
|
||||
p++;
|
||||
else
|
||||
break;
|
||||
} else if (*p == re_delim) {
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
if (!*p) {
|
||||
msg_warn("%s, line %d: no closing regexp delimiter: %c",
|
||||
VSTREAM_PATH(map_fp), lineno, re_delim);
|
||||
return NULL;
|
||||
}
|
||||
*p++ = '\0'; /* Null term the regexp */
|
||||
|
||||
re_options = REG_EXTENDED | REG_ICASE;
|
||||
while (*p) {
|
||||
if (!*p || ISSPACE(*p) || (*p == '!' && p[1] == re_delim)) {
|
||||
/* end of the regexp */
|
||||
expr = (regex_t *) mymalloc(sizeof(*expr));
|
||||
error = regcomp(expr, regexp, re_options);
|
||||
if (error != 0) {
|
||||
char errbuf[256];
|
||||
|
||||
(void) regerror(error, expr, errbuf, sizeof(errbuf));
|
||||
msg_warn("%s, line %d: error in regexp: %s.",
|
||||
VSTREAM_PATH(map_fp), lineno, errbuf);
|
||||
myfree((char *) expr);
|
||||
return NULL;
|
||||
}
|
||||
*bufp = p;
|
||||
return expr;
|
||||
} else {
|
||||
switch (*p) {
|
||||
case 'i':
|
||||
re_options ^= REG_ICASE;
|
||||
break;
|
||||
case 'm':
|
||||
re_options ^= REG_NEWLINE;
|
||||
break;
|
||||
case 'x':
|
||||
re_options ^= REG_EXTENDED;
|
||||
break;
|
||||
default:
|
||||
msg_warn("%s, line %d: unknown regexp option '%c'",
|
||||
VSTREAM_PATH(map_fp), lineno, *p);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DICT_REGEXP_RULE *dict_regexp_parseline(int lineno, char *line, int *nsub, VSTREAM *map_fp)
|
||||
{
|
||||
DICT_REGEXP_RULE *rule;
|
||||
char *p,
|
||||
re_delim;
|
||||
regex_t *expr1,
|
||||
*expr2;
|
||||
int total_nsub;
|
||||
|
||||
p = line;
|
||||
re_delim = *p;
|
||||
|
||||
expr1 = dict_regexp_get_expr(lineno, &p, map_fp);
|
||||
if (!expr1) {
|
||||
return NULL;
|
||||
} else if (*p == '!' && p[1] == re_delim) {
|
||||
p++;
|
||||
expr2 = dict_regexp_get_expr(lineno, &p, map_fp);
|
||||
if (!expr2) {
|
||||
myfree((char *) expr1);
|
||||
return NULL;
|
||||
}
|
||||
total_nsub = expr1->re_nsub + expr2->re_nsub + 2;
|
||||
} else {
|
||||
expr2 = NULL;
|
||||
total_nsub = expr1->re_nsub + 1;
|
||||
}
|
||||
if (nsub)
|
||||
*nsub = total_nsub;
|
||||
|
||||
if (!ISSPACE(*p)) {
|
||||
msg_warn("%s, line %d: Too many expressions.",
|
||||
VSTREAM_PATH(map_fp), lineno);
|
||||
myfree((char *) expr1);
|
||||
if (expr2)
|
||||
myfree((char *) expr2);
|
||||
return NULL;
|
||||
}
|
||||
rule = (DICT_REGEXP_RULE *) mymalloc(sizeof(DICT_REGEXP_RULE));
|
||||
|
||||
while (*p && ISSPACE(*p))
|
||||
++p;
|
||||
|
||||
if (!*p) {
|
||||
msg_warn("%s, line %d: no replacement text: using empty string",
|
||||
VSTREAM_PATH(map_fp), lineno);
|
||||
p = "";
|
||||
}
|
||||
rule->expr[0] = expr1;
|
||||
rule->expr[1] = expr2;
|
||||
rule->replace = mystrdup(p);
|
||||
rule->lineno = lineno;
|
||||
return rule;
|
||||
}
|
||||
|
||||
/*
|
||||
* dict_regexp_open - load and compile a file containing regular expressions
|
||||
*/
|
||||
DICT *dict_regexp_open(const char *map, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT_REGEXP *dict_regexp;
|
||||
VSTREAM *map_fp;
|
||||
VSTRING *line_buffer;
|
||||
DICT_REGEXP_RULE *rule,
|
||||
*last_rule = NULL;
|
||||
int lineno = 0;
|
||||
int max_nsub = 0;
|
||||
int nsub;
|
||||
char *p;
|
||||
|
||||
line_buffer = vstring_alloc(100);
|
||||
|
||||
dict_regexp = (DICT_REGEXP *) mymalloc(sizeof(*dict_regexp));
|
||||
dict_regexp->dict.lookup = dict_regexp_lookup;
|
||||
dict_regexp->dict.update = dict_regexp_update;
|
||||
dict_regexp->dict.close = dict_regexp_close;
|
||||
dict_regexp->dict.fd = -1;
|
||||
dict_regexp->map = mystrdup(map);
|
||||
dict_regexp->dict.flags = dict_flags;
|
||||
|
||||
if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) {
|
||||
msg_fatal("open %s: %m", map);
|
||||
}
|
||||
while (readline(line_buffer, map_fp, &lineno)) {
|
||||
p = vstring_str(line_buffer);
|
||||
|
||||
if (*p == '#') /* Skip comments */
|
||||
continue;
|
||||
|
||||
if (*p == 0) /* Skip blank lines */
|
||||
continue;
|
||||
|
||||
rule = dict_regexp_parseline(lineno, p, &nsub, map_fp);
|
||||
if (rule) {
|
||||
if (nsub > max_nsub)
|
||||
max_nsub = nsub;
|
||||
|
||||
if (last_rule == NULL)
|
||||
dict_regexp->head = rule;
|
||||
else
|
||||
last_rule->next = rule;
|
||||
last_rule = rule;
|
||||
}
|
||||
}
|
||||
last_rule->next = NULL;
|
||||
|
||||
dict_regexp->pmatch = (regmatch_t *) mymalloc(sizeof(regmatch_t) * max_nsub);
|
||||
dict_regexp->nmatch = max_nsub;
|
||||
|
||||
vstring_free(line_buffer);
|
||||
vstream_fclose(map_fp);
|
||||
|
||||
return (&dict_regexp->dict);
|
||||
}
|
||||
|
||||
#endif /* NO_POSIX_REGEXP */
|
40
postfix/util/dict_regexp.h
Normal file
40
postfix/util/dict_regexp.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef _DICT_REGEXP_H_INCLUDED_
|
||||
#define _DICT_REGEXP_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_regexp 3h
|
||||
/* SUMMARY
|
||||
/* dictionary manager interface to REGEXP regular expression library
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_regexp.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <dict.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_regexp_open(const char *, int, int);
|
||||
|
||||
/* AUTHOR(S)
|
||||
/* LaMont Jones
|
||||
/* lamont@hp.com
|
||||
/*
|
||||
/* Based on PCRE dictionary contributed by Andrew McNamara
|
||||
/* andrewm@connect.com.au
|
||||
/* connect.com.au Pty. Ltd.
|
||||
/* Level 3, 213 Miller St
|
||||
/* North Sydney, NSW, Australia
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
#endif
|
@ -6,9 +6,10 @@
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_unix.h>
|
||||
/*
|
||||
/* DICT *dict_unix_open(map, dummy)
|
||||
/* DICT *dict_unix_open(map, dummy, dict_flags)
|
||||
/* const char *map;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_unix_open() makes the specified UNIX table accessible via
|
||||
/* the generic dictionary operations described in dict_open(3).
|
||||
@ -96,7 +97,7 @@ static void dict_unix_close(DICT *dict)
|
||||
|
||||
/* dict_unix_open - open UNIX map */
|
||||
|
||||
DICT *dict_unix_open(const char *map, int unused_flags)
|
||||
DICT *dict_unix_open(const char *map, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT_UNIX *dict_unix;
|
||||
struct dict_unix_lookup {
|
||||
@ -121,5 +122,6 @@ DICT *dict_unix_open(const char *map, int unused_flags)
|
||||
dict_unix->dict.close = dict_unix_close;
|
||||
dict_unix->dict.fd = -1;
|
||||
dict_unix->map = mystrdup(map);
|
||||
dict_unix->dict.flags = dict_flags;
|
||||
return (&dict_unix->dict);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_unix_open(const char *, int);
|
||||
extern DICT *dict_unix_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -1,10 +1,156 @@
|
||||
/*
|
||||
* The environ.c module from TCP Wrappers is not bundled with IBM's public
|
||||
* release. It will be made available as contributed software from
|
||||
* http://www.postfix.org/
|
||||
* From: TCP Wrapper.
|
||||
*
|
||||
* Many systems have putenv() but no setenv(). Other systems have setenv() but
|
||||
* no putenv() (MIPS). Still other systems have neither (NeXT). This is a
|
||||
* re-implementation that hopefully ends all problems.
|
||||
*
|
||||
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
|
||||
*/
|
||||
#include "sys_defs.h"
|
||||
|
||||
#ifdef MISSING_SETENV_PUTENV
|
||||
#error "This requires contributed software from http://www.postfix.org/"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern char **environ;
|
||||
|
||||
static int addenv(char *); /* append entry to environment */
|
||||
static int allocated = 0; /* environ is, or is not, allocated */
|
||||
|
||||
#define DO_CLOBBER 1
|
||||
|
||||
/* namelength - determine length of name in "name=whatever" */
|
||||
|
||||
static int namelength(const char *name)
|
||||
{
|
||||
char *equal;
|
||||
|
||||
equal = strchr(name, '=');
|
||||
return ((equal == 0) ? strlen(name) : (equal - name));
|
||||
}
|
||||
|
||||
/* findenv - given name, locate name=value */
|
||||
|
||||
static char **findenv(const char *name, int len)
|
||||
{
|
||||
char **envp;
|
||||
|
||||
for (envp = environ; envp && *envp; envp++)
|
||||
if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=')
|
||||
return (envp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* getenv - given name, locate value */
|
||||
|
||||
char *getenv(const char *name)
|
||||
{
|
||||
int len = namelength(name);
|
||||
char **envp = findenv(name, len);
|
||||
|
||||
return (envp ? *envp + len + 1 : 0);
|
||||
}
|
||||
|
||||
/* putenv - update or append environment (name,value) pair */
|
||||
|
||||
int putenv(const char *nameval)
|
||||
{
|
||||
char *equal = strchr(nameval, '=');
|
||||
char *value = (equal ? equal : "");
|
||||
|
||||
return (setenv(nameval, value, DO_CLOBBER));
|
||||
}
|
||||
|
||||
/* unsetenv - remove variable from environment */
|
||||
|
||||
void unsetenv(const char *name)
|
||||
{
|
||||
char **envp;
|
||||
|
||||
while ((envp = findenv(name, namelength(name))) != 0)
|
||||
while (envp[0] = envp[1])
|
||||
envp++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* setenv - update or append environment (name,value) pair */
|
||||
|
||||
int setenv(const char *name, const char *value, int clobber)
|
||||
{
|
||||
char *destination;
|
||||
char **envp;
|
||||
int l_name; /* length of name part */
|
||||
unsigned int l_nameval; /* length of name=value */
|
||||
|
||||
/* Permit name= and =value. */
|
||||
|
||||
l_name = namelength(name);
|
||||
envp = findenv(name, l_name);
|
||||
if (envp != 0 && clobber == 0)
|
||||
return (0);
|
||||
if (*value == '=')
|
||||
value++;
|
||||
l_nameval = l_name + strlen(value) + 1;
|
||||
|
||||
/*
|
||||
* Use available memory if the old value is long enough. Never free an
|
||||
* old name=value entry because it may not be allocated.
|
||||
*/
|
||||
|
||||
destination = (envp != 0 && strlen(*envp) >= l_nameval) ?
|
||||
*envp : malloc(l_nameval + 1);
|
||||
if (destination == 0)
|
||||
return (-1);
|
||||
strncpy(destination, name, l_name);
|
||||
destination[l_name] = '=';
|
||||
strcpy(destination + l_name + 1, value);
|
||||
return ((envp == 0) ? addenv(destination) : (*envp = destination, 0));
|
||||
}
|
||||
|
||||
/* cmalloc - malloc and copy block of memory */
|
||||
|
||||
static char *cmalloc(int new_len, char *old, int old_len)
|
||||
{
|
||||
char *new = malloc(new_len);
|
||||
|
||||
if (new != 0)
|
||||
memcpy(new, old, old_len);
|
||||
return (new);
|
||||
}
|
||||
|
||||
/* addenv - append environment entry */
|
||||
|
||||
static int addenv(char *nameval)
|
||||
{
|
||||
char **envp;
|
||||
int n_used; /* number of environment entries */
|
||||
int l_used; /* bytes used excl. terminator */
|
||||
int l_need; /* bytes needed incl. terminator */
|
||||
|
||||
for (envp = environ; envp && *envp; envp++)
|
||||
/* void */ ;
|
||||
n_used = envp - environ;
|
||||
l_used = n_used * sizeof(*envp);
|
||||
l_need = l_used + 2 * sizeof(*envp);
|
||||
|
||||
envp = allocated ?
|
||||
(char **) realloc((char *) environ, l_need) :
|
||||
(char **) cmalloc(l_need, (char *) environ, l_used);
|
||||
if (envp == 0) {
|
||||
return (-1);
|
||||
} else {
|
||||
allocated = 1;
|
||||
environ = envp;
|
||||
environ[n_used++] = nameval; /* add new entry */
|
||||
environ[n_used] = 0; /* terminate list */
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -109,7 +109,7 @@ 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));
|
||||
dict_register(pattern, dict_open(pattern, 0, 0));
|
||||
argv_add(list, pattern, (char *) 0);
|
||||
} else { /* other pattern */
|
||||
argv_add(list, pattern, (char *) 0);
|
||||
|
@ -1,15 +1,126 @@
|
||||
/*
|
||||
* The NETXSTEP and OPENSTEP software is not bundled with IBM's public
|
||||
* release. It will be made available as contributed software from
|
||||
* http://www.postfix.org/
|
||||
*/
|
||||
/*++
|
||||
/* NAME
|
||||
/* posix_signals 3
|
||||
/* SUMMARY
|
||||
/* POSIX signal handling compatibility
|
||||
/* SYNOPSIS
|
||||
/* #include <posix_signals.h>
|
||||
/*
|
||||
/* int sigemptyset(m)
|
||||
/* sigset_t *m;
|
||||
/*
|
||||
/* int sigaddset(set, signum)
|
||||
/* sigset_t *set;
|
||||
/* int signum;
|
||||
/*
|
||||
/* int sigprocmask(how, set, old)
|
||||
/* int how;
|
||||
/* sigset_t *set;
|
||||
/* sigset_t *old;
|
||||
/*
|
||||
/* int sigaction(sig, act, oact)
|
||||
/* int sig;
|
||||
/* struct sigaction *act;
|
||||
/* struct sigaction *oact;
|
||||
/* DESCRIPTION
|
||||
/* These routines emulate the POSIX signal handling interface.
|
||||
/* AUTHOR(S)
|
||||
/* Pieter Schoenmakers
|
||||
/* Eindhoven University of Technology
|
||||
/* P.O. Box 513
|
||||
/* 5600 MB Eindhoven
|
||||
/* The Netherlands
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include "sys_defs.h"
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Utility library.*/
|
||||
|
||||
#include "posix_signals.h"
|
||||
|
||||
#ifdef MISSING_SIGSET_T
|
||||
#error "This requires contributed software from http://www.postfix.org/"
|
||||
|
||||
int sigemptyset(sigset_t *m)
|
||||
{
|
||||
return *m = 0;
|
||||
}
|
||||
|
||||
int sigaddset(sigset_t *set, int signum)
|
||||
{
|
||||
*set |= sigmask(signum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sigprocmask(int how, sigset_t *set, sigset_t *old)
|
||||
{
|
||||
int previous;
|
||||
|
||||
if (how == SIG_BLOCK)
|
||||
previous = sigblock(*set);
|
||||
else if (how == SIG_SETMASK)
|
||||
previous = sigsetmask(*set);
|
||||
else if (how == SIG_UNBLOCK) {
|
||||
int m = sigblock(0);
|
||||
|
||||
previous = sigsetmask(m & ~*set);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (old)
|
||||
*old = previous;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MISSING_SIGACTION
|
||||
#error "This requires contributed software from http://www.postfix.org/"
|
||||
#endif
|
||||
|
||||
static struct sigaction actions[NSIG] = {};
|
||||
|
||||
static int sighandle(int signum)
|
||||
{
|
||||
if (signum == SIGCHLD) {
|
||||
/* XXX If the child is just stopped, don't invoke the handler. */
|
||||
}
|
||||
actions[signum].sa_handler(signum);
|
||||
}
|
||||
|
||||
int sigaction(int sig, struct sigaction *act, struct sigaction *oact)
|
||||
{
|
||||
static int initialized = 0;
|
||||
|
||||
if (!initialized) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
actions[i].sa_handler = SIG_DFL;
|
||||
initialized = 1;
|
||||
}
|
||||
if (sig <= 0 || sig >= NSIG) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (oact)
|
||||
*oact = actions[sig];
|
||||
|
||||
{
|
||||
struct sigvec mine = {
|
||||
sighandle, act->sa_mask,
|
||||
act->sa_flags & SA_RESTART ? SV_INTERRUPT : 0
|
||||
};
|
||||
|
||||
if (sigvec(sig, &mine, NULL))
|
||||
return -1;
|
||||
}
|
||||
|
||||
actions[sig] = *act;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,59 @@
|
||||
#ifndef _POSIX_SIGNALS_H_INCLUDED_
|
||||
#define _POSIX_SIGNALS_H_INCLUDED_
|
||||
/*++
|
||||
/* NAME
|
||||
/* posix_signals 3h
|
||||
/* SUMMARY
|
||||
/* POSIX signal handling compatibility
|
||||
/* SYNOPSIS
|
||||
/* #include <posix_signals.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* The NETXSTEP and OPENSTEP software is not bundled with IBM's public
|
||||
* release. It will be made available as contributed software from
|
||||
* http://www.postfix.org/
|
||||
* Compatibility interface.
|
||||
*/
|
||||
|
||||
#ifdef MISSING_SIGSET_T
|
||||
|
||||
typedef int sigset_t;
|
||||
|
||||
enum {
|
||||
SIG_BLOCK,
|
||||
SIG_UNBLOCK,
|
||||
SIG_SETMASK
|
||||
};
|
||||
|
||||
extern int sigemptyset(sigset_t *);
|
||||
extern int sigaddset(sigset_t *, int);
|
||||
extern int sigprocmask(int, sigset_t *, sigset_t *);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MISSING_SIGACTION
|
||||
|
||||
struct sigaction {
|
||||
void (*sa_handler) ();
|
||||
sigset_t sa_mask;
|
||||
int sa_flags;
|
||||
};
|
||||
|
||||
/* Possible values for sa_flags. Or them to set multiple. */
|
||||
enum {
|
||||
SA_RESTART,
|
||||
SA_NOCLDSTOP = 4 /* drop the = 4. */
|
||||
};
|
||||
|
||||
extern int sigaction(int, struct sigaction *, struct sigaction *);
|
||||
|
||||
#endif
|
||||
|
||||
/* AUTHOR(S)
|
||||
/* Pieter Schoenmakers
|
||||
/* Eindhoven University of Technology
|
||||
/* P.O. Box 513
|
||||
/* 5600 MB Eindhoven
|
||||
/* The Netherlands
|
||||
/*--*/
|
||||
|
||||
#endif
|
||||
|
@ -36,6 +36,7 @@
|
||||
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
|
||||
#define USE_STATFS
|
||||
#define STATFS_IN_SYS_MOUNT_H
|
||||
#define HAS_POSIX_REGEXP
|
||||
#endif
|
||||
|
||||
#if defined(OPENBSD2)
|
||||
@ -285,6 +286,7 @@ extern int initgroups(const char *, int);
|
||||
#define STATFS_IN_SYS_VFS_H
|
||||
#define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT
|
||||
#define PREPEND_PLUS_TO_OPTSTRING
|
||||
#define HAS_POSIX_REGEXP
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user