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

snapshot-20010323

This commit is contained in:
Wietse Venema 2001-03-23 00:00:00 -05:00 committed by Viktor Dukhovni
parent f9eee68f7a
commit c70c1482d6
41 changed files with 737 additions and 252 deletions

View File

@ -128,9 +128,9 @@ for transit mail that arrives and leaves via SMTP, provided that
you create no temporary files. Each temporary file adds another you create no temporary files. Each temporary file adds another
factor to the performance loss. factor to the performance loss.
We will set up a content filtering program listening on localhost We will set up a content filtering program that receives SMTP mail
port 10025 that receives mail via the SMTP protocol, and that via localhost port 10025, and that submits SMTP mail back into
submits mail back into Postfix via localhost port 10026. Postfix via localhost port 10026.
.................................. ..................................
: Postfix : : Postfix :
@ -162,7 +162,7 @@ transport table. The content filtering records are added by the
smtpd and pickup servers. smtpd and pickup servers.
When a queue file has content filtering information, the queue When a queue file has content filtering information, the queue
manager will deliver the mail to the specified content filtering manager will deliver the mail to the specified content filter
regardless of its final destination. regardless of its final destination.
The content filter can be set up with the Postfix spawn service, The content filter can be set up with the Postfix spawn service,
@ -183,6 +183,9 @@ you want to have your filter listening on port localhost:10025
instead of Postfix, then you must run your filter as a stand-alone instead of Postfix, then you must run your filter as a stand-alone
program. program.
Note: the localhost port 10025 SMTP server filter should announce
itself as "220 localhost...", to silence warnings in the log.
The /some/where/filter command is most likely a PERL script. PERL The /some/where/filter command is most likely a PERL script. PERL
has modules that make talking SMTP easy. The command-line specifies has modules that make talking SMTP easy. The command-line specifies
that mail should be sent back into Postfix via localhost port 10026. that mail should be sent back into Postfix via localhost port 10026.

View File

@ -4960,3 +4960,31 @@ Apologies for any names omitted.
Code cleanup: some queue/transport operations need to be Code cleanup: some queue/transport operations need to be
moved, after the code cleanup of the recipient/concurrency moved, after the code cleanup of the recipient/concurrency
limit handling. Patrik Rak. Files: *qmgr/qmgr_message.c. limit handling. Patrik Rak. Files: *qmgr/qmgr_message.c.
20010301
Feature: configurable name in syslog output (default:
"syslog_name = postfix") so that different Postfix instances
can be recognized by their logging. File: global/mail_task.c.
20010313
Workaround for logic mismatch in nqmgr that was exposed
with the introduction of the asynchronous bounce client.
Patrik Rak.
20010321
Workaround: LMTP connection caching never worked for
destinations starting with unix: or inet:. File:
lmtp/lmtp_connect.c.
20010322
Portability: Solaris <2.6 does not have srandom() and
random() in libc. File: util/rand_sleep.c. It does not
have to be cryptographically strong.
Bugfix: the fast ETRN flush server could not handle [ipaddr]
or domain names with one-character hostname part. It should
be OK now. File: flush/flush.c.

View File

@ -249,6 +249,8 @@ or, if you feel nostalgic, use the Postfix sendmail command:
and watch your syslog file for any error messages. and watch your syslog file for any error messages.
% egrep '(reject|warning|error|fatal|panic):' /some/log/file
When it is run for the first time, the Postfix startup shell script When it is run for the first time, the Postfix startup shell script
will create a bunch of subdirectories below the Postfix spool will create a bunch of subdirectories below the Postfix spool
directory. directory.
@ -290,6 +292,8 @@ or, if you feel nostalgic, use the Postfix sendmail program:
and watch your syslog file for any error messages. and watch your syslog file for any error messages.
% egrep '(reject|warning|error|fatal|panic):' /some/log/file
When it is run for the first time, the Postfix startup shell script When it is run for the first time, the Postfix startup shell script
will create a bunch of subdirectories below the Postfix spool will create a bunch of subdirectories below the Postfix spool
directory. directory.
@ -323,6 +327,8 @@ But the good old sendmail way works just as well:
and watch the syslog file for any complaints from the mail system. and watch the syslog file for any complaints from the mail system.
% egrep '(reject|warning|error|fatal|panic):' /some/log/file
When it is run for the first time, the Postfix startup shell script When it is run for the first time, the Postfix startup shell script
will create a bunch of subdirectories below the Postfix spool will create a bunch of subdirectories below the Postfix spool
directory. directory.

View File

@ -1,3 +1,9 @@
LINUX PORTABILITY
=================
On RedHat Linux 7.0, you must install the db3-devel RPM before you
can compile the Postfix source code.
LINUX SYSLOGD PERFORMANCE LINUX SYSLOGD PERFORMANCE
========================= =========================

View File

@ -76,7 +76,7 @@
# octets separated by ".". # octets separated by ".".
# #
# ACTIONS # ACTIONS
# [45]XX text # [45]NN text
# Reject the address etc. that matches the pattern, # Reject the address etc. that matches the pattern,
# and respond with the numerical code and text. # and respond with the numerical code and text.
# #
@ -86,7 +86,7 @@
# OK Accept the address etc. that matches the pattern. # OK Accept the address etc. that matches the pattern.
# #
# restriction... # restriction...
# Apply the named UCE restriction (permit, reject, # Apply the named UCE restriction(s) (permit, reject,
# reject_unauth_destination, and so on). # reject_unauth_destination, and so on).
# #
# REGULAR EXPRESSION TABLES # REGULAR EXPRESSION TABLES

View File

@ -226,14 +226,12 @@ mail_owner = postfix
# $inet_interfaces. If this parameter is defined, then the SMTP server # $inet_interfaces. If this parameter is defined, then the SMTP server
# will reject mail for unknown local users. # will reject mail for unknown local users.
# #
# The local_recipient_maps parameter accepts tables with bare usernames # If you use the default Postfix local delivery agent for local
# such as unix:passwd.byname and alias maps. # delivery, uncomment the definition below.
# #
# Beware: if the Postfix SMTP server runs chrooted, you may have to # Beware: if the Postfix SMTP server runs chrooted, you may have to
# copy the passwd database into the jail. This is system dependent. # copy the passwd (not shadow) database into the jail. This is
# # system dependent.
# FOR THIS TO WORK, DO NOT SPECIFY VIRTUAL DOMAINS IN MYDESTINATION.
# MYDESTINATION MUST LIST NON-VIRTUAL DOMAINS ONLY.
# #
#local_recipient_maps = $alias_maps unix:passwd.byname #local_recipient_maps = $alias_maps unix:passwd.byname

View File

@ -35,7 +35,7 @@ case $daemon_directory in
exit 1 exit 1
esac esac
LOGGER="$command_directory/postlog -t postfix-script" LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-script"
INFO="$LOGGER -p info" INFO="$LOGGER -p info"
WARN="$LOGGER -p warn" WARN="$LOGGER -p warn"
ERROR="$LOGGER -p error" ERROR="$LOGGER -p error"

View File

@ -35,7 +35,7 @@ case $daemon_directory in
exit 1 exit 1
esac esac
LOGGER="$command_directory/postlog -t postfix-script" LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-script"
INFO="$LOGGER -p info" INFO="$LOGGER -p info"
WARN="$LOGGER -p warn" WARN="$LOGGER -p warn"
ERROR="$LOGGER -p error" ERROR="$LOGGER -p error"

View File

@ -4,6 +4,16 @@
# This file contains example settings of Postfix configuration # This file contains example settings of Postfix configuration
# parameters that control compatibility with broken software. # parameters that control compatibility with broken software.
# The broken_sasl_auth_clients controls inter-operability with SMTP
# clients that do not recognize that Postfix supports RFC 2554 (AUTH
# command). Examples of such clients are MicroSoft Outlook Express
# version 4 and MicroSoft Exchange version 5.0.
#
# Specify broken_sasl_auth_clients=yes to have Postfix advertise
# AUTH support in a non-standard way.
#
broken_sasl_auth_clients = no
# The ignore_mx_lookup_error parameter controls what happens when a # The ignore_mx_lookup_error parameter controls what happens when a
# name server fails to respond to an MX lookup request. By default, # name server fails to respond to an MX lookup request. By default,
# Postfix defers delivery and tries again after some delay. Specify # Postfix defers delivery and tries again after some delay. Specify

View File

@ -360,6 +360,18 @@ relocated_maps =
# #
syslog_facility = mail syslog_facility = mail
# The syslog_name parameter specifies the mail system name that is
# prepended to the process name in syslog records headers, so that
# "smtpd" becomes "postfix/smtpd".
#
# Beware: a non-default syslog_name setting takes effect only
# after process initialization. Some initialization errors will be
# logged with the default name, especially errors while parsing
# the command line and errors while accessing the Postfix main.cf
# configuration file.
#
syslog_name = postfix
# The trigger_timeout parameter limits the time to send a trigger to # The trigger_timeout parameter limits the time to send a trigger to
# a Postfix daemon. This prevents programs from getting stuck when the # a Postfix daemon. This prevents programs from getting stuck when the
# mail system is under heavy load. # mail system is under heavy load.

View File

@ -87,7 +87,7 @@ ACCESS(5) ACCESS(5)
octets separated by ".". octets separated by ".".
<b>ACTIONS</b> <b>ACTIONS</b>
[<b>45</b>]<i>XX</i> <i>text</i> [<b>45</b>]<i>NN</i> <i>text</i>
Reject the address etc. that matches the pattern, Reject the address etc. that matches the pattern,
and respond with the numerical code and text. and respond with the numerical code and text.
@ -97,7 +97,7 @@ ACCESS(5) ACCESS(5)
<b>OK</b> Accept the address etc. that matches the pattern. <b>OK</b> Accept the address etc. that matches the pattern.
<i>restriction...</i> <i>restriction...</i>
Apply the named UCE restriction (<b>permit</b>, reject, Apply the named UCE restriction(s) (<b>permit</b>, reject,
<b>reject</b><i>_</i><b>unauth</b><i>_</i><b>destination</b>, and so on). <b>reject</b><i>_</i><b>unauth</b><i>_</i><b>destination</b>, and so on).
<b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b> <b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b>

View File

@ -24,6 +24,8 @@
<li><a href="#poppers">POP or IMAP problems</a> <li><a href="#poppers">POP or IMAP problems</a>
<li><a href="#systems">Problems with specific Operating Systems</a>
<li><a href="#warnings">Postfix warnings and error messages</a> <li><a href="#warnings">Postfix warnings and error messages</a>
<li><a href="#example_config">Example configurations</a> <li><a href="#example_config">Example configurations</a>
@ -74,8 +76,18 @@
<li><a href="#noalias">What does "fatal: open database /etc/aliases.db" mean?</a> <li><a href="#noalias">What does "fatal: open database /etc/aliases.db" mean?</a>
<li><a href="#noservice">What does "fatal: unknown service: smtp/tcp" mean?</a>
<li><a href="#nosuid">sendmail has set-uid root file permissions, or is run from a set-uid root process</a> <li><a href="#nosuid">sendmail has set-uid root file permissions, or is run from a set-uid root process</a>
<li><a href="#whoami">sendmail: unable to find out your login name</a>
<li><a href="#unknown_virtual_loop">Mail for unknown users in
virtual domains fails with "mail loops back to myself"</a>
<li><a href="#virtual_relay">Postfix refuses mail for virtual
domains with "relay access denied"</a>
</ul> </ul>
<p> <p>
@ -186,6 +198,8 @@ domains with "relay access denied"</a>
<li><a href="#skip_greeting">Postfix does not try all the MX addresses</a> <li><a href="#skip_greeting">Postfix does not try all the MX addresses</a>
<li><a href="#noservice">What does "fatal: unknown service: smtp/tcp" mean?</a>
</ul> </ul>
<a name="local_delivery"><h3>Local (non-virtual) delivery</h3> <a name="local_delivery"><h3>Local (non-virtual) delivery</h3>
@ -311,6 +325,36 @@ mailbox</a>
</ul> </ul>
<p>
<a name="systems"><h3>Problems with specific Operating Systems</h3>
<p>
<ul>
<li><a href="#compaq">Problems with Compaq</a>
<li><a href="#irix">Problems with IRIX</a>
</ul>
<a name="compaq"><h3>Problems with Compaq</h3>
<ul>
<li><a href="#compaq-chmod">Compaq mail blackhole problem</a>
</ul>
<a name="irix"><h3>Problems with IRIX</h3>
<ul>
<li><a href="#sgistruct">IRIX problems translating IP address to string</a>
</ul>
<hr> <hr>
<a name="poppers"><h3>POP or IMAP problems</h3> <a name="poppers"><h3>POP or IMAP problems</h3>
@ -970,6 +1014,30 @@ PERMISSION_SECURITY="secure local"
<hr> <hr>
<a name="whoami"><h3>sendmail: unable to find out your login name</h3>
This message is logged when submitting mail from a process with a
userid that does not exist in the UNIX password file. Postfix uses
this information in order to set the envelope sender address.
<p>
The envelope sender address is also the default value for the From:
header address, when none is specified in the message.
<p>
To fix, specify the envelope sender address on the sendmail command
line:
<blockquote>
<pre>
sendmail -f user@domain ...
</pre>
</blockquote>
<hr>
<a name="moby-freebsd"><h3>Running hundreds of Postfix processes on FreeBSD</h3></a> <a name="moby-freebsd"><h3>Running hundreds of Postfix processes on FreeBSD</h3></a>
With hundreds of Postfix processes, the kernel will eventually With hundreds of Postfix processes, the kernel will eventually
@ -1112,32 +1180,41 @@ depending on the interface that it is supposed to handle.
<a name="delay"><h3>Postfix responds slowly to incoming SMTP connections</h3></a> <a name="delay"><h3>Postfix responds slowly to incoming SMTP connections</h3></a>
<dl> Question:
<dt>Question: <blockquote>
<dd> My Postfix server is too slow. When I telnet to the SMTP port My Postfix server is too slow. When I telnet to the SMTP port
(<tt>telnet hostname 25</tt>), the response comes after 40 seconds. (<tt>telnet hostname 25</tt>), the response comes after 40 seconds.
On the other hand, when I telnet to the the POP port (<tt>telnet On the other hand, when I telnet to the the POP port (<tt>telnet
hostname 110</tt>) the response comes with no delay. hostname 110</tt>) the response comes with no delay.
<p> </blockquote>
<dt>Answer:
<dd>
This is a DNS configuration problem. Postfix tries to resolve the
SMTP client IP address to a hostname. Apparently, your POP server
does not look up POP clients.
<p> <p>
The fix is to properly configure the naming service. If you can't Answer:
have every host in the DNS, then configure the mail server to look
in /etc/hosts before the DNS, and specify the clients in /etc/hosts.
</dl> <blockquote>
You have a name service problem.
<p>
Postfix calls the C library routines <b>gethostbyname()</b> and
<b>gethostbyaddr()</b> in order to find out the SMTP client hostname.
These library routines use several system configuration files in
order to satisfy the request. They may in fact end up calling the
DNS for reasons that are not under control by Postfix.
<p>
Depending on your system, these controlling files can be named
<b>/etc/nsswitch.conf</b>, <b>/etc/svcorder</b>, <b>/etc/host.conf</b>
or otherwise. Those files specify whether the C library routines
will use local <b>/etc/hosts</b> before or after DNS.
</blockquote>
<hr> <hr>
@ -1733,6 +1810,35 @@ use the command <b>postconf mail_version</b>.
Execute the command <b>postfix reload</b> to make the change Execute the command <b>postfix reload</b> to make the change
effective immediately. effective immediately.
<a name="noservice"><h3>What does "fatal: unknown service: smtp/tcp"
mean?</h3>
The Postfix <b>/etc/postfix/master.cf</b> file specifies that the
Postfix SMTP client runs inside a <b>chroot</b> environment. However,
the files necessary for that mode of operation are not installed
below <b>/var/spool/postfix</b>.
<p>
Enabling <b>chroot</b> operation adds a non-trivial barrier for
system penetrators.
<p>
Two solutions:
<ul>
<li> Disable the <b>chroot</b> in <b>/etc/postfix/master.cf</b>
(and issue <b>postfix reload</b> when done).
<p>
<li>Install the necessary files for <b>chroot</b> operation.
Instructions are given in the source code distribution, in the
<b>examples/chroot-setup</b> directory.
</ul>
<hr> <hr>
<a name="root"> <h3>Root's mail is delivered to nobody</h3> <a name="root"> <h3>Root's mail is delivered to nobody</h3>
@ -2300,6 +2406,11 @@ virtual domain.
<p> <p>
Sendmail-style virtual domains are not supported in Postfix versions
released before 20001118.
<p>
Be sure to follow instructions in the <a href="virtual.5.html"> Be sure to follow instructions in the <a href="virtual.5.html">
virtual</a> manual page. virtual</a> manual page.
@ -2909,6 +3020,36 @@ href="http://www.isc.org/"> http://www.isc.org/</a>.
<hr> <hr>
<a name="compaq-chmod"><h3>Compaq mail blackhole problem</h3>
On some Compaq Tru64 UNIX configurations, Postfix will receive mail
and then nothing happens. The mail does not even show up with the
<b>mailq</b> command.
<p>
Postfix sets the execute bit on a queue file to indicate that it
is done receiving a message. As long as a queue file does not have
the execute bit set, Postfix will ignore it as "mail still being
received".
<p>
With enhanced security enabled, Compaq Tru64 UNIX has a feature
that disallows non-superuser attempts to set the execute bit on a
queuefile. Unfortunately, Postfix is never informed that such
attempts fail, and mail seems to disappear into a black hole.
<p>
Postfix could be modified to use some other bit than the execute
bit, but that might equally well fail on other systems. Another
possibility is to allow non-superusers to set the execute bit on
files, and to mount the Postfix queue file system with the
<b>noexec</b> option or equivalent.
<hr>
<a href="index.html">Up one level</a> | Postfix FAQ <a href="index.html">Up one level</a> | Postfix FAQ
</body> </body>

View File

@ -13,11 +13,9 @@ PIPE(8) PIPE(8)
<b>DESCRIPTION</b> <b>DESCRIPTION</b>
The <b>pipe</b> daemon processes requests from the Postfix queue The <b>pipe</b> daemon processes requests from the Postfix queue
manager to deliver messages to external commands. Each manager to deliver messages to external commands. This
delivery request specifies a queue file, a sender address, program expects to be run from the <a href="master.8.html"><b>master</b>(8)</a> process man-
a domain or host to deliver to, and one or more recipi- ager.
ents. This program expects to be run from the <a href="master.8.html"><b>master</b>(8)</a>
process manager.
The <b>pipe</b> daemon updates queue files and marks recipients The <b>pipe</b> daemon updates queue files and marks recipients
as finished, or it informs the queue manager that delivery as finished, or it informs the queue manager that delivery
@ -25,6 +23,20 @@ PIPE(8) PIPE(8)
reports are sent to the <a href="bounce.8.html"><b>bounce</b>(8)</a> or <a href="defer.8.html"><b>defer</b>(8)</a> daemon as reports are sent to the <a href="bounce.8.html"><b>bounce</b>(8)</a> or <a href="defer.8.html"><b>defer</b>(8)</a> daemon as
appropriate. appropriate.
<b>SINGLE-RECIPIENT</b> <b>DELIVERY</b>
Some external commands cannot handle more than one recipi-
ent per delivery request. Examples of such transports are
pagers, fax machines, and so on.
To prevent Postfix from sending multiple recipients per
delivery request, specify
<i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> <b>=</b> <b>1</b>
in the Postfix <b>main.cf</b> file, where <i>transport</i> is the name
in the first column of the Postfix <b>master.cf</b> entry for the
pipe-based delivery transport.
<b>COMMAND</b> <b>ATTRIBUTE</b> <b>SYNTAX</b> <b>COMMAND</b> <b>ATTRIBUTE</b> <b>SYNTAX</b>
The external command attributes are given in the <b>master.cf</b> The external command attributes are given in the <b>master.cf</b>
file at the end of a service definition. The syntax is as file at the end of a service definition. The syntax is as
@ -47,18 +59,6 @@ PIPE(8) PIPE(8)
the envelope sender address. the envelope sender address.
<b>.</b> Prepend <b>.</b> to lines starting with "<b>.</b>". This <b>.</b> Prepend <b>.</b> to lines starting with "<b>.</b>". This
is needed by, for example, <b>BSMTP</b> software.
&gt; Prepend &gt; to lines starting with "<b>From</b> ".
This is expected by, for example, <b>UUCP</b> soft-
ware.
<b>user</b>=<i>username</i> (required)
<b>user</b>=<i>username</i>:<i>groupname</i>
The external command is executed with the rights of
the specified <i>username</i>. The software refuses to
execute commands with root privileges, or with the
@ -71,6 +71,18 @@ PIPE(8) PIPE(8)
PIPE(8) PIPE(8) PIPE(8) PIPE(8)
is needed by, for example, <b>BSMTP</b> software.
&gt; Prepend &gt; to lines starting with "<b>From</b> ".
This is expected by, for example, <b>UUCP</b> soft-
ware.
<b>user</b>=<i>username</i> (required)
<b>user</b>=<i>username</i>:<i>groupname</i>
The external command is executed with the rights of
the specified <i>username</i>. The software refuses to
execute commands with root privileges, or with the
privileges of the mail system owner. If <i>groupname</i> privileges of the mail system owner. If <i>groupname</i>
is specified, the corresponding group ID is used is specified, the corresponding group ID is used
instead of the group ID of <i>username</i>. instead of the group ID of <i>username</i>.
@ -101,7 +113,9 @@ PIPE(8) PIPE(8)
This macro expands to the extension part of This macro expands to the extension part of
a recipient address. For example, with an a recipient address. For example, with an
address <i>user+foo@domain</i> the extension is address <i>user+foo@domain</i> the extension is
<i>foo</i>. A command-line argument that contains <i>foo</i>.
A command-line argument that contains
<b>${extension</b>} expands into as many command- <b>${extension</b>} expands into as many command-
line arguments as there are recipients. line arguments as there are recipients.
@ -109,22 +123,8 @@ PIPE(8) PIPE(8)
This macro expands to the complete local This macro expands to the complete local
part of a recipient address. For example, part of a recipient address. For example,
with an address <i>user+foo@domain</i> the mailbox with an address <i>user+foo@domain</i> the mailbox
is <i>user+foo</i>. A command-line argument that is <i>user+foo</i>.
contains <b>${mailbox</b>} expands into as many
command-line arguments as there are recipi-
ents.
<b>${nexthop</b>}
This macro expands to the next-hop hostname.
<b>${recipient</b>}
This macro expands to the complete recipient
address. A command-line argument that con-
tains <b>${recipient</b>} expands into as many com-
mand-line arguments as there are recipients.
<b>${sender</b>}
This macro expands to the envelope sender
@ -137,6 +137,23 @@ PIPE(8) PIPE(8)
PIPE(8) PIPE(8) PIPE(8) PIPE(8)
A command-line argument that contains
<b>${mailbox</b>} expands into as many command-line
arguments as there are recipients.
<b>${nexthop</b>}
This macro expands to the next-hop hostname.
<b>${recipient</b>}
This macro expands to the complete recipient
address.
A command-line argument that contains
<b>${recipient</b>} expands into as many command-
line arguments as there are recipients.
<b>${sender</b>}
This macro expands to the envelope sender
address. address.
<b>${size</b>} <b>${size</b>}
@ -148,7 +165,9 @@ PIPE(8) PIPE(8)
This macro expands to the username part of a This macro expands to the username part of a
recipient address. For example, with an recipient address. For example, with an
address <i>user+foo@domain</i> the username part is address <i>user+foo@domain</i> the username part is
<i>user</i>. A command-line argument that contains <i>user</i>.
A command-line argument that contains
<b>${user</b>} expands into as many command-line <b>${user</b>} expands into as many command-line
arguments as there are recipients. arguments as there are recipients.
@ -172,6 +191,18 @@ PIPE(8) PIPE(8)
<b>CONFIGURATION</b> <b>PARAMETERS</b> <b>CONFIGURATION</b> <b>PARAMETERS</b>
The following <b>main.cf</b> parameters are especially relevant The following <b>main.cf</b> parameters are especially relevant
3
PIPE(8) PIPE(8)
to this program. See the Postfix <b>main.cf</b> file for syntax to this program. See the Postfix <b>main.cf</b> file for syntax
details and for default values. Use the <b>postfix</b> <b>reload</b> details and for default values. Use the <b>postfix</b> <b>reload</b>
command after a configuration change. command after a configuration change.
@ -191,18 +222,6 @@ PIPE(8) PIPE(8)
<i>transport_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> <i>transport_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same Limit the number of parallel deliveries to the same
3
PIPE(8) PIPE(8)
destination, for delivery via the named <i>transport</i>. destination, for delivery via the named <i>transport</i>.
The default limit is taken from the <b>default</b><i>_</i><b>desti-</b> The default limit is taken from the <b>default</b><i>_</i><b>desti-</b>
<b>nation</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter. The limit is <b>nation</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter. The limit is
@ -239,25 +258,6 @@ PIPE(8) PIPE(8)
Yorktown Heights, NY 10598, USA Yorktown Heights, NY 10598, USA
4 4

View File

@ -69,7 +69,7 @@ address is a sequence of one or more octets separated by ".".
.nf .nf
.ad .ad
.fi .fi
.IP "[\fB45\fR]\fIXX text\fR" .IP "[\fB45\fR]\fINN text\fR"
Reject the address etc. that matches the pattern, and respond with Reject the address etc. that matches the pattern, and respond with
the numerical code and text. the numerical code and text.
.IP \fBREJECT\fR .IP \fBREJECT\fR
@ -78,7 +78,7 @@ error response message is generated.
.IP \fBOK\fR .IP \fBOK\fR
Accept the address etc. that matches the pattern. Accept the address etc. that matches the pattern.
.IP \fIrestriction...\fR .IP \fIrestriction...\fR
Apply the named UCE restriction (\fBpermit\fR, \fRreject\fR, Apply the named UCE restriction(s) (\fBpermit\fR, \fRreject\fR,
\fBreject_unauth_destination\fR, and so on). \fBreject_unauth_destination\fR, and so on).
.SH REGULAR EXPRESSION TABLES .SH REGULAR EXPRESSION TABLES
.na .na

View File

@ -13,9 +13,7 @@ Postfix delivery to external command
.ad .ad
.fi .fi
The \fBpipe\fR daemon processes requests from the Postfix queue The \fBpipe\fR daemon processes requests from the Postfix queue
manager to deliver messages to external commands. Each delivery manager to deliver messages to external commands.
request specifies a queue file, a sender address, a domain or host
to deliver to, and one or more recipients.
This program expects to be run from the \fBmaster\fR(8) process This program expects to be run from the \fBmaster\fR(8) process
manager. manager.
@ -23,6 +21,24 @@ The \fBpipe\fR daemon updates queue files and marks recipients
as finished, or it informs the queue manager that delivery should as finished, or it informs the queue manager that delivery should
be tried again at a later time. Delivery problem reports are sent be tried again at a later time. Delivery problem reports are sent
to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate. to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
.SH SINGLE-RECIPIENT DELIVERY
.na
.nf
.ad
.fi
Some external commands cannot handle more than one recipient
per delivery request. Examples of such transports are pagers,
fax machines, and so on.
To prevent Postfix from sending multiple recipients per delivery
request, specify
.ti +4
\fItransport\fB_destination_recipient_limit = 1\fR
in the Postfix \fBmain.cf\fR file, where \fItransport\fR
is the name in the first column of the Postfix \fBmaster.cf\fR
entry for the pipe-based delivery transport.
.SH COMMAND ATTRIBUTE SYNTAX .SH COMMAND ATTRIBUTE SYNTAX
.na .na
.nf .nf
@ -82,18 +98,21 @@ manager delivery request:
This macro expands to the extension part of a recipient address. This macro expands to the extension part of a recipient address.
For example, with an address \fIuser+foo@domain\fR the extension is For example, with an address \fIuser+foo@domain\fR the extension is
\fIfoo\fR. \fIfoo\fR.
.sp
A command-line argument that contains \fB${\fBextension\fR}\fR expands A command-line argument that contains \fB${\fBextension\fR}\fR expands
into as many command-line arguments as there are recipients. into as many command-line arguments as there are recipients.
.IP \fB${\fBmailbox\fR}\fR .IP \fB${\fBmailbox\fR}\fR
This macro expands to the complete local part of a recipient address. This macro expands to the complete local part of a recipient address.
For example, with an address \fIuser+foo@domain\fR the mailbox is For example, with an address \fIuser+foo@domain\fR the mailbox is
\fIuser+foo\fR. \fIuser+foo\fR.
.sp
A command-line argument that contains \fB${\fBmailbox\fR}\fR A command-line argument that contains \fB${\fBmailbox\fR}\fR
expands into as many command-line arguments as there are recipients. expands into as many command-line arguments as there are recipients.
.IP \fB${\fBnexthop\fR}\fR .IP \fB${\fBnexthop\fR}\fR
This macro expands to the next-hop hostname. This macro expands to the next-hop hostname.
.IP \fB${\fBrecipient\fR}\fR .IP \fB${\fBrecipient\fR}\fR
This macro expands to the complete recipient address. This macro expands to the complete recipient address.
.sp
A command-line argument that contains \fB${\fBrecipient\fR}\fR A command-line argument that contains \fB${\fBrecipient\fR}\fR
expands into as many command-line arguments as there are recipients. expands into as many command-line arguments as there are recipients.
.IP \fB${\fBsender\fR}\fR .IP \fB${\fBsender\fR}\fR
@ -105,6 +124,7 @@ is an approximation of the size of the message as delivered.
This macro expands to the username part of a recipient address. This macro expands to the username part of a recipient address.
For example, with an address \fIuser+foo@domain\fR the username For example, with an address \fIuser+foo@domain\fR the username
part is \fIuser\fR. part is \fIuser\fR.
.sp
A command-line argument that contains \fB${\fBuser\fR}\fR expands A command-line argument that contains \fB${\fBuser\fR}\fR expands
into as many command-line arguments as there are recipients. into as many command-line arguments as there are recipients.
.RE .RE

View File

@ -57,7 +57,7 @@
# ACTIONS # ACTIONS
# .ad # .ad
# .fi # .fi
# .IP "[\fB45\fR]\fIXX text\fR" # .IP "[\fB45\fR]\fINN text\fR"
# Reject the address etc. that matches the pattern, and respond with # Reject the address etc. that matches the pattern, and respond with
# the numerical code and text. # the numerical code and text.
# .IP \fBREJECT\fR # .IP \fBREJECT\fR
@ -66,7 +66,7 @@
# .IP \fBOK\fR # .IP \fBOK\fR
# Accept the address etc. that matches the pattern. # Accept the address etc. that matches the pattern.
# .IP \fIrestriction...\fR # .IP \fIrestriction...\fR
# Apply the named UCE restriction (\fBpermit\fR, \fRreject\fR, # Apply the named UCE restriction(s) (\fBpermit\fR, \fRreject\fR,
# \fBreject_unauth_destination\fR, and so on). # \fBreject_unauth_destination\fR, and so on).
# REGULAR EXPRESSION TABLES # REGULAR EXPRESSION TABLES
# .ad # .ad

View File

@ -182,7 +182,6 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf,
* straightforward. * straightforward.
*/ */
if (vstream_fflush(state->dst)) { if (vstream_fflush(state->dst)) {
msg_warn("%s: write queue file: %m", state->queue_id);
if (errno == EFBIG) { if (errno == EFBIG) {
msg_warn("%s: queue file size limit exceeded", state->queue_id); msg_warn("%s: queue file size limit exceeded", state->queue_id);
state->errs |= CLEANUP_STAT_SIZE; state->errs |= CLEANUP_STAT_SIZE;

View File

@ -129,6 +129,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <utime.h> #include <utime.h>
#include <errno.h> #include <errno.h>
#include <ctype.h>
/* Utility library. */ /* Utility library. */
@ -182,10 +183,44 @@ static DOMAIN_LIST *flush_domains;
/* /*
* Silly little macros. * Silly little macros.
*/ */
#define STR(x) vstring_str(x) #define STR(x) vstring_str(x)
#define STREQ(x,y) (strcmp(x,y) == 0) #define STREQ(x,y) (strcmp(x,y) == 0)
/*
* Forward declarations for where we broke routines along their name space
* domain boundaries (actually, hostnames versus safe-to-use pathnames).
*/
static int flush_add_path(const char *, const char *);
static int flush_send_path(const char *);
/* flush_site_to_path - convert domain or [addr] to harmless string */
static VSTRING *flush_site_to_path(VSTRING *path, const char *site)
{
int ch;
/*
* Allocate buffer on the fly; caller still needs to clean up.
*/
if (path == 0)
path = vstring_alloc(10);
/*
* Convert character values to hexadecimal.
*/
while ((ch = *(unsigned const char *) site++) != 0)
if (ISALNUM(ch))
VSTRING_ADDCH(path, ch);
else
VSTRING_ADDCH(path, '_');
VSTRING_TERMINATE(path);
if (msg_verbose)
msg_info("site %s to path %s", site, STR(path));
return (path);
}
/* flush_policy_ok - check logging policy */ /* flush_policy_ok - check logging policy */
static int flush_policy_ok(const char *site) static int flush_policy_ok(const char *site)
@ -193,12 +228,13 @@ static int flush_policy_ok(const char *site)
return (domain_list_match(flush_domains, site)); return (domain_list_match(flush_domains, site));
} }
/* flush_add_service - append queue ID to per-site fast flush log */ /* flush_add_service - append queue ID to per-site fast flush logfile */
static int flush_add_service(const char *site, const char *queue_id) static int flush_add_service(const char *site, const char *queue_id)
{ {
char *myname = "flush_add_service"; char *myname = "flush_add_service";
VSTREAM *log; VSTRING *site_path;
int status;
if (msg_verbose) if (msg_verbose)
msg_info("%s: site %s queue_id %s", myname, site, queue_id); msg_info("%s: site %s queue_id %s", myname, site, queue_id);
@ -209,13 +245,29 @@ static int flush_add_service(const char *site, const char *queue_id)
if (flush_policy_ok(site) == 0) if (flush_policy_ok(site) == 0)
return (FLUSH_STAT_OK); return (FLUSH_STAT_OK);
/*
* Map site to path and update log.
*/
site_path = flush_site_to_path((VSTRING *) 0, site);
status = flush_add_path(STR(site_path), queue_id);
vstring_free(site_path);
return (status);
}
/* flush_add_path - add record to log */
static int flush_add_path(const char *path, const char *queue_id)
{
char *myname = "flush_add_path";
VSTREAM *log;
/* /*
* Open the logfile or bust. * Open the logfile or bust.
*/ */
if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, site, if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, path,
O_CREAT | O_APPEND | O_WRONLY, 0600)) == 0) O_CREAT | O_APPEND | O_WRONLY, 0600)) == 0)
msg_fatal("%s: open fast flush log for site %s: %m", msg_fatal("%s: open fast flush logfile %s: %m", myname, path);
myname, site);
/* /*
* We must lock the logfile, so that we don't lose information due to * We must lock the logfile, so that we don't lose information due to
@ -223,7 +275,7 @@ static int flush_add_service(const char *site, const char *queue_id)
* will eventually take care of the problem, but it will take a while. * will eventually take care of the problem, but it will take a while.
*/ */
if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0) if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock fast flush log for site %s: %m", myname, site); msg_fatal("%s: lock fast flush logfile %s: %m", myname, path);
/* /*
* Append the queue ID. With 15 bits if microsecond time, a queue ID is * Append the queue ID. With 15 bits if microsecond time, a queue ID is
@ -237,10 +289,9 @@ static int flush_add_service(const char *site, const char *queue_id)
* Clean up. * Clean up.
*/ */
if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0) if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock fast flush log for site %s: %m", msg_fatal("%s: unlock fast flush logfile %s: %m", myname, path);
myname, site);
if (vstream_fclose(log) != 0) if (vstream_fclose(log) != 0)
msg_warn("write fast flush log for site %s: %m", site); msg_warn("write fast flush logfile %s: %m", path);
return (FLUSH_STAT_OK); return (FLUSH_STAT_OK);
} }
@ -250,16 +301,8 @@ static int flush_add_service(const char *site, const char *queue_id)
static int flush_send_service(const char *site) static int flush_send_service(const char *site)
{ {
char *myname = "flush_send_service"; char *myname = "flush_send_service";
VSTRING *queue_id; VSTRING *site_path;
VSTRING *queue_file; int status;
VSTREAM *log;
struct utimbuf tbuf;
static char qmgr_trigger[] = {
QMGR_REQ_SCAN_INCOMING, /* scan incoming queue */
QMGR_REQ_FLUSH_DEAD, /* flush dead site/transport cache */
};
HTABLE *dup_filter;
int count;
if (msg_verbose) if (msg_verbose)
msg_info("%s: site %s", myname, site); msg_info("%s: site %s", myname, site);
@ -270,13 +313,39 @@ static int flush_send_service(const char *site)
if (flush_policy_ok(site) == 0) if (flush_policy_ok(site) == 0)
return (mail_flush_deferred()); return (mail_flush_deferred());
/*
* Map site name to path name and flush the log.
*/
site_path = flush_site_to_path((VSTRING *) 0, site);
status = flush_send_path(STR(site_path));
vstring_free(site_path);
return (status);
}
/* flush_send_path - flush logfile file */
static int flush_send_path(const char *path)
{
const char *myname = "flush_send_path";
VSTRING *queue_id;
VSTRING *queue_file;
VSTREAM *log;
struct utimbuf tbuf;
static char qmgr_trigger[] = {
QMGR_REQ_SCAN_INCOMING, /* scan incoming queue */
QMGR_REQ_FLUSH_DEAD, /* flush dead site/transport cache */
};
HTABLE *dup_filter;
int count;
/* /*
* Open the logfile. If the file does not exist, then there is no queued * Open the logfile. If the file does not exist, then there is no queued
* mail for this destination. * mail for this destination.
*/ */
if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, site, O_RDWR, 0600)) == 0) { if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, path, O_RDWR, 0600)) == 0) {
if (errno != ENOENT) if (errno != ENOENT)
msg_fatal("%s: open fast flush log for site %s: %m", myname, site); msg_fatal("%s: open fast flush logfile %s: %m", myname, path);
return (FLUSH_STAT_OK); return (FLUSH_STAT_OK);
} }
@ -287,7 +356,7 @@ static int flush_send_service(const char *site)
* watchdog will take care of it. * watchdog will take care of it.
*/ */
if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0) if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock fast flush log for site %s: %m", myname, site); msg_fatal("%s: lock fast flush logfile %s: %m", myname, path);
/* /*
* This is the part that dominates running time: schedule the listed * This is the part that dominates running time: schedule the listed
@ -312,15 +381,15 @@ static int flush_send_service(const char *site)
tbuf.actime = tbuf.modtime = event_time(); tbuf.actime = tbuf.modtime = event_time();
for (count = 0; vstring_get_nonl(queue_id, log) != VSTREAM_EOF; count++) { for (count = 0; vstring_get_nonl(queue_id, log) != VSTREAM_EOF; count++) {
if (!mail_queue_id_ok(STR(queue_id))) { if (!mail_queue_id_ok(STR(queue_id))) {
msg_warn("bad queue id \"%.30s...\" in fast flush log for site %s", msg_warn("bad queue id \"%.30s...\" in fast flush logfile %s",
STR(queue_id), site); STR(queue_id), path);
continue; continue;
} }
if (dup_filter->used >= FLUSH_DUP_FILTER_SIZE if (dup_filter->used >= FLUSH_DUP_FILTER_SIZE
|| htable_find(dup_filter, STR(queue_id)) == 0) { || htable_find(dup_filter, STR(queue_id)) == 0) {
if (msg_verbose) if (msg_verbose)
msg_info("%s: site %s: update %s time stamps", msg_info("%s: logfile %s: update queue file %s time stamps",
myname, site, STR(queue_id)); myname, path, STR(queue_id));
if (dup_filter->used <= FLUSH_DUP_FILTER_SIZE) if (dup_filter->used <= FLUSH_DUP_FILTER_SIZE)
htable_enter(dup_filter, STR(queue_id), 0); htable_enter(dup_filter, STR(queue_id), 0);
@ -344,8 +413,8 @@ static int flush_send_service(const char *site)
} }
} else { } else {
if (msg_verbose) if (msg_verbose)
msg_info("%s: site %s: skip file %s as duplicate", msg_info("%s: logfile %s: skip queue file %s as duplicate",
myname, site, STR(queue_file)); myname, path, STR(queue_file));
} }
} }
htable_free(dup_filter, (void (*) (char *)) 0); htable_free(dup_filter, (void (*) (char *)) 0);
@ -356,19 +425,18 @@ static int flush_send_service(const char *site)
* Truncate the fast flush log. * Truncate the fast flush log.
*/ */
if (count > 0 && ftruncate(vstream_fileno(log), (off_t) 0) < 0) if (count > 0 && ftruncate(vstream_fileno(log), (off_t) 0) < 0)
msg_fatal("%s: truncate fast flush log for site %s: %m", myname, site); msg_fatal("%s: truncate fast flush logfile %s: %m", myname, path);
/* /*
* Request delivery and clean up. * Request delivery and clean up.
*/ */
if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0) if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
msg_fatal("%s: unlock fast flush log for site %s: %m", msg_fatal("%s: unlock fast flush logfile %s: %m", myname, path);
myname, site);
if (vstream_fclose(log) != 0) if (vstream_fclose(log) != 0)
msg_warn("read fast flush log for site %s: %m", site); msg_warn("%s: read fast flush logfile %s: %m", myname, path);
if (count > 0) { if (count > 0) {
if (msg_verbose) if (msg_verbose)
msg_info("%s: requesting delivery for site %s", myname, site); msg_info("%s: requesting delivery for logfile %s", myname, path);
mail_trigger(MAIL_CLASS_PUBLIC, MAIL_SERVICE_QUEUE, mail_trigger(MAIL_CLASS_PUBLIC, MAIL_SERVICE_QUEUE,
qmgr_trigger, sizeof(qmgr_trigger)); qmgr_trigger, sizeof(qmgr_trigger));
} }
@ -381,23 +449,15 @@ static int flush_refresh_service(int max_age)
{ {
char *myname = "flush_refresh_service"; char *myname = "flush_refresh_service";
SCAN_DIR *scan; SCAN_DIR *scan;
char *site; char *site_path;
struct stat st; struct stat st;
VSTRING *path = vstring_alloc(10); VSTRING *path = vstring_alloc(10);
scan = scan_dir_open(MAIL_QUEUE_FLUSH); scan = scan_dir_open(MAIL_QUEUE_FLUSH);
while ((site = mail_scan_dir_next(scan)) != 0) { while ((site_path = mail_scan_dir_next(scan)) != 0) {
if (!mail_queue_id_ok(site)) if (!mail_queue_id_ok(site_path))
continue; /* XXX grumble. */ continue; /* XXX grumble. */
mail_queue_path(path, MAIL_QUEUE_FLUSH, site); mail_queue_path(path, MAIL_QUEUE_FLUSH, site_path);
if (flush_policy_ok(site) == 0) {
if (unlink(STR(path)) < 0)
msg_warn("remove %s: %m", STR(path));
else if (msg_verbose)
msg_info("%s: spurious fast flush logfile name: %s",
myname, site);
continue;
}
if (stat(STR(path), &st) < 0) { if (stat(STR(path), &st) < 0) {
if (errno != ENOENT) if (errno != ENOENT)
msg_warn("%s: stat %s: %m", myname, STR(path)); msg_warn("%s: stat %s: %m", myname, STR(path));
@ -413,15 +473,15 @@ static int flush_refresh_service(int max_age)
msg_info("%s: unlink %s, empty and unchanged for %d days", msg_info("%s: unlink %s, empty and unchanged for %d days",
myname, STR(path), var_fflush_purge / 86400); myname, STR(path), var_fflush_purge / 86400);
} else if (msg_verbose) } else if (msg_verbose)
msg_info("%s: skip site %s - empty log", myname, site); msg_info("%s: skip logfile %s - empty log", myname, site_path);
} else if (st.st_atime + max_age < event_time()) { } else if (st.st_atime + max_age < event_time()) {
if (msg_verbose) if (msg_verbose)
msg_info("%s: flush site %s", myname, site); msg_info("%s: flush logfile %s", myname, site_path);
flush_send_service(site); flush_send_path(site_path);
} else { } else {
if (msg_verbose) if (msg_verbose)
msg_info("%s: skip site %s, unread for <%d hours(s) ", msg_info("%s: skip logfile %s, unread for <%d hours(s) ",
myname, site, max_age / 3600); myname, site_path, max_age / 3600);
} }
} }
scan_dir_close(scan); scan_dir_close(scan);
@ -466,14 +526,12 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
site = vstring_alloc(10); site = vstring_alloc(10);
queue_id = vstring_alloc(10); queue_id = vstring_alloc(10);
if (mail_command_read(client_stream, "%s %s", site, queue_id) == 2 if (mail_command_read(client_stream, "%s %s", site, queue_id) == 2
&& valid_hostname(STR(site), DONT_GRIPE)
&& mail_queue_id_ok(STR(queue_id))) && mail_queue_id_ok(STR(queue_id)))
status = flush_add_service(lowercase(STR(site)), STR(queue_id)); status = flush_add_service(lowercase(STR(site)), STR(queue_id));
mail_print(client_stream, "%d", status); mail_print(client_stream, "%d", status);
} else if (STREQ(STR(request), FLUSH_REQ_SEND)) { } else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
site = vstring_alloc(10); site = vstring_alloc(10);
if (mail_command_read(client_stream, "%s", site) == 1 if (mail_command_read(client_stream, "%s", site) == 1)
&& valid_hostname(STR(site), DONT_GRIPE))
status = flush_send_service(lowercase(STR(site))); status = flush_send_service(lowercase(STR(site)));
mail_print(client_stream, "%d", status); mail_print(client_stream, "%d", status);
} else if (STREQ(STR(request), FLUSH_REQ_REFRESH) } else if (STREQ(STR(request), FLUSH_REQ_REFRESH)

View File

@ -601,6 +601,7 @@ mail_params.o: ../../include/valid_hostname.h
mail_params.o: ../../include/stringops.h mail_params.o: ../../include/stringops.h
mail_params.o: ../../include/vstring.h mail_params.o: ../../include/vstring.h
mail_params.o: ../../include/vbuf.h mail_params.o: ../../include/vbuf.h
mail_params.o: ../../include/safe.h
mail_params.o: mynetworks.h mail_params.o: mynetworks.h
mail_params.o: mail_conf.h mail_params.o: mail_conf.h
mail_params.o: mail_version.h mail_params.o: mail_version.h
@ -683,7 +684,9 @@ mail_task.o: mail_task.c
mail_task.o: ../../include/sys_defs.h mail_task.o: ../../include/sys_defs.h
mail_task.o: ../../include/vstring.h mail_task.o: ../../include/vstring.h
mail_task.o: ../../include/vbuf.h mail_task.o: ../../include/vbuf.h
mail_task.o: ../../include/safe.h
mail_task.o: mail_params.h mail_task.o: mail_params.h
mail_task.o: mail_conf.h
mail_task.o: mail_task.h mail_task.o: mail_task.h
mail_trigger.o: mail_trigger.c mail_trigger.o: mail_trigger.c
mail_trigger.o: ../../include/sys_defs.h mail_trigger.o: ../../include/sys_defs.h

View File

@ -21,7 +21,8 @@
*/ */
#define CONF_ENV_PATH "MAIL_CONFIG" /* config database */ #define CONF_ENV_PATH "MAIL_CONFIG" /* config database */
#define CONF_ENV_VERB "MAIL_VERBOSE" /* verbose mode on */ #define CONF_ENV_VERB "MAIL_VERBOSE" /* verbose mode on */
#define CONF_ENV_DEBUG "MAIL_DEBUG" /* verbose mode on */ #define CONF_ENV_DEBUG "MAIL_DEBUG" /* live debugging */
#define CONF_ENV_LOGTAG "MAIL_LOGTAG" /* instance name */
/* /*
* External representation for booleans. * External representation for booleans.

View File

@ -14,6 +14,7 @@
/* char *var_transit_origin; /* char *var_transit_origin;
/* char *var_transit_dest; /* char *var_transit_dest;
/* char *var_mail_name; /* char *var_mail_name;
/* char *var_syslog_name;
/* char *var_mail_owner; /* char *var_mail_owner;
/* uid_t var_owner_uid; /* uid_t var_owner_uid;
/* gid_t var_owner_gid; /* gid_t var_owner_gid;
@ -92,6 +93,7 @@
#include <sys_defs.h> #include <sys_defs.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <pwd.h> #include <pwd.h>
#include <time.h> #include <time.h>
@ -107,6 +109,7 @@
#include <get_hostname.h> #include <get_hostname.h>
#include <valid_hostname.h> #include <valid_hostname.h>
#include <stringops.h> #include <stringops.h>
#include <safe.h>
/* Global library. */ /* Global library. */
@ -127,6 +130,7 @@ char *var_relayhost;
char *var_transit_origin; char *var_transit_origin;
char *var_transit_dest; char *var_transit_dest;
char *var_mail_name; char *var_mail_name;
char *var_syslog_name;
char *var_mail_owner; char *var_mail_owner;
uid_t var_owner_uid; uid_t var_owner_uid;
gid_t var_owner_gid; gid_t var_owner_gid;
@ -270,6 +274,7 @@ void mail_params_init()
}; };
static CONFIG_STR_TABLE other_str_defaults[] = { static CONFIG_STR_TABLE other_str_defaults[] = {
VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name, 1, 0, VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name, 1, 0,
VAR_SYSLOG_NAME, DEF_SYSLOG_NAME, &var_syslog_name, 1, 0,
VAR_MAIL_OWNER, DEF_MAIL_OWNER, &var_mail_owner, 1, 0, VAR_MAIL_OWNER, DEF_MAIL_OWNER, &var_mail_owner, 1, 0,
VAR_MYDEST, DEF_MYDEST, &var_mydest, 0, 0, VAR_MYDEST, DEF_MYDEST, &var_mydest, 0, 0,
VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin, 1, 0, VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin, 1, 0,
@ -326,6 +331,7 @@ void mail_params_init()
VAR_OWNREQ_SPECIAL, DEF_OWNREQ_SPECIAL, &var_ownreq_special, VAR_OWNREQ_SPECIAL, DEF_OWNREQ_SPECIAL, &var_ownreq_special,
0, 0,
}; };
const char *cp;
/* /*
* Extract syslog_facility early, so that from here on all errors are * Extract syslog_facility early, so that from here on all errors are
@ -376,6 +382,15 @@ void mail_params_init()
*/ */
time(&var_starttime); time(&var_starttime);
/*
* Export the syslog name so children can inherit and use it before they
* have initialized.
*/
if ((cp = safe_getenv(CONF_ENV_LOGTAG)) == 0
|| strcmp(cp, var_syslog_name) != 0)
if (setenv(CONF_ENV_LOGTAG, var_syslog_name, 1) < 0)
msg_fatal("setenv %s %s: %m", CONF_ENV_LOGTAG, var_syslog_name);
/* /*
* I have seen this happen just too often. * I have seen this happen just too often.
*/ */

View File

@ -1192,7 +1192,7 @@ extern int var_fflush_refresh;
* and what Postfix exports to the external world. * and what Postfix exports to the external world.
*/ */
#define VAR_IMPORT_ENVIRON "import_environment" #define VAR_IMPORT_ENVIRON "import_environment"
#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG TZ XAUTHORITY DISPLAY" #define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY"
extern char *var_import_environ; extern char *var_import_environ;
#define VAR_EXPORT_ENVIRON "export_environment" #define VAR_EXPORT_ENVIRON "export_environment"
@ -1230,6 +1230,13 @@ extern int var_virt_mailbox_limit;
#define DEF_VIRT_MAILBOX_LOCK "fcntl" #define DEF_VIRT_MAILBOX_LOCK "fcntl"
extern char *var_virt_mailbox_lock; extern char *var_virt_mailbox_lock;
/*
* Distinct logging tag for multiple Postfix instances.
*/
#define VAR_SYSLOG_NAME "syslog_name"
#define DEF_SYSLOG_NAME "postfix"
extern char *var_syslog_name;
/* LICENSE /* LICENSE
/* .ad /* .ad
/* .fi /* .fi

View File

@ -12,7 +12,8 @@
/* mail_task() enforces consistent naming of mailer processes. /* mail_task() enforces consistent naming of mailer processes.
/* It strips pathname information from the process name, and /* It strips pathname information from the process name, and
/* prepends the name of the mail system so that logfile entries /* prepends the name of the mail system so that logfile entries
/* are easier to recognize. /* are easier to recognize. The mail system name is specified
/* with the "syslog_name" configuration parameter.
/* /*
/* The result is volatile. Make a copy of the result if it is /* The result is volatile. Make a copy of the result if it is
/* to be used for any appreciable amount of time. /* to be used for any appreciable amount of time.
@ -35,25 +36,28 @@
/* Utility library. */ /* Utility library. */
#include <vstring.h> #include <vstring.h>
#include <safe.h>
/* Global library. */ /* Global library. */
#include "mail_params.h" #include "mail_params.h"
#include "mail_conf.h"
#include "mail_task.h" #include "mail_task.h"
#define MAIL_TASK_FORMAT "postfix/%s"
/* mail_task - clean up and decorate the process name */ /* mail_task - clean up and decorate the process name */
const char *mail_task(const char *argv0) const char *mail_task(const char *argv0)
{ {
static VSTRING *canon_name; static VSTRING *canon_name;
const char *slash; const char *slash;
const char *tag;
if (canon_name == 0) if (canon_name == 0)
canon_name = vstring_alloc(10); canon_name = vstring_alloc(10);
if ((slash = strrchr(argv0, '/')) != 0) if ((slash = strrchr(argv0, '/')) != 0)
argv0 = slash + 1; argv0 = slash + 1;
vstring_sprintf(canon_name, MAIL_TASK_FORMAT, argv0); if ((tag = safe_getenv(CONF_ENV_LOGTAG)) == 0)
tag = DEF_SYSLOG_NAME;
vstring_sprintf(canon_name, "%s/%s", tag, argv0);
return (vstring_str(canon_name)); return (vstring_str(canon_name));
} }

View File

@ -15,7 +15,7 @@
* Version of this program. * Version of this program.
*/ */
#define VAR_MAIL_VERSION "mail_version" #define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-20010228" #define DEF_MAIL_VERSION "Snapshot-20010323"
extern char *var_mail_version; extern char *var_mail_version;
/* LICENSE /* LICENSE

View File

@ -252,7 +252,7 @@ VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags)
VSTRING_ADDCH(vp, ')'); VSTRING_ADDCH(vp, ')');
break; break;
case TOK822_COMMENT_TEXT: case TOK822_COMMENT_TEXT:
tok822_copy_quoted(vp, vstring_str(tp->vstr), "()\\\r\n"); tok822_copy_quoted(vp, vstring_str(tp->vstr), "()\\");
break; break;
case TOK822_QSTRING: case TOK822_QSTRING:
VSTRING_ADDCH(vp, '"'); VSTRING_ADDCH(vp, '"');
@ -540,7 +540,7 @@ TOK822 *tok822_scan_addr(const char *addr)
#include <unistd.h> #include <unistd.h>
#include <vstream.h> #include <vstream.h>
#include <vstring_vstream.h> #include <readlline.h>
/* tok822_print - display token */ /* tok822_print - display token */
@ -577,7 +577,7 @@ int main(int unused_argc, char **unused_argv)
TOK822 *list; TOK822 *list;
VSTRING *buf = vstring_alloc(100); VSTRING *buf = vstring_alloc(100);
while (vstring_fgets_nonl(buf, VSTREAM_IN)) { while (readlline(buf, VSTREAM_IN, (int *) 0, READLL_KEEPNL)) {
if (!isatty(vstream_fileno(VSTREAM_IN))) if (!isatty(vstream_fileno(VSTREAM_IN)))
vstream_printf(">>>%s<<<\n\n", vstring_str(buf)); vstream_printf(">>>%s<<<\n\n", vstring_str(buf));
list = tok822_parse(vstring_str(buf)); list = tok822_parse(vstring_str(buf));

View File

@ -330,6 +330,10 @@ static int deliver_message(DELIVER_REQUEST *request, char **unused_argv)
/* /*
* Disconnect if we're going to a different destination. Discard * Disconnect if we're going to a different destination. Discard
* transcript and status information for sending QUIT. * transcript and status information for sending QUIT.
*
* XXX Should transform nexthop into canonical form (unix:/path or
* inet:host:port) before doing connection cache lookup. See also the
* connection cache updating code in lmtp_connect.c.
*/ */
if (strcasecmp(state->session->dest, request->nexthop) != 0) { if (strcasecmp(state->session->dest, request->nexthop) != 0) {
lmtp_quit(state); lmtp_quit(state);

View File

@ -116,7 +116,8 @@ static LMTP_SESSION *lmtp_connect_sock(int, struct sockaddr *, int,
/* lmtp_connect_unix - connect to UNIX-domain address */ /* lmtp_connect_unix - connect to UNIX-domain address */
static LMTP_SESSION *lmtp_connect_unix(const char *addr, VSTRING *why) static LMTP_SESSION *lmtp_connect_unix(const char *addr,
const char *destination, VSTRING *why)
{ {
#undef sun #undef sun
char *myname = "lmtp_connect_unix"; char *myname = "lmtp_connect_unix";
@ -156,7 +157,7 @@ static LMTP_SESSION *lmtp_connect_unix(const char *addr, VSTRING *why)
msg_info("%s: trying: %s...", myname, addr); msg_info("%s: trying: %s...", myname, addr);
return (lmtp_connect_sock(sock, (struct sockaddr *) & sun, sizeof(sun), return (lmtp_connect_sock(sock, (struct sockaddr *) & sun, sizeof(sun),
addr, addr, addr, why)); addr, addr, destination, why));
} }
/* lmtp_connect_addr - connect to explicit address */ /* lmtp_connect_addr - connect to explicit address */
@ -358,11 +359,17 @@ LMTP_SESSION *lmtp_connect(const char *destination, VSTRING *why)
* XXX Ad-hoc transport parsing and connection management. Some or all * XXX Ad-hoc transport parsing and connection management. Some or all
* should be moved away to a reusable library routine so that every * should be moved away to a reusable library routine so that every
* program benefits from it. * program benefits from it.
*
* XXX Should transform destination into canonical form (unix:/path or
* inet:host:port before entering it into the connection cache. See also
* the connection cache lookup code in lmtp.c.
*/ */
if (strncmp(destination, "unix:", 5) == 0) if (strncmp(destination, "unix:", 5) == 0)
return (lmtp_connect_unix(destination + 5, why)); return (lmtp_connect_unix(destination + 5, destination, why));
if (strncmp(destination, "inet:", 5) == 0) if (strncmp(destination, "inet:", 5) == 0)
destination += 5; dest_buf = lmtp_parse_destination(destination + 5, def_service,
&host, &port);
else
dest_buf = lmtp_parse_destination(destination, def_service, dest_buf = lmtp_parse_destination(destination, def_service,
&host, &port); &host, &port);
if (msg_verbose) if (msg_verbose)

View File

@ -138,6 +138,7 @@ master_listen.o: ../../include/vstring.h
master_listen.o: ../../include/vbuf.h master_listen.o: ../../include/vbuf.h
master_listen.o: ../../include/inet_addr_list.h master_listen.o: ../../include/inet_addr_list.h
master_listen.o: ../../include/set_eugid.h master_listen.o: ../../include/set_eugid.h
master_listen.o: ../../include/set_ugid.h
master_listen.o: ../../include/mail_params.h master_listen.o: ../../include/mail_params.h
master_listen.o: master.h master_listen.o: master.h
master_proto.o: master_proto.c master_proto.o: master_proto.c

View File

@ -53,6 +53,7 @@
#include <stringops.h> #include <stringops.h>
#include <inet_addr_list.h> #include <inet_addr_list.h>
#include <set_eugid.h> #include <set_eugid.h>
#include <set_ugid.h>
#include <iostuff.h> #include <iostuff.h>
/* Global library. */ /* Global library. */
@ -88,7 +89,7 @@ void master_listen_init(MASTER_SERV *serv)
LOCAL_LISTEN(serv->name, serv->max_proc > var_proc_limit ? LOCAL_LISTEN(serv->name, serv->max_proc > var_proc_limit ?
serv->max_proc : var_proc_limit, NON_BLOCKING); serv->max_proc : var_proc_limit, NON_BLOCKING);
close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC); close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
set_eugid(getuid(), getgid()); set_ugid(getuid(), getgid());
break; break;
/* /*
@ -98,7 +99,7 @@ void master_listen_init(MASTER_SERV *serv)
set_eugid(var_owner_uid, var_owner_gid); set_eugid(var_owner_uid, var_owner_gid);
serv->listen_fd[0] = fifo_listen(serv->name, 0622, NON_BLOCKING); serv->listen_fd[0] = fifo_listen(serv->name, 0622, NON_BLOCKING);
close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC); close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
set_eugid(getuid(), getgid()); set_ugid(getuid(), getgid());
break; break;
/* /*

View File

@ -152,7 +152,7 @@ static void master_sigchld(int sig)
static void master_sigdeath(int sig) static void master_sigdeath(int sig)
{ {
char *myname = "master_sigsetup"; char *myname = "master_sigdeath";
struct sigaction action; struct sigaction action;
pid_t pid = getpid(); pid_t pid = getpid();

View File

@ -149,7 +149,7 @@ static void qmgr_active_defer(const char *queue_name, const char *queue_id,
tbuf.actime = tbuf.modtime = event_time() + delay; tbuf.actime = tbuf.modtime = event_time() + delay;
path = mail_queue_path((VSTRING *) 0, queue_name, queue_id); path = mail_queue_path((VSTRING *) 0, queue_name, queue_id);
if (utime(path, &tbuf) < 0) if (utime(path, &tbuf) < 0 && errno != ENOENT)
msg_fatal("%s: update %s time stamps: %m", myname, path); msg_fatal("%s: update %s time stamps: %m", myname, path);
if (mail_queue_rename(queue_id, queue_name, dest_queue)) { if (mail_queue_rename(queue_id, queue_name, dest_queue)) {
if (errno != ENOENT) if (errno != ENOENT)

View File

@ -770,8 +770,18 @@ static QMGR_PEER *qmgr_job_peer_select(QMGR_JOB *job)
* Try reading in more recipients. Note that we do not try to read them * Try reading in more recipients. Note that we do not try to read them
* as soon as possible as that would decrease the chance of per-site * as soon as possible as that would decrease the chance of per-site
* recipient grouping. We waited until reading more is really necessary. * recipient grouping. We waited until reading more is really necessary.
*
* XXX Workaround for logic mismatch. The message->refcount test needs
* explanation. If the refcount is zero, it means that qmgr_active_done()
* is beeing completed asynchronously. In such case, we can't read in
* more recipients as bad things would happen after qmgr_active_done()
* continues processing. Note that this results in the given job beeing
* stalled for some time, but fortunately this particular situation is so
* rare that it is not critical. Still we seek for better solution.
*/ */
if (message->rcpt_offset != 0 && message->rcpt_limit > message->rcpt_count) { if (message->rcpt_offset != 0
&& message->rcpt_limit > message->rcpt_count
&& message->refcount > 0) {
qmgr_message_realloc(message); qmgr_message_realloc(message);
if (HAS_ENTRIES(job)) if (HAS_ENTRIES(job))
return (qmgr_peer_select(job)); return (qmgr_peer_select(job));

View File

@ -7,9 +7,7 @@
/* \fBpipe\fR [generic Postfix daemon options] command_attributes... /* \fBpipe\fR [generic Postfix daemon options] command_attributes...
/* DESCRIPTION /* DESCRIPTION
/* The \fBpipe\fR daemon processes requests from the Postfix queue /* The \fBpipe\fR daemon processes requests from the Postfix queue
/* manager to deliver messages to external commands. Each delivery /* manager to deliver messages to external commands.
/* request specifies a queue file, a sender address, a domain or host
/* to deliver to, and one or more recipients.
/* This program expects to be run from the \fBmaster\fR(8) process /* This program expects to be run from the \fBmaster\fR(8) process
/* manager. /* manager.
/* /*
@ -17,6 +15,22 @@
/* as finished, or it informs the queue manager that delivery should /* as finished, or it informs the queue manager that delivery should
/* be tried again at a later time. Delivery problem reports are sent /* be tried again at a later time. Delivery problem reports are sent
/* to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate. /* to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
/* SINGLE-RECIPIENT DELIVERY
/* .ad
/* .fi
/* Some external commands cannot handle more than one recipient
/* per delivery request. Examples of such transports are pagers,
/* fax machines, and so on.
/*
/* To prevent Postfix from sending multiple recipients per delivery
/* request, specify
/*
/* .ti +4
/* \fItransport\fB_destination_recipient_limit = 1\fR
/*
/* in the Postfix \fBmain.cf\fR file, where \fItransport\fR
/* is the name in the first column of the Postfix \fBmaster.cf\fR
/* entry for the pipe-based delivery transport.
/* COMMAND ATTRIBUTE SYNTAX /* COMMAND ATTRIBUTE SYNTAX
/* .ad /* .ad
/* .fi /* .fi
@ -74,18 +88,21 @@
/* This macro expands to the extension part of a recipient address. /* This macro expands to the extension part of a recipient address.
/* For example, with an address \fIuser+foo@domain\fR the extension is /* For example, with an address \fIuser+foo@domain\fR the extension is
/* \fIfoo\fR. /* \fIfoo\fR.
/* .sp
/* A command-line argument that contains \fB${\fBextension\fR}\fR expands /* A command-line argument that contains \fB${\fBextension\fR}\fR expands
/* into as many command-line arguments as there are recipients. /* into as many command-line arguments as there are recipients.
/* .IP \fB${\fBmailbox\fR}\fR /* .IP \fB${\fBmailbox\fR}\fR
/* This macro expands to the complete local part of a recipient address. /* This macro expands to the complete local part of a recipient address.
/* For example, with an address \fIuser+foo@domain\fR the mailbox is /* For example, with an address \fIuser+foo@domain\fR the mailbox is
/* \fIuser+foo\fR. /* \fIuser+foo\fR.
/* .sp
/* A command-line argument that contains \fB${\fBmailbox\fR}\fR /* A command-line argument that contains \fB${\fBmailbox\fR}\fR
/* expands into as many command-line arguments as there are recipients. /* expands into as many command-line arguments as there are recipients.
/* .IP \fB${\fBnexthop\fR}\fR /* .IP \fB${\fBnexthop\fR}\fR
/* This macro expands to the next-hop hostname. /* This macro expands to the next-hop hostname.
/* .IP \fB${\fBrecipient\fR}\fR /* .IP \fB${\fBrecipient\fR}\fR
/* This macro expands to the complete recipient address. /* This macro expands to the complete recipient address.
/* .sp
/* A command-line argument that contains \fB${\fBrecipient\fR}\fR /* A command-line argument that contains \fB${\fBrecipient\fR}\fR
/* expands into as many command-line arguments as there are recipients. /* expands into as many command-line arguments as there are recipients.
/* .IP \fB${\fBsender\fR}\fR /* .IP \fB${\fBsender\fR}\fR
@ -97,6 +114,7 @@
/* This macro expands to the username part of a recipient address. /* This macro expands to the username part of a recipient address.
/* For example, with an address \fIuser+foo@domain\fR the username /* For example, with an address \fIuser+foo@domain\fR the username
/* part is \fIuser\fR. /* part is \fIuser\fR.
/* .sp
/* A command-line argument that contains \fB${\fBuser\fR}\fR expands /* A command-line argument that contains \fB${\fBuser\fR}\fR expands
/* into as many command-line arguments as there are recipients. /* into as many command-line arguments as there are recipients.
/* .RE /* .RE

View File

@ -80,6 +80,7 @@
#include <vstream.h> #include <vstream.h>
#include <msg_vstream.h> #include <msg_vstream.h>
#include <safe.h> #include <safe.h>
#include <events.h>
/* Global library. */ /* Global library. */
@ -159,11 +160,12 @@ int main(int argc, char **argv)
/* /*
* Kick the service. * Kick the service.
*/ */
if (mail_trigger(class, service, request, strlen(request)) < 0) { if (mail_trigger(class, service, request, strlen(request) + 1) < 0) {
msg_warn("Cannot contact class %s service %s - perhaps the mail system is down", msg_warn("Cannot contact class %s service %s - perhaps the mail system is down",
class, service); class, service);
exit(1); exit(1);
} else { } else {
event_loop(-1);
exit(0); exit(0);
} }
} }

View File

@ -149,7 +149,7 @@ static void qmgr_active_defer(const char *queue_name, const char *queue_id,
tbuf.actime = tbuf.modtime = event_time() + delay; tbuf.actime = tbuf.modtime = event_time() + delay;
path = mail_queue_path((VSTRING *) 0, queue_name, queue_id); path = mail_queue_path((VSTRING *) 0, queue_name, queue_id);
if (utime(path, &tbuf) < 0) if (utime(path, &tbuf) < 0 && errno != ENOENT)
msg_fatal("%s: update %s time stamps: %m", myname, path); msg_fatal("%s: update %s time stamps: %m", myname, path);
if (mail_queue_rename(queue_id, queue_name, dest_queue)) { if (mail_queue_rename(queue_id, queue_name, dest_queue)) {
if (errno != ENOENT) if (errno != ENOENT)

View File

@ -16,6 +16,10 @@
/* a brief connection to it and by writing the contents of the /* a brief connection to it and by writing the contents of the
/* named buffer. /* named buffer.
/* /*
/* The connection is closed by a background thread. Some kernels
/* cannot handle client-side disconnect before the server has
/* received the message.
/*
/* Arguments: /* Arguments:
/* .IP service /* .IP service
/* Name of the communication endpoint. /* Name of the communication endpoint.
@ -45,6 +49,7 @@
/* System library. */ /* System library. */
#include <sys_defs.h> #include <sys_defs.h>
#include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -53,13 +58,40 @@
#include <msg.h> #include <msg.h>
#include <connect.h> #include <connect.h>
#include <iostuff.h> #include <iostuff.h>
#include <mymalloc.h>
#include <events.h>
#include <trigger.h> #include <trigger.h>
struct inet_trigger {
int fd;
char *service;
};
/* inet_trigger_event - disconnect from peer */
static void inet_trigger_event(int event, char *context)
{
struct inet_trigger *ip = (struct inet_trigger *) context;
static char *myname = "inet_trigger_event";
/*
* Disconnect.
*/
if (event == EVENT_TIME)
msg_warn("%s: read timeout for service %s", myname, ip->service);
if (close(ip->fd) < 0)
msg_warn("%s: close %s: %m", myname, ip->service);
myfree(ip->service);
myfree((char *) ip);
}
/* inet_trigger - wakeup INET-domain server */ /* inet_trigger - wakeup INET-domain server */
int inet_trigger(const char *service, const char *buf, int len, int timeout) int inet_trigger(const char *service, const char *buf, int len, int timeout)
{ {
char *myname = "inet_trigger"; char *myname = "inet_trigger";
struct inet_trigger *ip;
int fd; int fd;
if (msg_verbose > 1) if (msg_verbose > 1)
@ -73,6 +105,9 @@ int inet_trigger(const char *service, const char *buf, int len, int timeout)
msg_warn("%s: connect to %s: %m", myname, service); msg_warn("%s: connect to %s: %m", myname, service);
return (-1); return (-1);
} }
ip = (struct inet_trigger *) mymalloc(sizeof(*ip));
ip->fd = fd;
ip->service = mystrdup(service);
/* /*
* Write the request... * Write the request...
@ -82,10 +117,10 @@ int inet_trigger(const char *service, const char *buf, int len, int timeout)
msg_warn("%s: write to %s: %m", myname, service); msg_warn("%s: write to %s: %m", myname, service);
/* /*
* Disconnect. * Wakeup when the peer disconnects, or when we lose patience.
*/ */
if (close(fd) < 0) if (timeout > 0)
if (msg_verbose) event_request_timer(inet_trigger_event, (char *) ip, timeout);
msg_warn("%s: close %s: %m", myname, service); event_enable_read(fd, inet_trigger_event, (char *) ip);
return (0); return (0);
} }

View File

@ -67,8 +67,8 @@ void rand_sleep(unsigned delay, unsigned variation)
* Use the semi-crappy random number generator. * Use the semi-crappy random number generator.
*/ */
if (my_pid == 0) if (my_pid == 0)
srandom((my_pid = getpid()) ^ time((time_t *) 0)); srand((my_pid = getpid()) ^ time((time_t *) 0));
usec = (delay - variation / 2) + variation * (double) random() / RAND_MAX; usec = (delay - variation / 2) + variation * (double) rand() / RAND_MAX;
doze(usec); doze(usec);
} }

View File

@ -36,6 +36,7 @@
/* Utility library. */ /* Utility library. */
#include "msg.h"
#include "sane_accept.h" #include "sane_accept.h"
/* sane_accept - sanitize accept() error returns */ /* sane_accept - sanitize accept() error returns */
@ -55,6 +56,10 @@ int sane_accept(int sock, struct sockaddr * sa, SOCKADDR_SIZE *len)
EWOULDBLOCK, EWOULDBLOCK,
0, 0,
}; };
static int accept_warn_errors[] = {
ECONNABORTED,
0,
};
int count; int count;
int err; int err;
int fd; int fd;
@ -68,6 +73,13 @@ int sane_accept(int sock, struct sockaddr * sa, SOCKADDR_SIZE *len)
* XXX LINUX < 2.1 accept() wakes up before the three-way handshake is * XXX LINUX < 2.1 accept() wakes up before the three-way handshake is
* complete, so it can fail with ECONNRESET and other "false alarm" * complete, so it can fail with ECONNRESET and other "false alarm"
* indications. * indications.
*
* XXX FreeBSD 4.2-STABLE accept() returns ECONNABORTED when a UNIX-domain
* client has disconnected in the mean time. The data that was sent with
* connect() write() close() is lost, even though the write() and close()
* reported successful completion. This was fixed shortly before FreeBSD
* 4.3. However, other systems may make that same mistake again, so we're
* adding a special warning.
*/ */
if ((fd = accept(sock, sa, len)) < 0) { if ((fd = accept(sock, sa, len)) < 0) {
for (count = 0; (err = accept_ok_errors[count]) != 0; count++) { for (count = 0; (err = accept_ok_errors[count]) != 0; count++) {
@ -76,6 +88,13 @@ int sane_accept(int sock, struct sockaddr * sa, SOCKADDR_SIZE *len)
break; break;
} }
} }
for (count = 0; (err = accept_warn_errors[count]) != 0; count++) {
if (errno == err) {
msg_warn("accept: %m");
errno = EAGAIN;
break;
}
}
} }
return (fd); return (fd);
} }

View File

@ -15,6 +15,10 @@
/* stream_trigger() wakes up the named stream server by making /* stream_trigger() wakes up the named stream server by making
/* a brief connection to it and writing the named buffer. /* a brief connection to it and writing the named buffer.
/* /*
/* The connection is closed by a background thread. Some kernels
/* cannot handle client-side disconnect before the server has
/* received the message.
/*
/* Arguments: /* Arguments:
/* .IP service /* .IP service
/* Name of the communication endpoint. /* Name of the communication endpoint.
@ -51,13 +55,39 @@
#include <msg.h> #include <msg.h>
#include <connect.h> #include <connect.h>
#include <iostuff.h> #include <iostuff.h>
#include <mymalloc.h>
#include <events.h>
#include <trigger.h> #include <trigger.h>
struct stream_trigger {
int fd;
char *service;
};
/* stream_trigger_event - disconnect from peer */
static void stream_trigger_event(int event, char *context)
{
struct stream_trigger *sp = (struct stream_trigger *) context;
static char *myname = "stream_trigger_event";
/*
* Disconnect.
*/
if (event == EVENT_TIME)
msg_warn("%s: read timeout for service %s", myname, sp->service);
if (close(sp->fd) < 0)
msg_warn("%s: close %s: %m", myname, sp->service);
myfree(sp->service);
myfree((char *) sp);
}
/* stream_trigger - wakeup stream server */ /* stream_trigger - wakeup stream server */
int stream_trigger(const char *service, const char *buf, int len, int timeout) int stream_trigger(const char *service, const char *buf, int len, int timeout)
{ {
char *myname = "stream_trigger"; char *myname = "stream_trigger";
struct stream_trigger *sp;
int fd; int fd;
if (msg_verbose > 1) if (msg_verbose > 1)
@ -72,6 +102,13 @@ int stream_trigger(const char *service, const char *buf, int len, int timeou
return (-1); return (-1);
} }
/*
* Stash away context.
*/
sp = (struct stream_trigger *) mymalloc(sizeof(*sp));
sp->fd = fd;
sp->service = mystrdup(service);
/* /*
* Write the request... * Write the request...
*/ */
@ -80,10 +117,10 @@ int stream_trigger(const char *service, const char *buf, int len, int timeou
msg_warn("%s: write to %s: %m", myname, service); msg_warn("%s: write to %s: %m", myname, service);
/* /*
* Disconnect. * Wakeup when the peer disconnects, or when we lose patience.
*/ */
if (close(fd) < 0) if (timeout > 0)
if (msg_verbose) event_request_timer(stream_trigger_event, (char *) sp, timeout);
msg_warn("%s: close %s: %m", myname, service); event_enable_read(fd, stream_trigger_event, (char *) sp);
return (0); return (0);
} }

View File

@ -329,10 +329,12 @@ extern int opterr;
#define USE_STATVFS #define USE_STATVFS
#define STATVFS_IN_SYS_STATVFS_H #define STATVFS_IN_SYS_STATVFS_H
#define STRCASECMP_IN_STRINGS_H #define STRCASECMP_IN_STRINGS_H
#if 0
extern time_t time(time_t *); extern time_t time(time_t *);
extern int seteuid(uid_t); extern int seteuid(uid_t);
extern int setegid(gid_t); extern int setegid(gid_t);
extern int initgroups(const char *, int); extern int initgroups(const char *, int);
#endif
#endif #endif

View File

@ -15,6 +15,10 @@
/* unix_trigger() wakes up the named UNIX-domain server by making /* unix_trigger() wakes up the named UNIX-domain server by making
/* a brief connection to it and writing the named buffer. /* a brief connection to it and writing the named buffer.
/* /*
/* The connection is closed by a background thread. Some kernels
/* cannot handle client-side disconnect before the server has
/* received the message.
/*
/* Arguments: /* Arguments:
/* .IP service /* .IP service
/* Name of the communication endpoint. /* Name of the communication endpoint.
@ -43,6 +47,7 @@
/* System library. */ /* System library. */
#include <sys_defs.h> #include <sys_defs.h>
#include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -51,13 +56,39 @@
#include <msg.h> #include <msg.h>
#include <connect.h> #include <connect.h>
#include <iostuff.h> #include <iostuff.h>
#include <mymalloc.h>
#include <events.h>
#include <trigger.h> #include <trigger.h>
struct unix_trigger {
int fd;
char *service;
};
/* unix_trigger_event - disconnect from peer */
static void unix_trigger_event(int event, char *context)
{
struct unix_trigger *up = (struct unix_trigger *) context;
static char *myname = "unix_trigger_event";
/*
* Disconnect.
*/
if (event == EVENT_TIME)
msg_warn("%s: read timeout for service %s", myname, up->service);
if (close(up->fd) < 0)
msg_warn("%s: close %s: %m", myname, up->service);
myfree(up->service);
myfree((char *) up);
}
/* unix_trigger - wakeup UNIX-domain server */ /* unix_trigger - wakeup UNIX-domain server */
int unix_trigger(const char *service, const char *buf, int len, int timeout) int unix_trigger(const char *service, const char *buf, int len, int timeout)
{ {
char *myname = "unix_trigger"; char *myname = "unix_trigger";
struct unix_trigger *up;
int fd; int fd;
if (msg_verbose > 1) if (msg_verbose > 1)
@ -72,6 +103,13 @@ int unix_trigger(const char *service, const char *buf, int len, int timeout)
return (-1); return (-1);
} }
/*
* Stash away context.
*/
up = (struct unix_trigger *) mymalloc(sizeof(*up));
up->fd = fd;
up->service = mystrdup(service);
/* /*
* Write the request... * Write the request...
*/ */
@ -80,10 +118,10 @@ int unix_trigger(const char *service, const char *buf, int len, int timeout)
msg_warn("%s: write to %s: %m", myname, service); msg_warn("%s: write to %s: %m", myname, service);
/* /*
* Disconnect. * Wakeup when the peer disconnects, or when we lose patience.
*/ */
if (close(fd) < 0) if (timeout > 0)
if (msg_verbose) event_request_timer(unix_trigger_event, (char *) up, timeout);
msg_warn("%s: close %s: %m", myname, service); event_enable_read(fd, unix_trigger_event, (char *) up);
return (0); return (0);
} }