Bugfix: missing terminator in new attribute-based function
call caused signal 11. File: src/cleanup/cleanup.c.
- Lame workaround for ESTALE errors with mail deliver over
- NFS. Some bandages have been added to the local delivery
- agent. Wietse maintains that Postfix offers no guarantee
- for reliable delivery over NFS.
+20011114
-20011107
-
- Workaround: in order to get mail past PIX firewall bugs,
- Postfix now waits until the socket send buffer is empty
- before sending the final ".<CR><LF>". Files:
- util/sock_empty_wait.c, smtp/smtp_proto.c.
+ Bugfix: reset the smtpd command transaction log between
+ deliveries. File: smtpd/smtpd.c.
Open problems:
Medium: smtpd access maps don't understand the recipient
delimiter setting.
- Low: default domain for appending to unqualified recipients.
-
Low: The $process_id_directory setting is not used anywhere
in Postfix. Problem reported by Michael Smith, texas.net.
This should be documented, or better, the code should warn
- Run the INSTALL.sh script as the super-user:
- # make install (interactive version, first time install)
- # make upgrade (non-interactive version, for upgrades)
+ # make install (interactive version, first time install)
+ # make install </dev/null (non-interactive version, for upgrades)
The non-interactive version needs the /etc/postfix/install.cf
file from a previous installation. If the file does not exist,
install: update
sh INSTALL.sh
-upgrade: update
- sh INSTALL.sh </dev/null
-
depend clean:
set -e; for i in $(DIRS); do \
(set -e; echo "[$$i]"; cd $$i; $(MAKE) $@) || exit 1; \
# Specify "mynetworks_style = host" when Postfix should "trust"
# only the local machine.
#
-#mynetworks_style = class
-#mynetworks_style = subnet
-#mynetworks_style = host
+# mynetworks_style = class
+# mynetworks_style = subnet
+# mynetworks_style = host
# Alternatively, you can specify the mynetworks list by hand, in
# which case Postfix ignores the mynetworks_style setting.
#
# If you're connected via UUCP, see also the default_transport parameter.
#
-#relayhost = $mydomain
-#relayhost = gateway.my.domain
-#relayhost = uucphost
-#relayhost = [an.ip.add.ress]
+# relayhost = $mydomain
+# relayhost = gateway.my.domain
+# relayhost = uucphost
+# relayhost = [an.ip.add.ress]
# REJECTING UNKNOWN LOCAL USERS
#
# Basically, the software tries user+foo and .forward+foo before
# trying user and .forward.
#
-#recipient_delimiter = +
+# recipient_delimiter = +
# DELIVERY TO MAILBOX
#
# UNIX-style mailboxes are kept. The default setting depends on the
# system type.
#
-#mail_spool_directory = /var/mail
-#mail_spool_directory = /var/spool/mail
+# mail_spool_directory = /var/mail
+# mail_spool_directory = /var/spool/mail
# The mailbox_command parameter specifies the optional external
# command to use instead of mailbox delivery. The command is run as
#
# luser_relay works only for the default Postfix local delivery agent.
#
-#luser_relay = $user@other.host
-#luser_relay = $local@other.host
-#luser_relay = admin+$local
+# luser_relay = $user@other.host
+# luser_relay = $local@other.host
+# luser_relay = admin+$local
# JUNK MAIL CONTROLS
#
# increase the verbose logging level by the amount specified in the
# debug_peer_level parameter.
#
-#debug_peer_list = 127.0.0.1
-#debug_peer_list = some.domain
+# debug_peer_list = 127.0.0.1
+# debug_peer_list = some.domain
# The debugger_command specifies the external command that is executed
# when a Postfix daemon program is run with the -D option.
# specify multiple tables, not necessarily all under control by
# Postfix.
#
-#alias_database = dbm:/etc/aliases
-#alias_database = dbm:/etc/mail/aliases
+# alias_database = dbm:/etc/aliases
+# alias_database = dbm:/etc/mail/aliases
alias_database = hash:/etc/aliases
# The alias_maps parameter specifies the list of alias databases used
# It will take a minute or so before changes become visible. Use
# "postfix reload" to eliminate the delay.
#
-#alias_maps = dbm:/etc/aliases, nis:mail.aliases
-#alias_maps = hash:/etc/aliases
+# alias_maps = dbm:/etc/aliases, nis:mail.aliases
+# alias_maps = hash:/etc/aliases
alias_maps = hash:/etc/aliases
# By default, the local authentication realm name is the name of the
# machine.
#
-#smtpd_sasl_local_domain = $mydomain
+# smtpd_sasl_local_domain = $mydomain
smtpd_sasl_local_domain = $myhostname
# SMTP CLIENT CONTROLS
# will become visible after a minute or so. Use "postfix reload"
# to eliminate the delay.
#
-#canonical_maps = dbm:/etc/postfix/canonical
-#canonical_maps = hash:/etc/postfix/canonical
-#canonical_maps = hash:/etc/postfix/canonical, nis:canonical
-#canonical_maps = hash:/etc/postfix/canonical, netinfo:/canonical
+# canonical_maps = dbm:/etc/postfix/canonical
+# canonical_maps = hash:/etc/postfix/canonical
+# canonical_maps = hash:/etc/postfix/canonical, nis:canonical
+# canonical_maps = hash:/etc/postfix/canonical, netinfo:/canonical
canonical_maps =
# The recipient_canonical_maps parameter specifies optional address
#
# $recipient_canonical_maps is used before $canonical_maps lookups.
#
-#recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
+# recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
recipient_canonical_maps =
# The sender_canonical_maps parameter specifies optional address
#
# $sender_canonical_maps is used before $canonical_maps lookups.
#
-#sender_canonical_maps = hash:/etc/postfix/sender_canonical
+# sender_canonical_maps = hash:/etc/postfix/sender_canonical
sender_canonical_maps =
# increase the verbose logging level by the amount specified in the
# debug_peer_level parameter.
#
-#debug_peer_list = 127.0.0.1
-#debug_peer_list = some.domain
+# debug_peer_list = 127.0.0.1
+# debug_peer_list = some.domain
debug_peer_list =
# The debugger_command specifies the external command that is executed
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
-#lmtp_connect_timeout = 30s
+# lmtp_connect_timeout = 30s
lmtp_connect_timeout = 0s
# The lmtp_lhlo_timeout parameter specifies the LMTP client timeout
# with lots of interactive users, this "protocol" can be a real
# performance pig. Specify "biff = no" to disable.
#
-#biff = no
+# biff = no
biff = yes
# The require_home_directory parameter controls whether a local
# external commands. The default is to disallow delivery to "|command"
# in :include: files.
#
-#allow_mail_to_commands = alias,forward,include
+# allow_mail_to_commands = alias,forward,include
allow_mail_to_commands = alias,forward
# The allow_mail_to_files parameter restricts mail delivery to external
# file. The default is to disallow delivery to /file/name in :include:
# files.
#
-#allow_mail_to_files = alias,forward,include
+# allow_mail_to_files = alias,forward,include
allow_mail_to_files = alias,forward
# The default_privs parameter specifies the default rights used by
# mailbox file is /var/spool/mail/user or /var/mail/user. Specify
# "Maildir/" for qmail-style delivery (the / is required).
#
-#home_mailbox = Mailbox
-#home_mailbox = Maildir/
+# home_mailbox = Mailbox
+# home_mailbox = Maildir/
home_mailbox =
# The luser_relay parameter specifies an optional destination address
#
# luser_relay works only for the default Postfix local delivery agent.
#
-#luser_relay = $user@other.host
-#luser_relay = $local@other.host
-#luser_relay = admin+$local
+# luser_relay = $user@other.host
+# luser_relay = $local@other.host
+# luser_relay = admin+$local
# The mail_spool_directory parameter specifies the directory where
# UNIX-style mailboxes are kept. The default setting depends on the
# system type.
#
-#mail_spool_directory = /var/mail
-#mail_spool_directory = /var/spool/mail
+# mail_spool_directory = /var/mail
+# mail_spool_directory = /var/spool/mail
# The mailbox_command parameter specifies the optional external
# command to use instead of mailbox delivery. The command is run
# IF YOU USE THIS TO DELIVER MAIL SYSTEM-WIDE, YOU MUST SET UP AN
# ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER.
#
-#mailbox_command = /some/where/procmail
-#mailbox_command = /some/where/procmail -a "$EXTENSION"
+# mailbox_command = /some/where/procmail
+# mailbox_command = /some/where/procmail -a "$EXTENSION"
mailbox_command =
# The mailbox_command_maps allows you to specify a per-user mailbox
# Specify one or more maps. If this feature is used then every user
# must have a matching entry.
#
-#mailbox_command_maps = hash:/etc/postfix/mailbox_commands
+# mailbox_command_maps = hash:/etc/postfix/mailbox_commands
# The mailbox_transport specifies the optional transport in master.cf
# to use after processing aliases and .forward files. This parameter
# :nexthop part is optional. For more details see the sample transport
# configuration file.
#
-#mailbox_transport = lmtp:unix:/file/name
-#mailbox_transport = cyrus
+# mailbox_transport = lmtp:unix:/file/name
+# mailbox_transport = cyrus
mailbox_transport =
# The fallback_transport specifies the optional transport in master.cf
# :nexthop part is optional. For more details see the sample transport
# configuration file.
#
-#fallback_transport = lmtp:unix:/file/name
-#fallback_transport = cyrus
+# fallback_transport = lmtp:unix:/file/name
+# fallback_transport = cyrus
fallback_transport =
#
# and command. Turning off the Delivered-To: header when forwarding
# mail is not recommended.
#
-#prepend_delivered_header = command, file, forward
-#prepend_delivered_header = forward
+# prepend_delivered_header = command, file, forward
+# prepend_delivered_header = forward
# systems the default type is either `dbm' or `hash'. The default is
# determined when the Postfix system is built.
#
-#default_database_type = hash
-#default_database_type = dbm
+# default_database_type = hash
+# default_database_type = dbm
# The default_transport parameter specifies the default message
# delivery transport to use when no transport is explicitly given in
# transport or nexthop are optional. For more details see the sample
# transports file.
#
-#default_transport = uucp:relayhostname
+# default_transport = uucp:relayhostname
default_transport = smtp
# The double_bounce_sender parameter specifies the sender address
#
# Specify a list of names separated by whitespace or comma.
#
-#import_environment = MAIL_CONFIG TZ XAUTHORITY DISPLAY HOME PURIFYOPTIONS
+# import_environment = MAIL_CONFIG TZ XAUTHORITY DISPLAY HOME PURIFYOPTIONS
import_environment = MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY
# The inet_interfaces parameter specifies the network interface
# a name matches a lookup key. Continue long lines by starting the
# next line with whitespace.
#
-#mydestination = $myhostname, localhost.$mydomain $mydomain
-#mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp.$mydomain
+# mydestination = $myhostname, localhost.$mydomain $mydomain
+# mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp.$mydomain
mydestination = $myhostname, localhost.$mydomain
# The mydomain parameter specifies the local internet domain name.
# a domain-wide alias database that aliases each user to
# user@that.users.mailhost.
#
-#myorigin = $mydomain
+# myorigin = $mydomain
myorigin = $myhostname
# The mynetworks parameter specifies the list of "trusted" SMTP
# Specify "mynetworks_style = host" when Postfix should "trust"
# only the local machine.
#
-#mynetworks_style = class
-#mynetworks_style = subnet
-#mynetworks_style = host
+# mynetworks_style = class
+# mynetworks_style = subnet
+# mynetworks_style = host
# Alternatively, you can specify the mynetworks list by hand, in
# which case Postfix ignores the mynetworks_style setting.
# policy (anti-UCE violations) and protocol error (broken mailers)
# reports.
#
-#notify_classes = bounce,delay,policy,protocol,resource,software
-#notify_classes = 2bounce,resource,software
+# notify_classes = bounce,delay,policy,protocol,resource,software
+# notify_classes = 2bounce,resource,software
notify_classes = resource,software
# The following parameters specify who gets postmaster notices if
# Basically, the software tries user+foo and .forward+foo before
# trying user and .forward.
#
-#recipient_delimiter = +
+# recipient_delimiter = +
recipient_delimiter =
# The propagate_unmatched_extensions parameter specifies what lookup
#
# If you're connected via UUCP, see also the default_transport parameter.
#
-#relayhost = $mydomain
-#relayhost = gateway.my.domain
-#relayhost = uucphost
-#relayhost = [an.ip.add.ress]
+# relayhost = $mydomain
+# relayhost = gateway.my.domain
+# relayhost = uucphost
+# relayhost = [an.ip.add.ress]
relayhost =
# The relocated_maps parameter specifies optional tables with contact
# Specify the types and names of databases to use. After change,
# run "postmap /etc/postfix/relocated", then "postfix reload".
#
-#relocated_maps = hash:/etc/postfix/relocated
+# relocated_maps = hash:/etc/postfix/relocated
relocated_maps =
# The syslog_facility parameter controls where Postfix logging is
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is h (hours).
#
-#delay_warning_time = 0h
+# delay_warning_time = 0h
# build the necessary DBM or DB file after change, then "postfix
# reload" to make the changes visible.
#
-#relocated_maps = dbm:/etc/postfix/relocated
-#relocated_maps = hash:/etc/postfix/relocated
-#relocated_maps = hash:/etc/postfix/relocated, nis:virtual
-#relocated_maps = hash:/etc/postfix/relocated, netinfo:/relocated
+# relocated_maps = dbm:/etc/postfix/relocated
+# relocated_maps = hash:/etc/postfix/relocated
+# relocated_maps = hash:/etc/postfix/relocated, nis:virtual
+# relocated_maps = hash:/etc/postfix/relocated, netinfo:/relocated
relocated_maps =
# The allow_percent_hack parameter controls the rewriting of the form
# "user%domain" to "user@domain". This is enabled by default.
#
-#allow_percent_hack = no
+# allow_percent_hack = no
allow_percent_hack = yes
# The append_at_myorigin controls the rewriting of the form "user" to
# The append_dot_mydomain controls the rewriting of the form
# "user@host" to "user@host.$mydomain". This is enabled by default.
#
-#append_dot_mydomain = no
+# append_dot_mydomain = no
append_dot_mydomain = yes
# The empty_address_recipient specifies the destination for mail from
#
# By default, address masquerading is disabled.
#
-#masquerade_domains = $mydomain
+# masquerade_domains = $mydomain
masquerade_domains =
# The masquerade_exceptions parameter gives an optional list of user
# "site!user" to "user@site". This is necessary if your machine is
# connected to UUCP networks. It is enabled by default.
#
-#swap_bangpath = no
+# swap_bangpath = no
swap_bangpath = yes
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
-#smtp_connect_timeout = 30s
+# smtp_connect_timeout = 30s
smtp_connect_timeout = 0s
# The smtp_helo_timeout parameter specifies the SMTP client timeout
# greeting banner it will report a mailer loop. That's better than
# having a machine meltdown.
#
-#smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
+# smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
smtpd_banner = $myhostname ESMTP $mail_name
# The smtpd_etrn_restrictions parameter restricts what clients are
# Specify "mynetworks_style = host" when Postfix should "trust"
# only the local machine.
#
-#mynetworks_style = class
+# mynetworks_style = class
mynetworks_style = subnet
-#mynetworks_style = host
+# mynetworks_style = host
# Alternatively, you can specify the mynetworks list by hand, in
# which case Postfix ignores the mynetworks_style setting.
# that SMTP clients must introduce themselves at the beginning of an
# SMTP session.
#
-#smtpd_helo_required = yes
+# smtpd_helo_required = yes
smtpd_helo_required = no
# The smtpd_helo_restrictions parameter specifies optional restrictions
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
-#smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
-#smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname
+# smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
+# smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname
smtpd_helo_restrictions =
# The smtpd_sender_restrictions parameter specifies optional restrictions
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
-#smtpd_sender_restrictions = reject_unknown_sender_domain
-#smtpd_sender_restrictions = reject_unknown_sender_domain, hash:/etc/postfix/access
+# smtpd_sender_restrictions = reject_unknown_sender_domain
+# smtpd_sender_restrictions = reject_unknown_sender_domain, hash:/etc/postfix/access
smtpd_sender_restrictions =
# The smtpd_recipient_restrictions parameter specifies restrictions on
# to use. If you use this feature, run "postmap /etc/postfix/transport"
# after change, then "postfix reload".
#
-#transport_maps = dbm:/etc/postfix/transport
-#transport_maps = hash:/etc/postfix/transport
-#transport_maps = hash:/etc/postfix/transport, nis:transport
-#transport_maps = hash:/etc/postfix/transport, netinfo:/transport
+# transport_maps = dbm:/etc/postfix/transport
+# transport_maps = hash:/etc/postfix/transport
+# transport_maps = hash:/etc/postfix/transport, nis:transport
+# transport_maps = hash:/etc/postfix/transport, netinfo:/transport
transport_maps =
# It may take a minute or so before the change becomes visible.
# Use "postfix reload" to eliminate the delay.
#
-#virtual_maps = dbm:/etc/postfix/virtual
-#virtual_maps = hash:/etc/postfix/virtual
-#virtual_maps = hash:/etc/postfix/virtual, nis:virtual
-#virtual_maps = hash:/etc/postfix/virtual, netinfo:/virtual
+# virtual_maps = dbm:/etc/postfix/virtual
+# virtual_maps = hash:/etc/postfix/virtual
+# virtual_maps = hash:/etc/postfix/virtual, nis:virtual
+# virtual_maps = hash:/etc/postfix/virtual, netinfo:/virtual
virtual_maps =
#define CHECK_RECIP_ACL "check_recipient_access"
#define CHECK_ETRN_ACL "check_etrn_access"
-#define WARN_IF_REJECT "warn_if_reject"
-
#define REJECT_MAPS_RBL "reject_maps_rbl"
#define VAR_MAPS_RBL_CODE "maps_rbl_reject_code"
#define DEF_MAPS_RBL_CODE 554
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20011107"
+#define DEF_MAIL_VERSION "Snapshot-20011114"
extern char *var_mail_version;
/* LICENSE
* As the mail system, bounce, defer delivery, or report success.
*/
if (status != 0) {
- status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ?
+ status = (errno == EAGAIN || errno == ENOSPC ?
defer_append : bounce_append)
(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"cannot append message to destination file %s: %s",
* As the mail system, bounce, defer delivery, or report success.
*/
if (status != 0) {
- status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ?
+ status = (errno == EAGAIN || errno == ENOSPC ?
defer_append : bounce_append)
(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"cannot access mailbox %s for user %s. %s",
set_eugid(var_owner_uid, var_owner_gid);
if (status)
- status = (errno == ENOSPC || errno == ESTALE ?
- defer_append : bounce_append)
+ status = (errno == ENOSPC ? defer_append : bounce_append)
(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"maildir delivery failed: %s", vstring_str(why));
else
#include <vstring_vstream.h>
#include <stringops.h>
#include <mymalloc.h>
-#include <iostuff.h>
/* Global library. */
* does not span a packet boundary. This hurts performance so it is not
* on by default.
*/
- if (resp->str[strspn(resp->str, "20 *\t\n")] == 0) {
- msg_info("enabling PIX <CRLF>.<CRLF> workaround for %s",
- session->namaddr);
+ if (resp->str[strspn(resp->str, "20 *\t\n")] == 0)
state->features |= SMTP_FEATURE_MAYBEPIX;
- }
/*
* See if we are talking to ourself. This should not be possible with the
} else if (strcasecmp(word, "ESMTP") == 0)
state->features |= SMTP_FEATURE_ESMTP;
}
- if (var_smtp_always_ehlo && (state->features & SMTP_FEATURE_MAYBEPIX) == 0)
+ if (var_smtp_always_ehlo)
state->features |= SMTP_FEATURE_ESMTP;
- if (var_smtp_never_ehlo || (state->features & SMTP_FEATURE_MAYBEPIX) != 0)
+ if (var_smtp_never_ehlo)
state->features &= ~SMTP_FEATURE_ESMTP;
/*
if (prev_type == REC_TYPE_CONT) /* missing newline at end */
smtp_fputs("", 0, session->stream);
- if ((state->features & SMTP_FEATURE_MAYBEPIX) != 0) {
+ if ((state->features & SMTP_FEATURE_ESMTP) == 0
+ && (state->features & SMTP_FEATURE_MAYBEPIX) != 0)
vstream_fflush(session->stream);/* hurts performance */
- sock_empty_wait(vstream_fileno(session->stream),
- session->stream->timeout / 2);
- }
if (vstream_ferror(state->src))
msg_fatal("queue file read error");
if (rec_type != REC_TYPE_XTRA)
*/
state->where = SMTPD_AFTER_DOT;
+ /*
+ * Notify the postmaster if there were errors. This usually indicates a
+ * client configuration problem, or that someone is trying nasty things.
+ * Either is significant enough to bother the postmaster. XXX Can't
+ * report problems when running in stand-alone mode: postmaster notices
+ * require availability of the cleanup service.
+ */
+ if (state->history != 0 && state->client != VSTREAM_IN
+ && (state->error_mask & state->notify_mask))
+ smtpd_chat_notify(state);
+ smtpd_chat_reset(state);
+
/*
* Cleanup. The client may send another MAIL command.
*/
VSTRING *sasl_encoded;
VSTRING *sasl_decoded;
#endif
- int warn_if_reject;
} SMTPD_STATE;
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
char *format,...)
{
va_list ap;
- int warn_if_reject;
- const char *whatsup;
-
- /*
- * Do not reject mail if we were asked to warn only. However,
- * configuration errors cannot be converted into warnings.
- */
- if (state->warn_if_reject && error_class != MAIL_ERROR_SOFTWARE) {
- warn_if_reject = 1;
- whatsup = "reject_warning";
- } else {
- warn_if_reject = 0;
- whatsup = "reject";
- }
/*
* Update the error class mask, and format the response. XXX What about
* rejected. Print the request, client name/address, and response.
*/
if (state->recipient && state->sender) {
- msg_info("%s: %s from %s: %s; from=<%s> to=<%s>",
- whatsup, state->where, state->namaddr, STR(error_text),
+ msg_info("reject: %s from %s: %s; from=<%s> to=<%s>",
+ state->where, state->namaddr, STR(error_text),
state->sender, state->recipient);
} else if (state->recipient) {
- msg_info("%s: %s from %s: %s; to=<%s>",
- whatsup, state->where, state->namaddr, STR(error_text),
+ msg_info("reject: %s from %s: %s; to=<%s>",
+ state->where, state->namaddr, STR(error_text),
state->recipient);
} else if (state->sender) {
- msg_info("%s: %s from %s: %s; from=<%s>",
- whatsup, state->where, state->namaddr, STR(error_text),
+ msg_info("reject: %s from %s: %s; from=<%s>",
+ state->where, state->namaddr, STR(error_text),
state->sender);
} else {
- msg_info("%s: %s from %s: %s",
- whatsup, state->where, state->namaddr, STR(error_text));
+ msg_info("reject: %s from %s: %s",
+ state->where, state->namaddr, STR(error_text));
}
- return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT);
+ return (SMTPD_CHECK_REJECT);
}
/* reject_dict_retry - reject with temporary failure if dict lookup fails */
int status = 0;
ARGV *list;
int found;
- int saved_recursion = state->recursion;
if (msg_verbose)
msg_info("%s: START", myname);
if (msg_verbose)
msg_info("%s: name=%s", myname, name);
- /*
- * Pseudo restrictions.
- */
- if (strcasecmp(name, WARN_IF_REJECT) == 0) {
- if (state->warn_if_reject == 0)
- state->warn_if_reject = state->recursion;
- continue;
- }
-
/*
* Spoof the is_map_command() routine, so that we do not have to make
* special cases for the implicit short-hand access map notation.
*/
if (strcasecmp(name, PERMIT_ALL) == 0) {
status = SMTPD_CHECK_OK;
- if (cpp[1] != 0 && state->warn_if_reject == 0)
+ if (cpp[1] != 0)
msg_warn("restriction `%s' after `%s' is ignored",
cpp[1], PERMIT_ALL);
} else if (strcasecmp(name, REJECT_ALL) == 0) {
status = smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: %s rejected: Access denied",
var_reject_code, reply_name, reply_class);
- if (cpp[1] != 0 && state->warn_if_reject == 0)
+ if (cpp[1] != 0)
msg_warn("restriction `%s' after `%s' is ignored",
cpp[1], REJECT_ALL);
} else if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) {
if (state->recipient)
status = check_relay_domains(state, state->recipient,
state->recipient, SMTPD_NAME_RECIPIENT);
- if (cpp[1] != 0 && state->warn_if_reject == 0)
+ if (cpp[1] != 0)
msg_warn("restriction `%s' after `%s' is ignored",
cpp[1], CHECK_RELAY_DOMAINS);
#ifdef USE_SASL_AUTH
if (msg_verbose)
msg_info("%s: name=%s status=%d", myname, name, status);
- if (state->warn_if_reject >= state->recursion)
- state->warn_if_reject = 0;
-
if (status != 0)
break;
}
if (msg_verbose && name == 0)
msg_info("%s: END", myname);
- state->recursion = saved_recursion;
-
return (status);
}
/*
* Apply restrictions in the order as specified.
*/
- state->recursion = 1;
+ state->recursion = 0;
status = setjmp(smtpd_check_buf);
if (status == 0 && client_restrctions->argc)
status = generic_checks(state, client_restrctions, state->namaddr,
/*
* Apply restrictions in the order as specified.
*/
- state->recursion = 1;
+ state->recursion = 0;
status = setjmp(smtpd_check_buf);
if (status == 0 && helo_restrctions->argc)
status = generic_checks(state, helo_restrctions, state->helo_name,
/*
* Apply restrictions in the order as specified.
*/
- state->recursion = 1;
+ state->recursion = 0;
status = setjmp(smtpd_check_buf);
if (status == 0 && mail_restrctions->argc)
status = generic_checks(state, mail_restrctions, sender,
/*
* Apply restrictions in the order as specified.
*/
- state->recursion = 1;
+ state->recursion = 0;
status = setjmp(smtpd_check_buf);
if (status == 0 && rcpt_restrctions->argc)
status = generic_checks(state, rcpt_restrctions,
/*
* Apply restrictions in the order as specified.
*/
- state->recursion = 1;
+ state->recursion = 0;
status = setjmp(smtpd_check_buf);
if (status == 0 && etrn_restrctions->argc)
status = generic_checks(state, etrn_restrctions, domain,
state->recursion = 0;
state->msg_size = 0;
state->junk_cmds = 0;
- state->warn_if_reject = 0;
#ifdef USE_SASL_AUTH
if (SMTPD_STAND_ALONE(state))
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \
sane_socketpair.c myrand.c netstring.c ctable.c attr_print.c intv.c \
- attr_scan.c base64_code.c sock_empty_wait.c attr_print0.c attr_scan0.c
+ attr_scan.c base64_code.c
OBJS = argv.o argv_split.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_mysql.o dict_ni.o dict_nis.o \
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \
sane_socketpair.o myrand.o netstring.o ctable.o attr_print.o intv.o \
- attr_scan.o base64_code.o sock_empty_wait.o attr_print0.c attr_scan0.c
+ attr_scan.o base64_code.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_mysql.h \
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
mystrtok sigdelay translit valid_hostname vstream_popen \
vstring vstring_vstream doze select_bug stream_test mac_expand \
watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
- inet_addr_list attr_print attr_scan base64_code attr_print0 attr_scan0
+ inet_addr_list attr_print attr_scan base64_code
LIB_DIR = ../../lib
INC_DIR = ../../include
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
-attr_print0: $(LIB) $@.o
- mv $@.o junk
- $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
- mv junk $@.o
-
-attr_scan0: $(LIB) $@.o
- mv $@.o junk
- $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
- mv junk $@.o
-
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
diff attr_scan.ref attr_scan.tmp
rm -f attr_scan.tmp
-attr_scan0_test: attr_print0 attr_scan0 attr_scan0.ref
- (./attr_print0 2>&3 | (sleep 1; ./attr_scan0)) >attr_scan0.tmp 2>&1 3>&1
- diff attr_scan0.ref attr_scan0.tmp
- rm -f attr_scan0.tmp
-
DB_TYPE = `../postconf/postconf -h default_database_type`
dict_test: dict_open testdb dict_test.in dict_test.ref
attr_print.o: base64_code.h
attr_print.o: vstring.h
attr_print.o: attr.h
-attr_print0.o: attr_print0.c
-attr_print0.o: sys_defs.h
-attr_print0.o: msg.h
-attr_print0.o: mymalloc.h
-attr_print0.o: vstream.h
-attr_print0.o: vbuf.h
-attr_print0.o: htable.h
-attr_print0.o: attr.h
attr_scan.o: attr_scan.c
attr_scan.o: sys_defs.h
attr_scan.o: msg.h
attr_scan.o: htable.h
attr_scan.o: base64_code.h
attr_scan.o: attr.h
-attr_scan0.o: attr_scan0.c
-attr_scan0.o: sys_defs.h
-attr_scan0.o: msg.h
-attr_scan0.o: mymalloc.h
-attr_scan0.o: vstream.h
-attr_scan0.o: vbuf.h
-attr_scan0.o: vstring.h
-attr_scan0.o: htable.h
-attr_scan0.o: attr.h
base64_code.o: base64_code.c
base64_code.o: sys_defs.h
base64_code.o: msg.h
skipblanks.o: stringops.h
skipblanks.o: vstring.h
skipblanks.o: vbuf.h
-sock_empty_wait.o: sock_empty_wait.c
-sock_empty_wait.o: sys_defs.h
-sock_empty_wait.o: msg.h
-sock_empty_wait.o: iostuff.h
spawn_command.o: spawn_command.c
spawn_command.o: sys_defs.h
spawn_command.o: msg.h
extern int attr_scan(VSTREAM *, int,...);
extern int attr_vscan(VSTREAM *, int, va_list);
- /*
- * attr_print0.c.
- */
-extern int attr_print0(VSTREAM *, int,...);
-extern int attr_vprint0(VSTREAM *, int, va_list);
-
- /*
- * attr_scan0.c.
- */
-extern int attr_scan0(VSTREAM *, int,...);
-extern int attr_vscan0(VSTREAM *, int, va_list);
-
/*
* Attribute names for testing the compatibility of the read and write
* routines.
+++ /dev/null
-/*++
-/* NAME
-/* attr_print0 3
-/* SUMMARY
-/* send attributes over byte stream
-/* SYNOPSIS
-/* #include <attr.h>
-/*
-/* int attr_print0(fp, flags, type, name, ...)
-/* VSTREAM fp;
-/* int flags;
-/* int type;
-/* char *name;
-/*
-/* int attr_vprint0(fp, flags, ap)
-/* VSTREAM fp;
-/* int flags;
-/* va_list ap;
-/* DESCRIPTION
-/* attr_print0() 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_scan0(). The stream
-/* is not flushed.
-/*
-/* attr_vprint0() 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_print0() argument list. This routine satisfies the formatting
-/* rules as outlined in attr_scan0(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_print0() 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_scan0(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 <attr.h>
-
-/* attr_vprint0 - send attribute list to stream */
-
-int attr_vprint0(VSTREAM *fp, int flags, va_list ap)
-{
- const char *myname = "attr_print0";
- 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 *);
- vstream_fwrite(fp, attr_name, strlen(attr_name));
- int_val = va_arg(ap, int);
- vstream_fprintf(fp, "%u", (unsigned) int_val);
- VSTREAM_PUTC('\0', fp);
- if (msg_verbose)
- msg_info("send attr %s = %u", attr_name, int_val);
- break;
- case ATTR_TYPE_STR:
- attr_name = va_arg(ap, char *);
- vstream_fwrite(fp, attr_name, strlen(attr_name));
- str_val = va_arg(ap, char *);
- vstream_fwrite(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++) {
- vstream_fwrite(fp, ht[0]->key, strlen(ht[0]->key));
- vstream_fwrite(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);
- }
- myfree((char *) ht_info_list);
- break;
- default:
- msg_panic("%s: unknown type code: %d", myname, attr_type);
- }
- }
- if ((flags & ATTR_FLAG_MORE) == 0)
- VSTREAM_PUTC('\0', fp);
- return (vstream_ferror(fp));
-}
-
-int attr_print0(VSTREAM *fp, int flags,...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, flags);
- ret = attr_vprint0(fp, flags, ap);
- va_end(ap);
- return (ret);
-}
-
-#ifdef TEST
-
- /*
- * Proof of concept test program. Mirror image of the attr_scan0 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_print0(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_print0(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_scan0 3
-/* SUMMARY
-/* recover attributes from byte stream
-/* SYNOPSIS
-/* #include <attr.h>
-/*
-/* int attr_scan0(fp, flags, type, name, ...)
-/* VSTREAM fp;
-/* int flags;
-/* int type;
-/* char *name;
-/*
-/* int attr_vscan0(fp, flags, ap)
-/* VSTREAM fp;
-/* int flags;
-/* va_list ap;
-/* DESCRIPTION
-/* attr_scan0() takes zero or more (name, value) request attributes
-/* and recovers the attribute values from the byte stream that was
-/* possibly generated by attr_print0().
-/*
-/* attr_vscan0() 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* null
-/* .br
-/* simple-attr :== attr-name null attr-value null
-/* .br
-/* attr-name :== any string not containing null
-/* .br
-/* attr-value :== any string not containing null
-/* .br
-/* null :== the ASCII null character
-/* .in
-/*
-/* All attribute names and attribute values are sent as null terminated
-/* strings. Each string must be no longer than 2*var_line_limit
-/* characters. The formatting rules favor implementations in C.
-/*
-/* Normally, attributes must be received in the sequence as specified with
-/* the attr_scan0() 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_scan0() operations from the
-/* same input attribute list.
-/* By default, attr_scan0() 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_scan0() and attr_vscan0() 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_print0(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 <vstring_vstream.h>
-#include <htable.h>
-#include <attr.h>
-
-/* Application specific. */
-
-#define STR(x) vstring_str(x)
-#define LEN(x) VSTRING_LEN(x)
-
-/* attr_scan0_string - pull a string from the input stream */
-
-static int attr_scan0_string(VSTREAM *fp, VSTRING *plain_buf, const char *context)
-{
- extern int var_line_limit; /* XXX */
- int limit = var_line_limit * 2;
- int ch;
-
- if ((ch = vstring_get_null_bound(plain_buf, fp, limit)) == VSTREAM_EOF) {
- msg_warn("premature end-of-input from %s while reading %s",
- VSTREAM_PATH(fp), context);
- return (-1);
- }
- if (ch != 0) {
- msg_warn("string length > %d characters from %s while reading %s",
- limit, VSTREAM_PATH(fp), context);
- return (-1);
- }
- if (msg_verbose)
- msg_info("%s: %s", context, *STR(plain_buf) ? STR(plain_buf) : "(end)");
- return (ch);
-}
-
-/* attr_scan0_number - pull a number from the input stream */
-
-static int attr_scan0_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf,
- const char *context)
-{
- char junk = 0;
- int ch;
-
- if ((ch = attr_scan0_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_vscan0 - receive attribute list from stream */
-
-int attr_vscan0(VSTREAM *fp, int flags, va_list ap)
-{
- const char *myname = "attr_scan0";
- 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_scan0_string(fp, name_buf,
- "input attribute name")) == VSTREAM_EOF)
- return (-1);
- if (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.
- */
- (void) attr_scan0_string(fp, string, "input attribute value");
- }
-
- /*
- * Do the requested conversion.
- */
- switch (wanted_type) {
- case ATTR_TYPE_NUM:
- number = va_arg(ap, unsigned int *);
- if ((ch = attr_scan0_number(fp, number, str_buf,
- "input attribute value")) < 0)
- return (-1);
- break;
- case ATTR_TYPE_STR:
- string = va_arg(ap, VSTRING *);
- if ((ch = attr_scan0_string(fp, string,
- "input attribute value")) < 0)
- return (-1);
- break;
- case ATTR_TYPE_HASH:
- if ((ch = attr_scan0_string(fp, str_buf,
- "input attribute value")) < 0)
- 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_scan0 - read attribute list from stream */
-
-int attr_scan0(VSTREAM *fp, int flags,...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, flags);
- ret = attr_vscan0(fp, flags, ap);
- va_end(ap);
- return (ret);
-}
-
-#ifdef TEST
-
- /*
- * Proof of concept test program. Mirror image of the attr_scan0 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_scan0(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_scan0(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
extern void doze(unsigned);
extern void rand_sleep(unsigned, unsigned);
extern int duplex_pipe(int *);
-extern int sock_empty_wait(int, int);
-extern int sock_maximize_send_lowat(int);
-extern void sock_set_send_lowat(int, int);
#define BLOCKING 0
#define NON_BLOCKING 1
+++ /dev/null
-/*++
-/* NAME
-/* sock_empty_wait 3
-/* SUMMARY
-/* wait until socket send buffer is near empty
-/* SYNOPSIS
-/* #include <iostuff.h>
-/*
-/* int sock_empty_wait(fd, timeout)
-/* int fd;
-/* int timeout;
-/* AUXILIARY ROUTINES
-/* int sock_maximize_send_lowat(fd)
-/* int fd;
-/*
-/* void sock_set_send_lowat(fd, send_lowat)
-/* int fd;
-/* int send_lowat;
-/* DESCRIPTION
-/* sock_empty_wait() blocks the process until the specified socket's
-/* send buffer is near empty, in the hope that the contents of the
-/* next write() operation will not be merged with preceding data.
-/*
-/* sock_maximize_send_lowat() maximizes the socket send buffer
-/* low-water mark, which controls how much free buffer space must
-/* be available before the socket is considered writable.
-/* The result value is the old low-water mark value.
-/*
-/* sock_set_send_lowat() sets the socket send buffer low-water mark
-/* to the specified value.
-/*
-/* Arguments:
-/* .IP fd
-/* File descriptor in the range 0..FD_SETSIZE.
-/* .IP timeout
-/* If positive, deadline in seconds. A zero value effects a poll.
-/* A negative value means wait until something happens.
-/* DIAGNOSTICS
-/* All system call errors are fatal.
-/*
-/* A zero result means success. When the specified deadline is
-/* exceeded, sock_empty_wait() returns -1 and sets errno to ETIMEDOUT.
-/* BUGS
-/* Linux knows better and does not allow the application to
-/* control the send buffer low-water mark.
-/* 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 <sys/socket.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <iostuff.h>
-
-/* sock_maximize_send_lowat - maximize the send buffer low-water mark */
-
-int sock_maximize_send_lowat(int fd)
-{
- char *myname = "sock_maximize_send_lowat";
- int send_buffer_size;
- int saved_low_water_mark;
- int want_low_water_mark;
- int got_low_water_mark;
- SOCKOPT_SIZE optlen;
-
- /*
- * Get the send buffer size.
- */
- optlen = sizeof(send_buffer_size);
- if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF,
- (char *) &send_buffer_size, &optlen) < 0)
- msg_fatal("%s: getsockopt SO_SNDBUF: %m", myname);
-
- /*
- * Save the send buffer low-water mark.
- */
- optlen = sizeof(saved_low_water_mark);
- if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
- (char *) &saved_low_water_mark, &optlen) < 0)
- msg_fatal("%s: getsockopt SO_SNDLOWAT: %m", myname);
-
- /*
- * Max out the send buffer low-water mark.
- */
- want_low_water_mark = send_buffer_size;
- if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
- (char *) &want_low_water_mark,
- sizeof(want_low_water_mark)) < 0)
- if (errno != ENOPROTOOPT)
- msg_fatal("%s: setsockopt SO_SNDLOWAT: %m", myname);
-
- /*
- * Make debugging a bit easier.
- */
- if (msg_verbose) {
- optlen = sizeof(got_low_water_mark);
- if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
- (char *) &got_low_water_mark, &optlen) < 0)
- msg_fatal("%s: getsockopt SO_SNDLOWAT: %m", myname);
- msg_info("%s: send buffer %d, low-water mark was %d, wanted %d, got %d",
- myname, send_buffer_size, saved_low_water_mark,
- want_low_water_mark, got_low_water_mark);
-
- }
- return (saved_low_water_mark);
-}
-
-/* sock_set_send_lowat - restore socket send buffer low-water mark */
-
-void sock_set_send_lowat(int fd, int want_low_water_mark)
-{
- char *myname = "sock_set_send_lowat";
- int got_low_water_mark;
- SOCKOPT_SIZE optlen;
-
- /*
- * Set the send buffer low-water mark.
- */
- if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
- (char *) &want_low_water_mark,
- sizeof(want_low_water_mark)) < 0)
- if (errno != ENOPROTOOPT)
- msg_fatal("%s: setsockopt SO_SNDLOWAT: %m", myname);
-
- /*
- * Make debugging a bit easier.
- */
- if (msg_verbose) {
- optlen = sizeof(got_low_water_mark);
- if (getsockopt(fd, SOL_SOCKET, SO_SNDLOWAT,
- (char *) &got_low_water_mark, &optlen) < 0)
- msg_fatal("%s: getsockopt SO_SNDLOWAT: %m", myname);
- msg_info("%s: low-water mark wanted %d, got %d",
- myname, want_low_water_mark, got_low_water_mark);
- }
-}
-
-/* sock_empty_wait - wait until socket send buffer is near empty */
-
-int sock_empty_wait(int fd, int timeout)
-{
- int saved_errno;
- int saved_low_water_mark;
- int result;
-
- /*
- * Max out the send buffer low-water mark.
- */
- saved_low_water_mark = sock_maximize_send_lowat(fd);
-
- /*
- * Wait until the socket is considered writable.
- */
- result = write_wait(fd, timeout);
-
- /*
- * Restore the send buffer low-water mark.
- */
- saved_errno = errno;
- sock_set_send_lowat(fd, saved_low_water_mark);
- errno = saved_errno;
-
- /*
- * Done.
- */
- return (result);
-}
/* VSTRING *vp;
/* VSTREAM *fp;
/* int bound;
-/*
-/* int vstring_get_null_bound(vp, fp, bound)
-/* VSTRING *vp;
-/* VSTREAM *fp;
-/* int bound;
/* DESCRIPTION
/* The routines in this module each read one newline or null-terminated
/* string from an input stream. In all cases the result is either the
/* vstring_get_null() reads a null-terminated string from the named
/* stream.
/*
-/* the vstring_get<whatever>_bound() routines read no more
+/* vstring_get_bound() and vstring_get_nonl_bound() read no more
/* than \fIbound\fR characters. Otherwise they behave like the
/* unbounded versions documented above.
/* DIAGNOSTICS
return (c == '\n' ? c : VSTRING_GET_RESULT(vp));
}
-/* vstring_get_null_bound - read null-terminated string from file */
-
-int vstring_get_null_bound(VSTRING *vp, VSTREAM *fp, int bound)
-{
- int c;
-
- if (bound <= 0)
- msg_panic("vstring_get_nonl_bound: invalid bound %d", bound);
-
- VSTRING_RESET(vp);
- while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
- VSTRING_ADDCH(vp, c);
- VSTRING_TERMINATE(vp);
- return (c == 0 ? c : VSTRING_GET_RESULT(vp));
-}
-
#ifdef TEST
/*
extern int vstring_get_null(VSTRING *, VSTREAM *);
extern int vstring_get_bound(VSTRING *, VSTREAM *, int);
extern int vstring_get_nonl_bound(VSTRING *, VSTREAM *, int);
-extern int vstring_get_null_bound(VSTRING *, VSTREAM *, int);
/*
* Backwards compatibility for code that still uses the vstring_fgets()
/* numerical user ID values that may be specified in any
/* \fBvirtual_owner_maps\fR or \fBvirtual_uid_maps\fR.
/* SECURITY
-/* .ad
-/* .fi
/* The virtual delivery agent is not security sensitive, provided
-/* that the lookup tables with recipient user/group ID information are
-/* adequately protected. This program is not designed to run chrooted.
+/* that the lookup tables with recipient information are adequately
+/* protected. This program is not designed to run chrooted.
/* STANDARDS
/* RFC 822 (ARPA Internet Text Messages)
/* DIAGNOSTICS
/* This setting is ignored with \fBmaildir\fR style delivery,
/* because such deliveries are safe without explicit locks.
/*
-/* Use the command \fBpostconf -l\fR to find out what locking methods
+/* Use the command \fBpostconf -m\fR to find out what locking methods
/* are available on your system.
/* .IP \fBdeliver_lock_attempts\fR
/* Limit the number of attempts to acquire an exclusive lock