Feature: configurable parent domain matching for domain
and hostname/address match lists: either .domain or the
- domain name itself.
+ domain name itself. Files: util/match_ops.c util/match_list.c
Feature: added pretend-to-be-behind-PIX mode to the smtp-sink
test program, in order to stress test some PIX bug workaround
20011115
+ Feature: mailbox_command_maps no longer requires that every
+ user has an entry. If the user does not have a command
+ entry, the local delivery agent tries the other delivery
+ methods instead. File: local/mailbox.c.
+
Bugfix: reset the smtpd command transaction log between
non-deliveries. File: smtpd/smtpd.c.
and eliminated one missing reset (Victor Duchovny, Morgan
Stanley). File: smtpd/smtpd.c.
+20011118
+
+ Cleanup: replaced unnecessary wrapper code by macros. Files:
+ global/{string,domain,namadr}_list.[hc].
+
+20011119
+
+ Feature: configurable parent domain matching strategy for
+ transport map lookups. File: trivial-rewrite/transport.c.
+
+ New parent_domain_matches_subdomains parameter. This lists
+ all the Postfix features where a domain name matches itself
+ and all its subdomains (instead of requiring ".domain.name"
+ for subdomain matches). Planning for future backwards
+ compatibility :-) File: global/match_parent_style.c.
+
+ Workaround: simplified the PIX ".<CR><LF>" bug to always
+ sleep for 10 seconds. File: smtp/smtp_proto.c.
+
+20011120
+
+ Workaround: disable attribute string length restriction so
+ that trivial-rewrite does not refuse to rewrite broken mail
+ headers. Files: util/attr_scan*.c.
+
Open problems:
Medium: need in-process caching for map lookups. LDAP
-Snapshot 20011103 introduces a negligible amount of features and
-is all about revision of Postfix internals. With more than 70 pages
-of context diffs compared to the previous snapshot, this release
-is a baseline for upcoming feature changes.
+Incompatible changes with snapshot-20011121
+===========================================
+
+The internal protocols have changed again, so you must "postfix
+reload" if upgrading from a previous release. The change is from
+base64 encoded strings to null-terminated strings.
+
+Major changes with snapshot-20011121
+====================================
+
+With host/domain name wildcard matching, the parent domain matching
+behavior is now configurable (that is, does "sub.domain.name" match
+the pattern "domain.name" or does it match the pattern ".domain.name").
+The new configuration parameter "parent_domain_matches_subdomains"
+specifies what Postfix features use the "sub.domain.name matches
+domain.name" approach. It is expected that eventually, all Postfix
+features will use ".domain.name" subdomain matching.
+
+New "warn_if_reject" smtpd pseudo restriction that only warns if
+a restriction would reject mail.
+
+Disgusting workaround for a well-known CISCO PIX firewall bug that
+causes the .<CR>LF> at the end of mail to be lost. The workaround
+has no effect for other mail deliveries.
+
+mailbox_command_maps allows you to configure the external delivery
+command per user (local delivery agent only). This feature has
+precedence over mailbox_command and home_mailbox settings.
Major changes with snapshot-20011103
====================================
flush.o: ../../include/domain_list.h
flush.o: ../../include/match_list.h
flush.o: ../../include/match_ops.h
+flush.o: ../../include/match_parent_style.h
flush.o: ../../include/mail_server.h
#include <mail_scan_dir.h>
#include <maps.h>
#include <domain_list.h>
+#include <match_parent_style.h>
/* Single server skeleton. */
static void pre_jail_init(char *unused_name, char **unused_argv)
{
- flush_domains = domain_list_init(MATCH_FLAG_PARENT, var_fflush_domains);
+ flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS),
+ var_fflush_domains);
}
/* main - pass control to the single-threaded skeleton */
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
- verp_sender.c
+ verp_sender.c match_parent_style.c
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
debug_peer.o debug_process.o defer.o deliver_completed.o \
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
- verp_sender.o
+ verp_sender.o match_parent_style.o
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
recipient_list.h record.h resolve_clnt.h resolve_local.h \
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
- mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h
+ mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
+ match_parent_style.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
debug_peer.o: ../../include/match_list.h
debug_peer.o: ../../include/match_ops.h
debug_peer.o: debug_peer.h
+debug_peer.o: match_parent_style.h
debug_process.o: debug_process.c
debug_process.o: ../../include/sys_defs.h
debug_process.o: ../../include/msg.h
mark_corrupt.o: mail_queue.h
mark_corrupt.o: ../../include/vstring.h
mark_corrupt.o: mark_corrupt.h
+match_parent_style.o: match_parent_style.c
+match_parent_style.o: ../../include/sys_defs.h
+match_parent_style.o: string_list.h
+match_parent_style.o: ../../include/match_list.h
+match_parent_style.o: ../../include/match_ops.h
+match_parent_style.o: mail_params.h
+match_parent_style.o: match_parent_style.h
mbox_conf.o: mbox_conf.c
mbox_conf.o: ../../include/sys_defs.h
mbox_conf.o: ../../include/name_mask.h
resolve_local.o: mail_params.h
resolve_local.o: own_inet_addr.h
resolve_local.o: resolve_local.h
+resolve_local.o: match_parent_style.h
rewrite_clnt.o: rewrite_clnt.c
rewrite_clnt.o: ../../include/sys_defs.h
rewrite_clnt.o: ../../include/msg.h
#include <mail_params.h>
#include <namadr_list.h>
#include <debug_peer.h>
+#include <match_parent_style.h>
/* Application-specific. */
* Finally.
*/
if (*var_debug_peer_list)
- debug_peer_list = namadr_list_init(MATCH_FLAG_PARENT,
- var_debug_peer_list);
+ debug_peer_list =
+ namadr_list_init(match_parent_style(VAR_DEBUG_PEER_LIST),
+ var_debug_peer_list);
}
/* debug_peer_check - see if this peer needs verbose logging */
/* .RS
/* .IP MATCH_FLAG_PARENT
/* The hostname pattern foo.com matches itself and any name below
-/* the domain foo.com.
-/* .IP MATCH_FLAG_DOTPARENT
-/* The hostname pattern foo.com matches itself only.
-/* The hostname pattern .foo.com matches any name below the domain
-/* foo.com.
+/* the domain foo.com. If this flag is cleared, foo.com matches itself
+/* only, and .foo.com matches any name below the domain foo.com.
/* .RE
/* Specify MATCH_FLAG_NONE to request none of the above.
/* The second argument is a list of domain patterns, or the name of
}
if (argc != optind + 2)
usage(argv[0]);
- list = domain_list_init(argv[optind]);
+ list = domain_list_init(MATCH_FLAG_PARENT, argv[optind]);
host = argv[optind + 1];
vstream_printf("%s: %s\n", host, domain_list_match(list, host) ?
"YES" : "NO");
/* char *var_mynetworks_style;
/* char *var_verp_delims;
/* char *var_verp_filter;
+/* char *var_par_dom_match;
/*
/* char *var_import_environ;
/* char *var_export_environ;
char *var_verp_delims;
char *var_verp_filter;
int var_in_flow_delay;
+char *var_par_dom_match;
char *var_import_environ;
char *var_export_environ;
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
VAR_VERP_DELIMS, DEF_VERP_DELIMS, &var_verp_delims, 2, 2,
VAR_VERP_FILTER, DEF_VERP_FILTER, &var_verp_filter, 1, 0,
+ VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match, 0, 0,
0,
};
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
#define DEF_IN_FLOW_DELAY "1s"
extern int var_in_flow_delay;
+ /*
+ * Backwards compatibility: foo.com matches itself and names below foo.com.
+ */
+#define VAR_PAR_DOM_MATCH "parent_domain_matches_subdomains"
+#define DEF_PAR_DOM_MATCH VAR_DEBUG_PEER_LIST "," \
+ VAR_FFLUSH_DOMAINS "," \
+ VAR_MYNETWORKS "," \
+ VAR_PERM_MX_NETWORKS "," \
+ VAR_QMQPD_CLIENTS "," \
+ VAR_RELAY_DOMAINS "," \
+ SMTPD_ACCESS_MAPS
+extern char *var_par_dom_match;
+
+#define SMTPD_ACCESS_MAPS "smtpd_access_maps"
+
/* LICENSE
/* .ad
/* .fi
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20011118"
+#define DEF_MAIL_VERSION "Snapshot-20011119"
extern char *var_mail_version;
/* LICENSE
--- /dev/null
+/*++
+/* NAME
+/* match_parent_style 3
+/* SUMMARY
+/* parent domain matching control
+/* SYNOPSIS
+/* #include <match_parent_style.h>
+/*
+/* int match_parent_style(name)
+/* const char *name;
+/* DESCRIPTION
+/* This module queries configuration parameters for the policy that
+/* controls how wild-card parent domain names are used by various
+/* postfix lookup mechanisms.
+/*
+/* match_parent_style() looks up "name" in the
+/* parent_domain_matches_subdomain configuration parameter
+/* and returns either MATCH_FLAG_PARENT or MATCH_PARENT_NONE.
+/* DIAGNOSTICS
+/* Fatal error: out of memory, name listed under both parent wild card
+/* matching policies.
+/* SEE ALSO
+/* string_list(3) plain string matching
+/* domain_list(3) match host name patterns
+/* namadr_list(3) match host name/address patterns
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+/* Global library. */
+
+#include <string_list.h>
+#include <mail_params.h>
+#include <match_parent_style.h>
+
+/* Application-specific. */
+
+static STRING_LIST *match_par_dom_list;
+
+int match_parent_style(const char *name)
+{
+ int result;
+
+ /*
+ * Initialize on the fly.
+ */
+ if (match_par_dom_list == 0)
+ match_par_dom_list =
+ string_list_init(MATCH_FLAG_NONE, var_par_dom_match);
+
+ /*
+ * Look up the parent domain matching policy.
+ */
+ if (string_list_match(match_par_dom_list, name))
+ result = MATCH_FLAG_PARENT;
+ else
+ result = 0;
+ return (result);
+}
--- /dev/null
+#ifndef _MATCH_PARENT_STYLE_H_INCLUDED_
+#define _MATCH_PARENT_STYLE_H_INCLUDED_
+
+/*++
+/* NAME
+/* match_parent_style 3h
+/* SUMMARY
+/* parent domain matching control
+/* SYNOPSIS
+/* #include <match_parent_style.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <match_ops.h>
+
+ /*
+ * External interface.
+ */
+extern int match_parent_style(const char *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
/* pattern. The matching process is case insensitive.
/*
/* namadr_list_init() performs initializations. The first
-/* argument is the bit-wise OR of zero or mor of the
+/* argument is the bit-wise OR of zero or more of the
/* following:
/* .RS
/* .IP MATCH_FLAG_PARENT
-/* The hostname pattern foo.com matches itself and any name below
-/* the domain foo.com.
-/* .IP MATCH_FLAG_DOTPARENT
-/* The hostname pattern foo.com matches itself only.
-/* The hostname pattern .foo.com matches any name below the domain
-/* foo.com.
+/* The hostname pattern foo.com matches itself and any name below
+/* the domain foo.com. If this flag is cleared, foo.com matches itself
+/* only, and .foo.com matches any name below the domain foo.com.
/* .RE
/* Specify MATCH_FLAG_NONE to request none of the above.
/* The second argument is a list of patterns, or the absolute
msg_vstream_init(argv[0], VSTREAM_ERR);
while ((ch = GETOPT(argc, argv, "v")) > 0) {
- switch (ch) {
- case 'v':
- msg_verbose++;
- break;
- default:
- usage(argv[0]);
- }
+ switch (ch) {
+ case 'v':
+ msg_verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ }
}
if (argc != optind + 3)
- usage(argv[0]);
- list = namadr_list_init(argv[optind]);
+ usage(argv[0]);
+ list = namadr_list_init(MATCH_FLAG_PARENT, argv[optind]);
host = argv[optind + 1];
addr = argv[optind + 2];
vstream_printf("%s/%s: %s\n", host, addr,
- namadr_list_match(list, host, addr) ?
- "YES" : "NO");
+ namadr_list_match(list, host, addr) ?
+ "YES" : "NO");
vstream_fflush(VSTREAM_OUT);
namadr_list_free(list);
}
#include <mail_params.h>
#include <own_inet_addr.h>
#include <resolve_local.h>
+#include <match_parent_style.h>
/* Application-specific */
}
if (argc != optind + 2)
usage(argv[0]);
- list = string_list_init(argv[optind]);
+ list = string_list_init(MATCH_FLAG_NONE, argv[optind]);
string = argv[optind + 1];
vstream_printf("%s: %s\n", string, string_list_match(list, string) ?
"YES" : "NO");
qmqpd.o: ../../include/match_list.h
qmqpd.o: ../../include/match_ops.h
qmqpd.o: ../../include/quote_822_local.h
+qmqpd.o: ../../include/match_parent_style.h
qmqpd.o: ../../include/mail_server.h
qmqpd.o: qmqpd.h
qmqpd_peer.o: qmqpd_peer.c
#include <mail_stream.h>
#include <namadr_list.h>
#include <quote_822_local.h>
+#include <match_parent_style.h>
/* Single-threaded server skeleton. */
static void pre_jail_init(char *unused_name, char **unused_argv)
{
debug_peer_init();
- qmqpd_clients = namadr_list_init(MATCH_FLAG_PARENT, var_qmqpd_clients);
+ qmqpd_clients =
+ namadr_list_init(match_parent_style(VAR_QMQPD_CLIENTS),
+ var_qmqpd_clients);
}
/* main - the main program */
smtp_fputs("", 0, session->stream);
if ((state->features & SMTP_FEATURE_MAYBEPIX) != 0) {
vstream_fflush(session->stream);/* hurts performance */
- sock_empty_wait(vstream_fileno(session->stream),
- session->stream->timeout / 2);
+ sleep(10); /* not to mention this */
}
if (vstream_ferror(state->src))
msg_fatal("queue file read error");
smtpd_check.o: ../../include/mail_conf.h
smtpd_check.o: ../../include/maps.h
smtpd_check.o: ../../include/mail_addr_find.h
+smtpd_check.o: ../../include/match_parent_style.h
smtpd_check.o: smtpd.h
smtpd_check.o: ../../include/mail_stream.h
smtpd_check.o: smtpd_sasl_glue.h
#include <mail_conf.h>
#include <maps.h>
#include <mail_addr_find.h>
+#include <match_parent_style.h>
/* Application-specific. */
static NAMADR_LIST *mynetworks;
static NAMADR_LIST *perm_mx_networks;
+ /*
+ * How to do parent domain wildcard matching, if any.
+ */
+static int access_parent_style;
+
/*
* Pre-parsed restriction lists.
*/
rest += 1;
continue;
}
- for (reqd = required; *reqd; reqd++) {
+ for (reqd = required; *reqd; reqd++)
if (strcmp(*rest, *reqd) == 0)
return (1);
- }
if ((expansion = (ARGV *) htable_find(smtpd_rest_classes, *rest)) != 0)
if (has_required(expansion, required))
return (1);
*/
example = vstring_alloc(10);
for (reqd = required; *reqd; reqd++)
- vstring_sprintf_append(example, "%s%s", *reqd,
- reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", ");
+ vstring_sprintf_append(example, "%s%s", *reqd,
+ reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", ");
msg_fatal("parameter \"%s\": specify at least one working instance of: %s",
name, STR(example));
}
/*
* Pre-open access control lists before going to jail.
*/
- mynetworks = namadr_list_init(MATCH_FLAG_PARENT, var_mynetworks);
- relay_domains = domain_list_init(MATCH_FLAG_PARENT, var_relay_domains);
- perm_mx_networks = namadr_list_init(MATCH_FLAG_PARENT, var_perm_mx_networks);
+ mynetworks =
+ namadr_list_init(match_parent_style(VAR_MYNETWORKS),
+ var_mynetworks);
+ relay_domains =
+ domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
+ var_relay_domains);
+ perm_mx_networks =
+ namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
+ var_perm_mx_networks);
/*
* Pre-parse and pre-open the recipient maps.
relocated_maps = maps_create(VAR_RELOCATED_MAPS, var_relocated_maps,
DICT_FLAG_LOCK);
+ access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS);
+
/*
* error_text is used for returning error responses.
*/
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
- for (name = low_domain; /* void */ ; name = next + 1) {
+ for (name = low_domain; /* void */ ; name = next) {
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, name)) != 0)
CHK_DOMAIN_RETURN(check_table_result(state, table, value,
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
- if ((next = strchr(name, '.')) == 0)
+ if ((next = strchr(name + 1, '.')) == 0)
break;
+ if (access_parent_style == MATCH_FLAG_PARENT)
+ next += 1;
flags = PARTIAL;
}
CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED);
char *var_relocated_maps;
char *var_local_rcpt_maps;
char *var_perm_mx_networks;
+char *var_par_dom_match;
typedef struct {
char *name;
VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps,
VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps,
VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps,
- VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, 0, 0,
+ VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks,
+ VAR_PAR_DOM_MATCH, DEF_PAR_DOM_MATCH, &var_par_dom_match,
0,
};
}
if (strcasecmp(args->argv[0], "mynetworks") == 0) {
namadr_list_free(mynetworks);
- mynetworks = namadr_list_init(MATCH_FLAG_PARENT, args->argv[1]);
+ mynetworks =
+ namadr_list_init(match_parent_style(VAR_MYNETWORKS),
+ args->argv[1]);
resp = 0;
break;
}
if (strcasecmp(args->argv[0], "relay_domains") == 0) {
domain_list_free(relay_domains);
- relay_domains = domain_list_init(MATCH_FLAG_PARENT, args->argv[1]);
+ relay_domains =
+ domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
+ args->argv[1]);
resp = 0;
break;
}
#include <mail_params.h>
#include <maps.h>
+#include <match_parent_style.h>
/* Application-specific. */
#include "transport.h"
static MAPS *transport_path;
+static int transport_match_parent_style;
/* transport_init - pre-jail initialization */
msg_panic("transport_init: repeated call");
transport_path = maps_create("transport", var_transport_maps,
DICT_FLAG_LOCK);
+ transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS);
}
/* transport_lookup - map a transport domain */
{
char *low_domain = lowercase(mystrdup(domain));
const char *name;
+ const char *next;
const char *value;
const char *host;
char *saved_value;
* Specify if a key is partial or full, to avoid matching partial keys with
* regular expressions.
*/
- for (name = low_domain; name != 0; name = strchr(name + 1, '.')) {
+ for (name = low_domain; /* void */; name = next) {
if ((value = maps_find(transport_path, name, maps_flag)) != 0) {
saved_value = mystrdup(value);
if ((host = split_at(saved_value, ':')) == 0 || *host == 0)
} else if (dict_errno != 0) {
msg_fatal("transport table lookup problem");
}
+ if ((next = strchr(name + 1, '.')) == 0)
+ break;
+ if (transport_match_parent_style == MATCH_FLAG_PARENT)
+ next++;
maps_flag = PARTIAL;
}
myfree(low_domain);
+++ /dev/null
-/*++
-/* NAME
-/* attr_print 3
-/* SUMMARY
-/* send attributes over byte stream
-/* SYNOPSIS
-/* #include <attr.h>
-/*
-/* int attr_print(fp, flags, type, name, ...)
-/* VSTREAM fp;
-/* int flags;
-/* int type;
-/* char *name;
-/*
-/* int attr_vprint(fp, flags, ap)
-/* VSTREAM fp;
-/* int flags;
-/* va_list ap;
-/* DESCRIPTION
-/* attr_print() takes zero or more (name, value) simple attributes
-/* or (name, count, value) list attributes, and converts its input
-/* to a byte stream that can be recovered with attr_scan(). The stream
-/* is not flushed.
-/*
-/* attr_vprint() provides an alternate interface that is convenient
-/* for calling from within variadoc functions.
-/*
-/* Attributes are sent in the requested order as specified with the
-/* attr_print() argument list. This routine satisfies the formatting
-/* rules as outlined in attr_scan(3).
-/*
-/* Arguments:
-/* .IP fp
-/* Stream to write the result to.
-/* .IP flags
-/* The bit-wise OR of zero or more of the following.
-/* .RS
-/* .IP ATTR_FLAG_MORE
-/* After sending the requested attributes, leave the output stream in
-/* a state that is usable for more attribute sending operations on
-/* the same output attribute list.
-/* By default, attr_print() automatically appends an attribute list
-/* terminator when it has sent the last requested attribute.
-/* .RE
-/* .IP type
-/* The type determines the arguments that follow.
-/* .RS
-/* .IP "ATTR_TYPE_NUM (char *, int)"
-/* This argument is followed by an attribute name and an integer.
-/* .IP "ATTR_TYPE_STR (char *, char *)"
-/* This argument is followed by an attribute name and a null-terminated
-/* string.
-/* .IP "ATTR_TYPE_HASH (HTABLE *)"
-/* The content of the hash table is sent as a sequence of string-valued
-/* attributes with names equal to the hash table lookup key.
-/* .IP ATTR_TYPE_END
-/* This terminates the attribute list.
-/* .RE
-/* DIAGNOSTICS
-/* The result value is 0 in case of success, VSTREAM_EOF in case
-/* of trouble.
-/*
-/* Panic: interface violation. All system call errors are fatal.
-/* SEE ALSO
-/* attr_scan(3) recover attributes from byte stream
-/* LICENSE
-/* .ad
-/* .fi
-/* The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/* Wietse Venema
-/* IBM T.J. Watson Research
-/* P.O. Box 704
-/* Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <stdarg.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <mymalloc.h>
-#include <vstream.h>
-#include <htable.h>
-#include <base64_code.h>
-#include <attr.h>
-
-#define STR(x) vstring_str(x)
-#define LEN(x) VSTRING_LEN(x)
-
-/* attr_print_str - encode and send attribute information */
-
-static void attr_print_str(VSTREAM *fp, const char *str, int len)
-{
- static VSTRING *base64_buf;
-
- if (base64_buf == 0)
- base64_buf = vstring_alloc(10);
-
- base64_encode(base64_buf, str, len);
- vstream_fputs(STR(base64_buf), fp);
-}
-
-static void attr_print_num(VSTREAM *fp, unsigned num)
-{
- static VSTRING *plain;
-
- if (plain == 0)
- plain = vstring_alloc(10);
-
- vstring_sprintf(plain, "%u", num);
- attr_print_str(fp, STR(plain), LEN(plain));
-}
-
-/* attr_vprint - send attribute list to stream */
-
-int attr_vprint(VSTREAM *fp, int flags, va_list ap)
-{
- const char *myname = "attr_print";
- int attr_type;
- char *attr_name;
- unsigned int_val;
- char *str_val;
- HTABLE_INFO **ht_info_list;
- HTABLE_INFO **ht;
-
- /*
- * Sanity check.
- */
- if (flags & ~ATTR_FLAG_ALL)
- msg_panic("%s: bad flags: 0x%x", myname, flags);
-
- /*
- * Iterate over all (type, name, value) triples, and produce output on
- * the fly.
- */
- while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) {
- switch (attr_type) {
- case ATTR_TYPE_NUM:
- attr_name = va_arg(ap, char *);
- attr_print_str(fp, attr_name, strlen(attr_name));
- int_val = va_arg(ap, int);
- VSTREAM_PUTC(':', fp);
- attr_print_num(fp, (unsigned) int_val);
- if (msg_verbose)
- msg_info("send attr %s = %u", attr_name, int_val);
- break;
- case ATTR_TYPE_STR:
- attr_name = va_arg(ap, char *);
- attr_print_str(fp, attr_name, strlen(attr_name));
- str_val = va_arg(ap, char *);
- VSTREAM_PUTC(':', fp);
- attr_print_str(fp, str_val, strlen(str_val));
- if (msg_verbose)
- msg_info("send attr %s = %s", attr_name, str_val);
- break;
- case ATTR_TYPE_HASH:
- ht_info_list = htable_list(va_arg(ap, HTABLE *));
- for (ht = ht_info_list; *ht; ht++) {
- attr_print_str(fp, ht[0]->key, strlen(ht[0]->key));
- VSTREAM_PUTC(':', fp);
- attr_print_str(fp, ht[0]->value, strlen(ht[0]->value));
- if (msg_verbose)
- msg_info("send attr name %s value %s",
- ht[0]->key, ht[0]->value);
- if (ht[1] != 0)
- VSTREAM_PUTC('\n', fp);
- }
- myfree((char *) ht_info_list);
- break;
- default:
- msg_panic("%s: unknown type code: %d", myname, attr_type);
- }
- VSTREAM_PUTC('\n', fp);
- }
- if ((flags & ATTR_FLAG_MORE) == 0)
- VSTREAM_PUTC('\n', fp);
- return (vstream_ferror(fp));
-}
-
-int attr_print(VSTREAM *fp, int flags,...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, flags);
- ret = attr_vprint(fp, flags, ap);
- va_end(ap);
- return (ret);
-}
-
-#ifdef TEST
-
- /*
- * Proof of concept test program. Mirror image of the attr_scan test
- * program.
- */
-#include <msg_vstream.h>
-
-int main(int unused_argc, char **argv)
-{
- HTABLE *table = htable_create(1);
-
- msg_vstream_init(argv[0], VSTREAM_ERR);
- msg_verbose = 1;
- htable_enter(table, "foo-name", mystrdup("foo-value"));
- htable_enter(table, "bar-name", mystrdup("bar-value"));
- attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
- ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711,
- ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
- ATTR_TYPE_HASH, table,
- ATTR_TYPE_END);
- attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
- ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711,
- ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
- ATTR_TYPE_END);
- if (vstream_fflush(VSTREAM_OUT) != 0)
- msg_fatal("write error: %m");
-
- htable_free(table, myfree);
- return (0);
-}
-
-#endif
+++ /dev/null
-/*++
-/* NAME
-/* attr_scan 3
-/* SUMMARY
-/* recover attributes from byte stream
-/* SYNOPSIS
-/* #include <attr.h>
-/*
-/* int attr_scan(fp, flags, type, name, ...)
-/* VSTREAM fp;
-/* int flags;
-/* int type;
-/* char *name;
-/*
-/* int attr_vscan(fp, flags, ap)
-/* VSTREAM fp;
-/* int flags;
-/* va_list ap;
-/* DESCRIPTION
-/* attr_scan() takes zero or more (name, value) request attributes
-/* and recovers the attribute values from the byte stream that was
-/* possibly generated by attr_print().
-/*
-/* attr_vscan() provides an alternative interface that is convenient
-/* for calling from within a variadic function.
-/*
-/* The input stream is formatted as follows, where (item)* stands
-/* for zero or more instances of the specified item, and where
-/* (item1 | item2) stands for choice:
-/*
-/* .in +5
-/* attr-list :== simple-attr* newline
-/* .br
-/* simple-attr :== attr-name colon attr-value newline
-/* .br
-/* attr-name :== any base64 encoded string
-/* .br
-/* attr-value :== any base64 encoded string
-/* .br
-/* colon :== the ASCII colon character
-/* .br
-/* newline :== the ASCII newline character
-/* .in
-/*
-/* All attribute names and attribute values are sent as base64-encoded
-/* strings. Each base64 encoding must be no longer than 2*var_line_limit
-/* characters. The formatting rules aim to make implementations in PERL
-/* and other languages easy.
-/*
-/* Normally, attributes must be received in the sequence as specified with
-/* the attr_scan() argument list. The input stream may contain additional
-/* attributes at any point in the input stream, including additional
-/* instances of requested attributes.
-/*
-/* Additional input attributes or input attribute instances are silently
-/* skipped over, unless the ATTR_FLAG_EXTRA processing flag is specified
-/* (see below). This allows for some flexibility in the evolution of
-/* protocols while still providing the option of being strict where
-/* this is desirable.
-/*
-/* Arguments:
-/* .IP fp
-/* Stream to recover the input attributes from.
-/* .IP flags
-/* The bit-wise OR of zero or more of the following.
-/* .RS
-/* .IP ATTR_FLAG_MISSING
-/* Log a warning when the input attribute list terminates before all
-/* requested attributes are recovered. It is always an error when the
-/* input stream ends without the newline attribute list terminator.
-/* .IP ATTR_FLAG_EXTRA
-/* Log a warning and stop attribute recovery when the input stream
-/* contains an attribute that was not requested. This includes the
-/* case of additional instances of a requested attribute.
-/* .IP ATTR_FLAG_MORE
-/* After recovering the requested attributes, leave the input stream
-/* in a state that is usable for more attr_scan() operations from the
-/* same input attribute list.
-/* By default, attr_scan() skips forward past the input attribute list
-/* terminator.
-/* .IP ATTR_FLAG_STRICT
-/* For convenience, this value combines both ATTR_FLAG_MISSING and
-/* ATTR_FLAG_EXTRA.
-/* .IP ATTR_FLAG_NONE
-/* For convenience, this value requests none of the above.
-/* .RE
-/* .IP type
-/* The type argument determines the arguments that follow.
-/* .RS
-/* .IP "ATTR_TYPE_NUM (char *, int *)"
-/* This argument is followed by an attribute name and an integer pointer.
-/* .IP "ATTR_TYPE_STR (char *, VSTRING *)"
-/* This argument is followed by an attribute name and a VSTRING pointer.
-/* .IP "ATTR_TYPE_HASH (HTABLE *)"
-/* All further input attributes are processed as string attributes.
-/* No specific attribute sequence is enforced.
-/* All attributes up to the attribute list terminator are read,
-/* but only the first instance of each attribute is stored.
-/* .sp
-/* The attribute string values are stored in the hash table under
-/* keys equal to the attribute name (obtained from the input stream).
-/* Values from the input stream are added to the hash table. Existing
-/* hash table entries are not replaced.
-/* .sp
-/* N.B. This construct must be followed by an ATTR_TYPE_END argument.
-/* .IP ATTR_TYPE_END
-/* This argument terminates the requested attribute list.
-/* .RE
-/* BUGS
-/* ATTR_TYPE_HASH accepts attributes with arbitrary names from possibly
-/* untrusted sources. This is unsafe, unless the resulting table is
-/* queried only with known to be good attribute names.
-/* DIAGNOSTICS
-/* attr_scan() and attr_vscan() return -1 when malformed input is
-/* detected (string too long, incomplete line, missing end marker).
-/* Otherwise, the result value is the number of attributes that were
-/* successfully recovered from the input stream (a hash table counts
-/* as the number of entries stored into the table).
-/*
-/* Panic: interface violation. All system call errors are fatal.
-/* SEE ALSO
-/* attr_print(3) send attributes over byte stream.
-/* LICENSE
-/* .ad
-/* .fi
-/* The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/* Wietse Venema
-/* IBM T.J. Watson Research
-/* P.O. Box 704
-/* Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <mymalloc.h>
-#include <vstream.h>
-#include <vstring.h>
-#include <htable.h>
-#include <base64_code.h>
-#include <attr.h>
-
-/* Application specific. */
-
-#define STR(x) vstring_str(x)
-#define LEN(x) VSTRING_LEN(x)
-
-/* attr_scan_string - pull a string from the input stream */
-
-static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context)
-{
- static VSTRING *base64_buf = 0;
- extern int var_line_limit; /* XXX */
- int limit = var_line_limit * 2;
- int ch;
-
- if (base64_buf == 0)
- base64_buf = vstring_alloc(10);
-
- VSTRING_RESET(base64_buf);
- while ((ch = VSTREAM_GETC(fp)) != ':' && ch != '\n') {
- if (ch == VSTREAM_EOF) {
- msg_warn("premature end-of-input from %s while reading %s",
- VSTREAM_PATH(fp), context);
- return (-1);
- }
- VSTRING_ADDCH(base64_buf, ch);
- if (LEN(base64_buf) > limit) {
- msg_warn("string length > %d characters from %s while reading %s",
- limit, VSTREAM_PATH(fp), context);
- return (-1);
- }
- }
- VSTRING_TERMINATE(base64_buf);
- if (base64_decode(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) {
- msg_warn("malformed base64 data from %s: %.100s",
- VSTREAM_PATH(fp), STR(base64_buf));
- return (-1);
- }
- if (msg_verbose)
- msg_info("%s: %s", context, *STR(plain_buf) ? STR(plain_buf) : "(end)");
- return (ch);
-}
-
-/* attr_scan_number - pull a number from the input stream */
-
-static int attr_scan_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf,
- const char *context)
-{
- char junk = 0;
- int ch;
-
- if ((ch = attr_scan_string(fp, str_buf, context)) < 0)
- return (-1);
- if (sscanf(STR(str_buf), "%u%c", ptr, &junk) != 1 || junk != 0) {
- msg_warn("malformed numerical data from %s while reading %s: %.100s",
- VSTREAM_PATH(fp), context, STR(str_buf));
- return (-1);
- }
- return (ch);
-}
-
-/* attr_vscan - receive attribute list from stream */
-
-int attr_vscan(VSTREAM *fp, int flags, va_list ap)
-{
- const char *myname = "attr_scan";
- static VSTRING *str_buf = 0;
- static VSTRING *name_buf = 0;
- int wanted_type = -1;
- char *wanted_name;
- unsigned int *number;
- VSTRING *string;
- HTABLE *hash_table;
- int ch;
- int conversions;
-
- /*
- * Sanity check.
- */
- if (flags & ~ATTR_FLAG_ALL)
- msg_panic("%s: bad flags: 0x%x", myname, flags);
-
- /*
- * Initialize.
- */
- if (str_buf == 0) {
- str_buf = vstring_alloc(10);
- name_buf = vstring_alloc(10);
- }
-
- /*
- * Iterate over all (type, name, value) triples.
- */
- for (conversions = 0; /* void */ ; conversions++) {
-
- /*
- * Determine the next attribute type and attribute name on the
- * caller's wish list.
- *
- * If we're reading into a hash table, we already know that the
- * attribute value is string-valued, and we get the attribute name
- * from the input stream instead. This is secure only when the
- * resulting table is queried with known to be good attribute names.
- */
- if (wanted_type != ATTR_TYPE_HASH) {
- wanted_type = va_arg(ap, int);
- if (wanted_type == ATTR_TYPE_END) {
- if ((flags & ATTR_FLAG_MORE) != 0)
- return (conversions);
- wanted_name = "(list terminator)";
- } else if (wanted_type == ATTR_TYPE_HASH) {
- wanted_name = "(any attribute name or list terminator)";
- hash_table = va_arg(ap, HTABLE *);
- if (va_arg(ap, int) !=ATTR_TYPE_END)
- msg_panic("%s: ATTR_TYPE_HASH not followed by ATTR_TYPE_END",
- myname);
- } else {
- wanted_name = va_arg(ap, char *);
- }
- }
-
- /*
- * Locate the next attribute of interest in the input stream.
- */
- for (;;) {
-
- /*
- * Get the name of the next attribute. Hitting EOF is always bad.
- * Hitting the end-of-input early is OK if the caller is prepared
- * to deal with missing inputs.
- */
- if (msg_verbose)
- msg_info("%s: wanted attribute: %s",
- VSTREAM_PATH(fp), wanted_name);
- if ((ch = attr_scan_string(fp, name_buf,
- "input attribute name")) == VSTREAM_EOF)
- return (-1);
- if (ch == '\n' && LEN(name_buf) == 0) {
- if (wanted_type == ATTR_TYPE_END
- || wanted_type == ATTR_TYPE_HASH)
- return (conversions);
- if ((flags & ATTR_FLAG_MISSING) != 0)
- msg_warn("missing attribute %s in input from %s",
- wanted_name, VSTREAM_PATH(fp));
- return (conversions);
- }
-
- /*
- * See if the caller asks for this attribute.
- */
- if (wanted_type == ATTR_TYPE_HASH
- || (wanted_type != ATTR_TYPE_END
- && strcmp(wanted_name, STR(name_buf)) == 0))
- break;
- if ((flags & ATTR_FLAG_EXTRA) != 0) {
- msg_warn("spurious attribute %s in input from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
- }
-
- /*
- * Skip over this attribute. The caller does not ask for it.
- */
- while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n')
- /* void */ ;
- }
-
- /*
- * Do the requested conversion. If the target attribute is a
- * non-array type, disallow sending a multi-valued attribute, and
- * disallow sending no value. If the target attribute is an array
- * type, allow the sender to send a zero-element array (i.e. no value
- * at all). XXX Need to impose a bound on the number of array
- * elements.
- */
- switch (wanted_type) {
- case ATTR_TYPE_NUM:
- if (ch != ':') {
- msg_warn("missing value for number attribute %s from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (-1);
- }
- number = va_arg(ap, unsigned int *);
- if ((ch = attr_scan_number(fp, number, str_buf,
- "input attribute value")) < 0)
- return (-1);
- if (ch != '\n') {
- msg_warn("multiple values for attribute %s from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (-1);
- }
- break;
- case ATTR_TYPE_STR:
- if (ch != ':') {
- msg_warn("missing value for string attribute %s from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (-1);
- }
- string = va_arg(ap, VSTRING *);
- if ((ch = attr_scan_string(fp, string,
- "input attribute value")) < 0)
- return (-1);
- if (ch != '\n') {
- msg_warn("multiple values for attribute %s from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (-1);
- }
- break;
- case ATTR_TYPE_HASH:
- if (ch != ':') {
- msg_warn("missing value for string attribute %s from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (-1);
- }
- if ((ch = attr_scan_string(fp, str_buf,
- "input attribute value")) < 0)
- return (-1);
- if (ch != '\n') {
- msg_warn("multiple values for attribute %s from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (-1);
- }
- if (htable_locate(hash_table, STR(name_buf)) != 0) {
- if ((flags & ATTR_FLAG_EXTRA) != 0) {
- msg_warn("duplicate attribute %s in input from %s",
- STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
- }
- } else {
- htable_enter(hash_table, STR(name_buf),
- mystrdup(STR(str_buf)));
- }
- break;
- default:
- msg_panic("%s: unknown type code: %d", myname, wanted_type);
- }
- }
-}
-
-/* attr_scan - read attribute list from stream */
-
-int attr_scan(VSTREAM *fp, int flags,...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, flags);
- ret = attr_vscan(fp, flags, ap);
- va_end(ap);
- return (ret);
-}
-
-#ifdef TEST
-
- /*
- * Proof of concept test program. Mirror image of the attr_scan test
- * program.
- */
-#include <msg_vstream.h>
-
-int var_line_limit = 2048;
-
-int main(int unused_argc, char **used_argv)
-{
- VSTRING *str_val = vstring_alloc(1);
- HTABLE *table = htable_create(1);
- HTABLE_INFO **ht_info_list;
- HTABLE_INFO **ht;
- int int_val;
- int ret;
-
- msg_verbose = 1;
- msg_vstream_init(used_argv[0], VSTREAM_ERR);
- if ((ret = attr_scan(VSTREAM_IN,
- ATTR_FLAG_STRICT,
- ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val,
- ATTR_TYPE_STR, ATTR_NAME_STR, str_val,
- ATTR_TYPE_HASH, table,
- ATTR_TYPE_END)) > 2) {
- vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val);
- vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val));
- ht_info_list = htable_list(table);
- for (ht = ht_info_list; *ht; ht++)
- vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value);
- myfree((char *) ht_info_list);
- } else {
- vstream_printf("return: %d\n", ret);
- }
- if ((ret = attr_scan(VSTREAM_IN,
- ATTR_FLAG_STRICT,
- ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val,
- ATTR_TYPE_STR, ATTR_NAME_STR, str_val,
- ATTR_TYPE_END)) == 2) {
- vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val);
- vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val));
- ht_info_list = htable_list(table);
- for (ht = ht_info_list; *ht; ht++)
- vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value);
- myfree((char *) ht_info_list);
- } else {
- vstream_printf("return: %d\n", ret);
- }
- if (vstream_fflush(VSTREAM_OUT) != 0)
- msg_fatal("write error: %m");
-
- vstring_free(str_val);
- htable_free(table, myfree);
-
- return (0);
-}
-
-#endif
int limit = var_line_limit * 2;
int ch;
- if ((ch = vstring_get_null_bound(plain_buf, fp, limit)) == VSTREAM_EOF) {
+ if ((ch = vstring_get_null(plain_buf, fp)) == VSTREAM_EOF) {
msg_warn("premature end-of-input from %s while reading %s",
VSTREAM_PATH(fp), context);
return (-1);
return (-1);
}
VSTRING_ADDCH(base64_buf, ch);
+#if 0
if (LEN(base64_buf) > limit) {
msg_warn("string length > %d characters from %s while reading %s",
limit, VSTREAM_PATH(fp), context);
return (-1);
}
+#endif
}
VSTRING_TERMINATE(base64_buf);
if (base64_decode(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) {
msg_warn("%s: connect to %s: %m", myname, service);
return (-1);
}
+ close_on_exec(fd, CLOSE_ON_EXEC);
ip = (struct inet_trigger *) mymalloc(sizeof(*ip));
ip->fd = fd;
ip->service = mystrdup(service);
int saved_ch;
struct stat st;
int ret;
- mode_t saved_mode;
+ mode_t saved_mode = 0;
/*
* Initialize. Make a copy of the path that we can safely clobber.
/* .RS
/* .IP MATCH_FLAG_PARENT
/* The hostname pattern foo.com matches any name within the domain
-/* foo.com.
-/* .IP MATCH_FLAG_DOTPARENT
-/* The hostname pattern .foo.com matches any name under foo.com.
-/* The pattern foo.com matches itself only.
+/* foo.com. If this flag is cleared, foo.com matches itself
+/* only, and .foo.com matches any name below the domain foo.com.
/* .RE
/* Specify MATCH_FLAG_NONE to request none of the above.
/* The pattern_list argument specifies a list of patterns. The third
/* of the named host. The flags argument specifies the bit-wise OR
/* of zero or more of the following:
/* .IP MATCH_FLAG_PARENT
-/* The pattern foo.com matches any name within the domain foo.com.
-/* .IP MATCH_FLAG_DOTPARENT
-/* The pattern .foo.com matches any name under foo.com. The pattern
-/* foo.com matches itself only.
+/* The hostname pattern foo.com matches itself and any name below
+/* the domain foo.com. If this flag is cleared, foo.com matches itself
+/* only, and .foo.com matches any name below the domain foo.com.
/* .RE
/* Specify MATCH_FLAG_NONE to request none of the above.
/*
if (strchr(pattern, ':') != 0) {
temp = lowercase(mystrdup(name));
match = 0;
- if (flags & MATCH_FLAG_PARENT) {
- for (entry = temp; /* void */ ; entry = next + 1) {
- if ((match = (dict_lookup(pattern, entry) != 0)) != 0)
- break;
- if (dict_errno != 0)
- msg_fatal("%s: table lookup problem", pattern);
- if ((next = strchr(entry, '.')) == 0)
- break;
- }
- }
- if (flags & MATCH_FLAG_DOTPARENT) {
- for (entry = temp; /* void */ ; entry = next) {
- if ((match = (dict_lookup(pattern, entry) != 0)) != 0)
- break;
- if (dict_errno != 0)
- msg_fatal("%s: table lookup problem", pattern);
- if ((next = strchr(entry, '.')) == 0)
- break;
- }
+ for (entry = temp; /* void */ ; entry = next) {
+ if ((match = (dict_lookup(pattern, entry) != 0)) != 0)
+ break;
+ if (dict_errno != 0)
+ msg_fatal("%s: table lookup problem", pattern);
+ if ((next = strchr(entry + 1, '.')) == 0)
+ break;
+ if (flags & MATCH_FLAG_PARENT)
+ next += 1;
}
myfree(temp);
return (match);
pd = name + strlen(name) - strlen(pattern);
if (pd > name && pd[-1] == '.' && strcasecmp(pd, pattern) == 0)
return (1);
- }
- if (flags & MATCH_FLAG_DOTPARENT) {
+ } else if (pattern[0] == '.') {
pd = name + strlen(name) - strlen(pattern);
- if (pd > name && pd[-1] == '.' && strcasecmp(pd - 1, pattern) == 0)
+ if (pd > name && strcasecmp(pd, pattern) == 0)
return (1);
}
}
#define MATCH_FLAG_NONE 0
#define MATCH_FLAG_PARENT (1<<0)
-#define MATCH_FLAG_DOTPARENT (1<<1)
-#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT|MATCH_FLAG_DOTPARENT)
+#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT)
extern int match_string(int, const char *, const char *);
extern int match_hostname(int, const char *, const char *);
msg_warn("%s: connect to %s: %m", myname, service);
return (-1);
}
+ close_on_exec(fd, CLOSE_ON_EXEC);
/*
* Stash away context.
msg_warn("%s: connect to %s: %m", myname, service);
return (-1);
}
+ close_on_exec(fd, CLOSE_ON_EXEC);
/*
* Stash away context.