2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 13:18:12 +00:00

snapshot-19990327

This commit is contained in:
Wietse Venema 1999-03-27 00:00:00 -05:00
parent a5534e6452
commit 702954b400
71 changed files with 1304 additions and 165 deletions

2
postfix/.indent.pro vendored
View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -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

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View 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

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -131,7 +131,7 @@ int mail_copy(const char *sender, const char *delivered,
quote_822_local(buf, sender);
if (flags & MAIL_COPY_FROM) {
time(&now);
vstream_fprintf(dst, "From %s %s", *sender == 0 ?
vstream_fprintf(dst, "From %s %s", *sender == 0 ?
MAIL_ADDR_MAIL_DAEMON :
vstring_str(buf),
asctime(localtime(&now)));

View File

@ -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

View File

@ -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);
}

View File

@ -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 *);

View File

@ -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));

View File

@ -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);

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -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.
*/

View File

@ -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.

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -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

View File

@ -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++;
}

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -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

View File

@ -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++;
}

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -312,7 +312,7 @@ static ARGV *smtpd_check_parse(char *checks)
while ((name = mystrtok(&bp, " \t\r\n,")) != 0) {
argv_add(argv, name, (char *) 0);
if (strchr(name, ':') && dict_handle(name) == 0)
dict_register(name, dict_open(name, 0));
dict_register(name, dict_open(name, 0, 0));
}
argv_terminate(argv);

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -27,6 +27,8 @@
-TDICT_NODE
-TDICT_OPEN_INFO
-TDICT_PCRE
-TDICT_REGEXP
-TDICT_REGEXP_LINE
-TDICT_UNIX
-TDNS_FIXED
-TDNS_REPLY

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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
View 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 */

View 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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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
/*