-TVBUF
-TVSTREAM
-TVSTREAM_POPEN_ARGS
+-TVSTREAN_POPEN_ARGS
-TVSTRING
-TWAIT_STATUS_T
-TWATCHDOG
Feature: specify "smtp_never_send_ehlo = no" to disable
ESMTP. Someone asked for this long ago. Files: smtp/smtp.c,
smtp/smtp_proto.c.
+
+ Feature? Bugfix? The smtp client will now ignore server
+ replies that do not start with "CODE SPACE" or with "CODE
+ HYPHEN". Which means that "CODE TEXT" is now treated as
+ "CODE HYPHEN TEXT", instead of being treated as "CODE SPACE
+ TEXT", the way it was before. File: smtp/smtp_chat.c.
+
+20001203
+
+ Documentation: postmap(1) and postalias(1) did not document
+ the process exit status for "-q key".
+
+20001204
+
+ Bugfix: master no longer imported MAIL_CONF and other
+ necessary environmental parameters. Postfix now has
+ explicit "import_environment" and "export_environment"
+ configuration parameters that control what environment
+ parameters are imported from or exported to the external
+ environment. Files: util/clean_env.c, util/spawn_command.c,
+ util/vstream_popen.c, global/pipe_command.c, and everything
+ that uses this code.
+
+20001208
+
+ Bugfix: while processing massive amounts of one-recipient
+ mail, qmgr could deadlock for 10 seconds while sending a
+ bounce message. All queue manager bounce send requests are
+ now implemented asynchronously. Files: global/abounce.[hc]
+ (asynchronous bounce client), qmgr/qmgr_active.c. Problem
+ reported by El Bunzo (webpower.nl) and Tiger Technologies
+ (tigertech.com).
===========================================
The "sun_mailtool_compatibility" is going away (a compatibility mode
-that turns of kernel locks on mailbox files). It still works, but
+that turns off kernel locks on mailbox files). It still works, but
a warning is logged. Instead, specify the mailbox locking strategy
via the new "mailbox_delivery_lock" parameter.
Major changes with snapshot-2000XXXX
====================================
-The locking style for delivery to mailbox is now fully configurable
-at runtime. The new configuration parameter is "mailbox_delivery_lock".
+The mailbox locking style is now fully configurable at runtime.
+The new configuration parameter is "mailbox_delivery_lock".
Depending on the operating system type, mailboxes can be locked
-with one or more of "flock", "fcntl" or "dotlock". The default
-setting of "mailbox_delivery_lock" is therefore system dependent.
+with one or more of "flock", "fcntl" or "dotlock". This also applies
+to "/file/name" deliveries by the Postfix local delivery agent.
+The default setting of "mailbox_delivery_lock" is system dependent.
The command "postconf -l" shows the available locking styles.
+The "import_environment" and "export_environment" configuration
+parameters now control what environment variables Postfix will
+import from its parent and what it variables Postfix will pass on
+to a non-Postfix process. It is not safe to import or export
+everything, and different sites may have different needs.
+
Incompatible changes with snapshot-20001121
===========================================
#
double_bounce_sender = double-bounce
+# The export_environment parameter specifies the names of environment
+# parameters that Postfix will export to non-Postfix processes.
+#
+# - TZ is needed for sane time keeping on most SYSV-ish systems
+#
+# Specify a list of names separated by whitespace or comma.
+#
+export_environment = TZ
+
# The hash_queue_depth parameter specifies the number of subdirectory
# levels below the queue directories listed in the hash_queue_names
# parameter.
#
hopcount_limit = 50
+# The import_environment parameter specifies the names of environment
+# parameters that Postfix processes will import from their parent
+# environment.
+#
+# - TZ is needed for sane time keeping on most SYSV-ish systems
+# - DISPLAY and XAUTHORITY are needed for debugging Postfix daemons
+# with an X-windows debugger.
+# - MAIL_CONFIG is needed to make "postfix -c" work.
+#
+# 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
+
# The inet_interfaces parameter specifies the network interface
# addresses that this mail system receives mail on. By default,
# the software claims all active interfaces on the machine. The
the right-hand side of the owner alias, instead
using of the left-hand side address.
- <b>forward</b><i>_</i><b>path</b>
- Search list for .forward files. The names are sub-
- ject to <i>$name</i> expansion.
+ <b>export</b><i>_</i><b>environment</b>
+ List of names of environment parameters that can be
+ exported to non-Postfix processes.
LOCAL(8) LOCAL(8)
+ <b>forward</b><i>_</i><b>path</b>
+ Search list for .forward files. The names are sub-
+ ject to <i>$name</i> expansion.
+
<b>local</b><i>_</i><b>command</b><i>_</i><b>shell</b>
- Shell to use for external command execution (for
- example, /some/where/smrsh -c). When a shell is
+ Shell to use for external command execution (for
+ example, /some/where/smrsh -c). When a shell is
specified, it is invoked even when the command con-
- tains no shell built-in commands or meta charac-
+ tains no shell built-in commands or meta charac-
ters.
<b>owner</b><i>_</i><b>request</b><i>_</i><b>special</b>
addresses.
<b>prepend</b><i>_</i><b>delivered</b><i>_</i><b>header</b>
- Prepend an optional <b>Delivered-To:</b> header upon
- external forwarding, delivery to command or file.
- Specify zero or more of: <b>command,</b> <b>file,</b> <b>forward</b>.
- Turning off <b>Delivered-To:</b> when forwarding mail is
+ Prepend an optional <b>Delivered-To:</b> header upon
+ external forwarding, delivery to command or file.
+ Specify zero or more of: <b>command,</b> <b>file,</b> <b>forward</b>.
+ Turning off <b>Delivered-To:</b> when forwarding mail is
not recommended.
<b>recipient</b><i>_</i><b>delimiter</b>
<b>test</b><i>_</i><b>home</b><i>_</i><b>directory</b>
Require that a recipient's home directory is acces-
- sible by the recipient before attempting delivery.
+ sible by the recipient before attempting delivery.
<b>Mailbox</b> <b>delivery</b>
<b>fallback</b><i>_</i><b>transport</b>
Message transport for recipients that are not found
- in the UNIX passwd database. This parameter over-
+ in the UNIX passwd database. This parameter over-
rides <b>luser</b><i>_</i><b>relay</b>.
<b>home</b><i>_</i><b>mailbox</b>
- Pathname of a mailbox relative to a user's home
+ Pathname of a mailbox relative to a user's home
directory. Specify a path ending in <b>/</b> for maildir-
style delivery.
<b>luser</b><i>_</i><b>relay</b>
- Destination (<i>@domain</i> or <i>address</i>) for non-existent
- users. The <i>address</i> is subjected to <i>$name</i> expan-
+ Destination (<i>@domain</i> or <i>address</i>) for non-existent
+ users. The <i>address</i> is subjected to <i>$name</i> expan-
sion.
<b>mail</b><i>_</i><b>spool</b><i>_</i><b>directory</b>
- Directory with UNIX-style mailboxes. The default
+ Directory with UNIX-style mailboxes. The default
pathname is system dependent.
<b>mailbox</b><i>_</i><b>command</b>
- External command to use for mailbox delivery. The
+ External command to use for mailbox delivery. The
command executes with the recipient privileges
- (exception: root). The string is subject to $name
+ (exception: root). The string is subject to $name
expansions.
- <b>mailbox</b><i>_</i><b>transport</b>
- Message transport to use for mailbox delivery to
- all local recipients, whether or not they are found
-
6
LOCAL(8) LOCAL(8)
- in the UNIX passwd database. This parameter over-
- rides all other configuration parameters that con-
+ <b>mailbox</b><i>_</i><b>transport</b>
+ Message transport to use for mailbox delivery to
+ all local recipients, whether or not they are found
+ in the UNIX passwd database. This parameter over-
+ rides all other configuration parameters that con-
trol mailbox delivery, including <b>luser</b><i>_</i><b>relay</b>.
<b>Locking</b> <b>controls</b>
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
- Limit the number of attempts to acquire an exclu-
+ Limit the number of attempts to acquire an exclu-
sive lock on a mailbox or external file.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
- Time in seconds between successive attempts to
+ Time in seconds between successive attempts to
acquire an exclusive lock.
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
Limit the time after which a stale lock is removed.
<b>mailbox</b><i>__</i><b>delivery</b><i>_</i><b>lock</b>
- What file locking method(s) to use when delivering
- to a UNIX-style mailbox. The default setting is
- system dependent. For a list of available file
+ What file locking method(s) to use when delivering
+ to a UNIX-style mailbox. The default setting is
+ system dependent. For a list of available file
locking methods, use the <b>postconf</b> <b>-l</b> command.
<b>Resource</b> <b>controls</b>
<b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b>
- Limit the amount of time for delivery to external
+ Limit the amount of time for delivery to external
command.
<b>duplicate</b><i>_</i><b>filter</b><i>_</i><b>limit</b>
- Limit the size of the duplicate filter for results
+ Limit the size of the duplicate filter for results
from alias etc. expansion.
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
- Limit the amount of memory used for processing a
+ Limit the amount of memory used for processing a
partial input line.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
- user. The default limit is taken from the
+ user. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the number of recipients per message deliv-
- ery. The default limit is taken from the
+ Limit the number of recipients per message deliv-
+ ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Security</b> <b>controls</b>
<b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>commands</b>
- Restrict the usage of mail delivery to external
+ Restrict the usage of mail delivery to external
command.
- <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b>
- Restrict the usage of mail delivery to external
- file.
LOCAL(8) LOCAL(8)
+ <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b>
+ Restrict the usage of mail delivery to external
+ file.
+
<b>command</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
- What characters are allowed to appear in $name
- expansions of mailbox_command. Illegal characters
+ What characters are allowed to appear in $name
+ expansions of mailbox_command. Illegal characters
are replaced by underscores.
<b>default</b><i>_</i><b>privs</b>
- Default rights for delivery to external file or
+ Default rights for delivery to external file or
command.
<b>forward</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
- What characters are allowed to appear in $name
- expansions of forward_path. Illegal characters are
+ What characters are allowed to appear in $name
+ expansions of forward_path. Illegal characters are
replaced by underscores.
<b>HISTORY</b>
- The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
+ The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
Daniel Bernstein.
- The <i>maildir</i> structure appears in the <b>qmail</b> system by
+ The <i>maildir</i> structure appears in the <b>qmail</b> system by
Daniel Bernstein.
<b>SEE</b> <b>ALSO</b>
<a href="qmgr.8.html">qmgr(8)</a> queue manager
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-
-
8
command after a configuration change.
<b>Miscellaneous</b>
+ <b>import</b><i>_</i><b>environment</b>
+
+ <b>export</b><i>_</i><b>environment</b>
+ Lists of names of environment parameters that can
+ be imported from (exported to) non-Postfix pro-
+ cesses.
+
<b>mail</b><i>_</i><b>owner</b>
The owner of the mail queue and of most Postfix
processes.
also the root directory of Postfix daemons that run
chrooted.
-<b>Resource</b> <b>controls</b>
- <b>default</b><i>_</i><b>process</b><i>_</i><b>limit</b>
- Default limit for the number of simultaneous child
- processes that provide a given service.
- <b>max</b><i>_</i><b>idle</b>
- Limit the time in seconds that a child process
- waits between service requests.
MASTER(8) MASTER(8)
+<b>Resource</b> <b>controls</b>
+ <b>default</b><i>_</i><b>process</b><i>_</i><b>limit</b>
+ Default limit for the number of simultaneous child
+ processes that provide a given service.
+
+ <b>max</b><i>_</i><b>idle</b>
+ Limit the time in seconds that a child process
+ waits between service requests.
+
<b>max</b><i>_</i><b>use</b>
Limit the number of service requests handled by a
child process.
-
-
-
-
-
-
-
-
-
command after a configuration change.
<b>Miscellaneous</b>
+ <b>export</b><i>_</i><b>environment</b>
+ List of names of environment parameters that can be
+ exported to non-Postfix processes.
+
<b>mail</b><i>_</i><b>owner</b>
- The process privileges used while not running an
+ The process privileges used while not running an
external command.
<b>Resource</b> <b>controls</b>
- In the text below, <i>transport</i> is the first field in a <b>mas-</b>
+ In the text below, <i>transport</i> is the first field in a <b>mas-</b>
<b>ter.cf</b> entry.
<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
- destination, for delivery via the named <i>transport</i>.
- 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
- enforced by the Postfix queue manager.
PIPE(8) PIPE(8)
+ destination, for delivery via the named <i>transport</i>.
+ 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
+ enforced by the Postfix queue manager.
+
<i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the number of recipients per message deliv-
- ery, for delivery via the named <i>transport</i>. The
- default limit is taken from the <b>default</b><i>_</i><b>destina-</b>
- <b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter. The limit is
+ Limit the number of recipients per message deliv-
+ ery, for delivery via the named <i>transport</i>. The
+ default limit is taken from the <b>default</b><i>_</i><b>destina-</b>
+ <b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter. The limit is
enforced by the Postfix queue manager.
<i>transport_</i><b>time</b><i>_</i><b>limit</b>
- Limit the time for delivery to external command,
- for delivery via the named <b>transport</b>. The default
- limit is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> parame-
- ter. The limit is enforced by the Postfix queue
+ Limit the time for delivery to external command,
+ for delivery via the named <b>transport</b>. The default
+ limit is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> parame-
+ ter. The limit is enforced by the Postfix queue
manager.
<b>SEE</b> <b>ALSO</b>
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-
-
-
put means no problems were detected. Duplicate entries are
skipped and are flagged with a warning.
+ <b>postalias</b> terminates with zero exit status in case of suc-
+ cess (including successful <b>postmap</b> <b>-q</b> lookup) and termi-
+ nates with non-zero exit status in case of failure.
+
<b>BUGS</b>
The "delete key" support is limited to one delete opera-
tion per command invocation.
<b>MAIL</b><i>_</i><b>VERBOSE</b>
Enable verbose logging for debugging purposes.
-<b>CONFIGURATION</b> <b>PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
- to this program. See the Postfix <b>main.cf</b> file for syntax
- details and for default values.
POSTALIAS(1) POSTALIAS(1)
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
+ details and for default values.
+
<b>database</b><i>_</i><b>type</b>
Default alias database type. On many UNIX systems,
the default type is either <b>dbm</b> or <b>hash</b>.
-
-
-
-
-
default values. Use the <b>postfix</b> <b>reload</b> command after a
configuration change.
- <b>queue</b><i>_</i><b>directory</b>
- Top-level directory of the Postfix queue. This is
- also the root directory of Postfix daemons that run
- chrooted.
-
+ <b>import</b><i>_</i><b>environment</b>
+ List of names of environment parameters that can be
+ imported from non-Postfix processes.
+ <b>queue</b><i>_</i><b>directory</b>
+ Top-level directory of the Postfix queue. This is
POSTDROP(1) POSTDROP(1)
+ also the root directory of Postfix daemons that run
+ chrooted.
+
<b>SEE</b> <b>ALSO</b>
<a href="sendmail.1.html">sendmail(1)</a> compatibility interface
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-
skipped and are flagged with a warning.
+ <b>postmap</b> terminates with zero exit status in case of suc-
+ cess (including successful <b>postmap</b> <b>-q</b> lookup) and termi-
+ nates with non-zero exit status in case of failure.
+
<b>BUGS</b>
The "delete key" support is limited to one delete opera-
tion per command invocation.
-
-
-
-
<b>ignore</b><i>_</i><b>mx</b><i>_</i><b>lookup</b><i>_</i><b>error</b>
When a name server fails to respond to an MX query,
- search for an A record instead of assuming that the
- name server will recover.
+ search for an A record instead deferring mail
+ delivery.
<b>inet</b><i>_</i><b>interfaces</b>
The network interface addresses that this mail sys-
<b>smtp</b><i>_</i><b>always</b><i>_</i><b>send</b><i>_</i><b>ehlo</b>
Always send EHLO at the start of a connection.
+ <b>smtp</b><i>_</i><b>never</b><i>_</i><b>send</b><i>_</i><b>ehlo</b>
+ Never send EHLO at the start of a connection.
+
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
Skip servers that greet us with a 4xx status code.
destination. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
- <b>smtp</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the number of recipients per message
-
3
SMTP(8) SMTP(8)
- delivery. The default limit is taken from the
+ <b>smtp</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
+ Limit the number of recipients per message deliv-
+ ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Timeout</b> <b>controls</b>
-
-
4
command after a configuration change.
<b>Miscellaneous</b>
+ <b>export</b><i>_</i><b>environment</b>
+ List of names of environment parameters that can be
+ exported to non-Postfix processes.
+
<b>mail</b><i>_</i><b>owner</b>
- The process privileges used while not running an
+ The process privileges used while not running an
external command.
<b>Resource</b> <b>control</b>
<i>service_</i><b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b>
- The amount of time the command is allowed to run
+ The amount of time the command is allowed to run
before it is killed with force. The <i>service</i> name is
- the name of the entry in the <b>master.cf</b> file. The
- default time limit is given by the global <b>com-</b>
+ the name of the entry in the <b>master.cf</b> file. The
+ default time limit is given by the global <b>com-</b>
<b>mand</b><i>_</i><b>time</b><i>_</i><b>limit</b> configuration parameter.
<b>SEE</b> <b>ALSO</b>
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
-
-
-
-
2
Problems are logged to the standard error stream. No output means
no problems were detected. Duplicate entries are skipped and are
flagged with a warning.
+
+\fBpostalias\fR terminates with zero exit status in case of success
+(including successful \fBpostmap -q\fR lookup) and terminates
+with non-zero exit status in case of failure.
.SH BUGS
.ad
.fi
See the Postfix \fBmain.cf\fR file for syntax details and for
default values. Use the \fBpostfix reload\fR command after a
configuration change.
+.IP \fBimport_environment\fR
+List of names of environment parameters that can be imported
+from non-Postfix processes.
.IP \fBqueue_directory\fR
Top-level directory of the Postfix queue. This is also the root
directory of Postfix daemons that run chrooted.
Problems and transactions are logged to the standard error
stream. No output means no problems. Duplicate entries are
skipped and are flagged with a warning.
+
+\fBpostmap\fR terminates with zero exit status in case of success
+(including successful \fBpostmap -q\fR lookup) and terminates
+with non-zero exit status in case of failure.
.SH BUGS
.ad
.fi
When delivering to an alias that has an owner- companion alias,
set the envelope sender address to the right-hand side of the
owner alias, instead using of the left-hand side address.
+.IP \fBexport_environment\fR
+List of names of environment parameters that can be exported
+to non-Postfix processes.
.IP \fBforward_path\fR
Search list for .forward files. The names are subject to \fI$name\fR
expansion.
.SH Miscellaneous
.ad
.fi
+.IP \fBimport_environment\fR
+.IP \fBexport_environment\fR
+Lists of names of environment parameters that can be imported
+from (exported to) non-Postfix processes.
.IP \fBmail_owner\fR
The owner of the mail queue and of most Postfix processes.
.IP \fBcommand_directory\fR
.SH Miscellaneous
.ad
.fi
+.IP \fBexport_environment\fR
+List of names of environment parameters that can be exported
+to non-Postfix processes.
.IP \fBmail_owner\fR
The process privileges used while not running an external command.
.SH "Resource controls"
or if a destination is unreachable.
.IP \fBignore_mx_lookup_error\fR
When a name server fails to respond to an MX query, search for an
-A record instead of assuming that the name server will recover.
+A record instead deferring mail delivery.
.IP \fBinet_interfaces\fR
The network interface addresses that this mail system receives
mail on. When any of those addresses appears in the list of mail
postmaster with transcripts of SMTP sessions with protocol errors.
.IP \fBsmtp_always_send_ehlo\fR
Always send EHLO at the start of a connection.
+.IP \fBsmtp_never_send_ehlo\fR
+Never send EHLO at the start of a connection.
.IP \fBsmtp_skip_4xx_greeting\fR
Skip servers that greet us with a 4xx status code.
.IP \fBsmtp_skip_5xx_greeting\fR
.SH Miscellaneous
.ad
.fi
+.IP \fBexport_environment\fR
+List of names of environment parameters that can be exported
+to non-Postfix processes.
.IP \fBmail_owner\fR
The process privileges used while not running an external command.
.SH Resource control
sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
- flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c
+ flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
debug_peer.o debug_process.o defer.o deliver_completed.o \
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
- flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o
+ flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
recipient_list.h record.h resolve_clnt.h resolve_local.h \
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
- mbox_conf.h mbox_open.h
+ mbox_conf.h mbox_open.h abounce.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
mbox_open.o: ../../include/vbuf.h
mbox_open.o: ../../include/vstring.h
mbox_open.o: ../../include/safe_open.h
+mbox_open.o: ../../include/iostuff.h
+mbox_open.o: ../../include/mymalloc.h
mbox_open.o: dot_lockfile.h
mbox_open.o: deliver_flock.h
mbox_open.o: ../../include/myflock.h
--- /dev/null
+/*++
+/* NAME
+/* abounce 3
+/* SUMMARY
+/* asynchronous bounce/defer service client
+/* SYNOPSIS
+/* #include <abounce.h>
+/*
+/* void abounce_flush(flags, queue, id, sender, callback, context)
+/* int flags;
+/* const char *queue;
+/* const char *id;
+/* const char *sender;
+/* void (*callback)(int status, char *context);
+/* char *context;
+/*
+/* void adefer_flush(flags, queue, id, sender, callback, context)
+/* int flags;
+/* const char *queue;
+/* const char *id;
+/* const char *sender;
+/* void (*callback)(int status, char *context);
+/* char *context;
+/*
+/* void adefer_warn(flags, queue, id, sender, callback, context)
+/* int flags;
+/* const char *queue;
+/* const char *id;
+/* const char *sender;
+/* void (*callback)(int status, char *context);
+/* char *context;
+/* DESCRIPTION
+/* This module implements an asynchronous interface to the
+/* bounce/defer service for submitting sender notifications
+/* without waiting for completion of the request.
+/*
+/* abounce_flush() bounces the specified message to
+/* the specified sender, including the bounce log that was
+/* built with bounce_append().
+/*
+/* adefer_flush() bounces the specified message to
+/* the specified sender, including the defer log that was
+/* built with defer_append().
+/*
+/* adefer_warn() sends a "mail is delayed" notification to
+/* the specified sender, including the defer log that was
+/* built with defer_append().
+/*
+/* Arguments:
+/* .IP flags
+/* The bitwise OR of zero or more of the following (specify
+/* BOUNCE_FLAG_NONE to request no special processing):
+/* .RS
+/* .IP BOUNCE_FLAG_CLEAN
+/* Delete the bounce log in case of an error (as in: pretend
+/* that we never even tried to bounce this message).
+/* .IP BOUNCE_FLAG_COPY
+/* Request that a postmaster copy is sent.
+/* .RE
+/* .IP queue
+/* The message queue name of the original message file.
+/* .IP id
+/* The message queue id if the original message file. The bounce log
+/* file has the same name as the original message file.
+/* .IP sender
+/* The sender envelope address.
+/* .IP callback
+/* Name of a routine that receives the notification status as
+/* documented for bounce_flush() or defer_flush().
+/* .IP context
+/* Application-specific context that is passed through to the
+/* callback routine. Use proper casts or the world will come
+/* to an end.
+/* DIAGNOSTICS
+/* In case of success, these functions log the action, and return a
+/* zero result via the callback routine. Otherwise, the functions
+/* return a non-zero result via the callback routine, and when
+/* BOUNCE_FLAG_CLEAN is disabled, log that message delivery is deferred.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <events.h>
+#include <vstream.h>
+
+/* Global library. */
+
+#include <mail_proto.h>
+#include <abounce.h>
+
+/* Application-specific. */
+
+ /*
+ * Each bounce/defer flush/warn request is implemented by sending the
+ * request to the bounce/defer server, and by creating a pseudo thread that
+ * suspends itself until the server replies (or dies). Upon wakeup, the
+ * pseudo thread delivers the request completion status to the application
+ * and destroys itself. The structure below maintains all the necessary
+ * request state while the pseudo thread is suspended.
+ */
+typedef struct {
+ int command; /* bounce request type */
+ int flags; /* bounce options */
+ char *id; /* queue ID for logging */
+ ABOUNCE_FN callback; /* application callback */
+ char *context; /* application context */
+ VSTREAM *fp; /* server I/O handle */
+} ABOUNCE;
+
+/* abounce_done - deliver status to application and clean up pseudo thread */
+
+static void abounce_done(ABOUNCE *ap, int status)
+{
+ (void) vstream_fclose(ap->fp);
+ if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0)
+ msg_info("%s: status=deferred (%s failed)", ap->id,
+ ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
+ ap->command == BOUNCE_CMD_WARN ? "delay warning" :
+ "whatever");
+ ap->callback(status, ap->context);
+ myfree(ap->id);
+ myfree((char *) ap);
+}
+
+/* abounce_event - resume pseudo thread after server reply event */
+
+static void abounce_event(int unused_event, char *context)
+{
+ ABOUNCE *ap = (ABOUNCE *) context;
+ int status;
+
+ event_disable_readwrite(vstream_fileno(ap->fp));
+ abounce_done(ap, mail_scan(ap->fp, "%d", &status) == 1 ? status : -1);
+}
+
+/* abounce_request - suspend pseudo thread until server reply event */
+
+static void abounce_request(const char *class, const char *service,
+ int command, int flags,
+ const char *queue, const char *id,
+ const char *sender,
+ ABOUNCE_FN callback,
+ char *context)
+{
+ ABOUNCE *ap;
+
+ /*
+ * Save pseudo thread state. Connect to the server. Send the request and
+ * suspend the pseudo thread until the server replies (or dies).
+ */
+ ap = (ABOUNCE *) mymalloc(sizeof(*ap));
+ ap->command = command;
+ ap->flags = flags;
+ ap->id = mystrdup(id);
+ ap->callback = callback;
+ ap->context = context;
+ ap->fp = mail_connect_wait(class, service);
+
+ if (mail_print(ap->fp, "%d %d %s %s %s %s", command,
+ flags, queue, id, sender, MAIL_EOF) == 0
+ && vstream_fflush(ap->fp) == 0) {
+ event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
+ } else {
+ abounce_done(ap, -1);
+ }
+}
+
+/* abounce_flush - asynchronous bounce flush */
+
+void abounce_flush(int flags, const char *queue, const char *id,
+ const char *sender, ABOUNCE_FN callback, char *context)
+{
+ abounce_request(MAIL_CLASS_PRIVATE, MAIL_SERVICE_BOUNCE, BOUNCE_CMD_FLUSH,
+ flags, queue, id, sender, callback, context);
+}
+
+/* adefer_flush - asynchronous defer flush */
+
+void adefer_flush(int flags, const char *queue, const char *id,
+ const char *sender, ABOUNCE_FN callback, char *context)
+{
+ abounce_request(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER, BOUNCE_CMD_FLUSH,
+ flags, queue, id, sender, callback, context);
+}
+
+/* adefer_warn - send copy of defer log to sender as warning bounce */
+
+void adefer_warn(int flags, const char *queue, const char *id,
+ const char *sender, ABOUNCE_FN callback, char *context)
+{
+ abounce_request(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER, BOUNCE_CMD_WARN,
+ flags, queue, id, sender, callback, context);
+}
--- /dev/null
+#ifndef _ABOUNCE_H_INCLUDED_
+#define _ABOUNCE_H_INCLUDED_
+
+/*++
+/* NAME
+/* abounce 3h
+/* SUMMARY
+/* asynchronous bounce/defer service client
+/* SYNOPSIS
+/* #include <abounce.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Global library.
+ */
+#include <bounce.h>
+
+ /*
+ * Client interface.
+ */
+typedef void (*ABOUNCE_FN) (int, char *);
+
+extern void abounce_flush(int, const char *, const char *, const char *, ABOUNCE_FN, char *);
+extern void adefer_flush(int, const char *, const char *, const char *, ABOUNCE_FN, char *);
+extern void adefer_warn(int, const char *, const char *, const char *, ABOUNCE_FN, char *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
/* char *var_relay_domains;
/* char *var_fflush_domains;
/*
+/* char *var_import_environ;
+/* char *var_export_environ;
+/*
/* void mail_params_init()
/* DESCRIPTION
/* This module (actually the associated include file) define the names
char *var_relay_domains;
char *var_fflush_domains;
+char *var_import_environ;
+char *var_export_environ;
+
/* check_myhostname - lookup hostname and validate */
static const char *check_myhostname(void)
VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 1,
VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0,
VAR_FFLUSH_DOMAINS, DEF_FFLUSH_DOMAINS, &var_fflush_domains, 0, 0,
+ VAR_EXPORT_ENVIRON, DEF_EXPORT_ENVIRON, &var_export_environ, 0, 0,
+ VAR_IMPORT_ENVIRON, DEF_IMPORT_ENVIRON, &var_import_environ, 0, 0,
0,
};
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
#define DEF_FFLUSH_REFRESH "12h"
extern int var_fflush_refresh;
+ /*
+ * Environmental management - what Postfix imports from the external world,
+ * and what Postfix exports to the external world.
+ */
+#define VAR_IMPORT_ENVIRON "import_environment"
+#define DEF_IMPORT_ENVIRON "MAIL_CONFIG, TZ, XAUTHORITY, DISPLAY"
+extern char *var_import_environ;
+
+#define VAR_EXPORT_ENVIRON "export_environment"
+#define DEF_EXPORT_ENVIRON "TZ"
+extern char *var_export_environ;
+
/* LICENSE
/* .ad
/* .fi
+Unterminated comment
+
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
#include <vstring.h>
#include <vstream.h>
#include <stringops.h>
+#include <argv.h>
/* Global library. */
#include <mail_proto.h>
#include <mail_queue.h>
#include <opened.h>
+#include <mail_params.h>
#include <mail_stream.h>
/* Application-specific. */
{
VSTREAM *stream;
MAIL_STREAM *info;
+ ARGV *export_env;
if (id_buf == 0)
id_buf = vstring_alloc(10);
* Treat fork() failure as a transient problem. Treat bad handshake as a
* permanent error.
*/
- while ((stream = vstream_popen(command, O_RDWR)) == 0) {
+ export_env = argv_split(var_export_environ, ", \t\r\n");
+ while ((stream = vstream_popen(O_RDWR,
+ VSTREAM_POPEN_COMMAND, command,
+ VSTREAM_POPEN_EXPORT, export_env->argv,
+ VSTREAM_POPEN_END)) == 0) {
msg_warn("fork: %m");
sleep(10);
}
+ argv_free(export_env);
+
if (mail_scan(stream, "%s", id_buf) != 1) {
vstream_pclose(stream);
return (0);
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20001203"
+#define DEF_MAIL_VERSION "Snapshot-20001208"
extern char *var_mail_version;
/* LICENSE
/* Additional environment information, in the form of a null-terminated
/* list of name, value, name, value, ... elements. By default only the
/* command search path is initialized to _PATH_DEFPATH.
+/* .IP "PIPE_CMD_EXPORT (char **)"
+/* Null-terminated array with names of environment parameters
+/* that can be exported. By default, everything is exported.
/* .IP "PIPE_CMD_COPY_FLAGS (int)"
/* Flags that are passed on to the \fImail_copy\fR() routine.
/* The default flags value is 0 (zero).
uid_t uid; /* privileges */
gid_t gid; /* privileges */
char **env; /* extra environment */
+ char **export; /* exportable environment */
char *shell; /* command shell */
};
args->uid = var_default_uid;
args->gid = var_default_gid;
args->env = 0;
+ args->export = 0;
args->shell = 0;
pipe_command_maxtime = var_command_maxtime;
case PIPE_CMD_ENV:
args->env = va_arg(ap, char **);
break;
+ case PIPE_CMD_EXPORT:
+ args->export = va_arg(ap, char **);
+ break;
case PIPE_CMD_SHELL:
args->shell = va_arg(ap, char *);
break;
* Environment plumbing. Always reset the command search path. XXX
* That should probably be done by clean_env().
*/
- clean_env();
+ if (args.export)
+ clean_env(args.export);
if (setenv("PATH", _PATH_DEFPATH, 1))
msg_fatal("%s: setenv: %m", myname);
if (args.env)
#define PIPE_CMD_ENV 9 /* extra environment */
#define PIPE_CMD_SHELL 10 /* alternative shell */
#define PIPE_CMD_EOL 11 /* record delimiter */
+#define PIPE_CMD_EXPORT 12 /* exportable environment */
/*
* Command completion status.
/*
/* Reserved addresses are not split: postmaster, mailer-daemon,
/* double-bounce. Addresses that begin with owner-, or addresses
-/* that end in -request are not split, unless the owner_request_special
+/* that end in -request are not split when the owner_request_special
/* parameter is set.
/* LICENSE
/* .ad
mailbox.o: ../../include/stringops.h
mailbox.o: ../../include/set_eugid.h
mailbox.o: ../../include/mail_copy.h
-mailbox.o: ../../include/safe_open.h
-mailbox.o: ../../include/deliver_flock.h
-mailbox.o: ../../include/myflock.h
-mailbox.o: ../../include/dot_lockfile.h
mailbox.o: ../../include/defer.h
mailbox.o: ../../include/bounce.h
mailbox.o: ../../include/sent.h
mailbox.o: ../../include/mail_proto.h
mailbox.o: ../../include/iostuff.h
mailbox.o: ../../include/mbox_open.h
+mailbox.o: ../../include/safe_open.h
mailbox.o: local.h
mailbox.o: ../../include/tok822.h
mailbox.o: ../../include/resolve_clnt.h
int copy_flags;
char **cpp;
char *cp;
+ ARGV *export_env;
/*
* Make verbose logging easier to understand.
for (cp = cpp[1]; *(cp += strspn(cp, var_cmd_exp_filter)) != 0;)
*cp++ = '_';
+ export_env = argv_split(var_export_environ, ", \t\r\n");
+
cmd_status = pipe_command(state.msg_attr.fp, why,
PIPE_CMD_UID, usr_attr.uid,
PIPE_CMD_GID, usr_attr.gid,
PIPE_CMD_DELIVERED, state.msg_attr.delivered,
PIPE_CMD_TIME_LIMIT, var_command_maxtime,
PIPE_CMD_ENV, env->argv,
+ PIPE_CMD_EXPORT, export_env->argv,
PIPE_CMD_SHELL, var_local_cmd_shell,
PIPE_CMD_END);
+ argv_free(export_env);
argv_free(env);
/*
/* When delivering to an alias that has an owner- companion alias,
/* set the envelope sender address to the right-hand side of the
/* owner alias, instead using of the left-hand side address.
+/* .IP \fBexport_environment\fR
+/* List of names of environment parameters that can be exported
+/* to non-Postfix processes.
/* .IP \fBforward_path\fR
/* Search list for .forward files. The names are subject to \fI$name\fR
/* expansion.
/* .SH Miscellaneous
/* .ad
/* .fi
+/* .IP \fBimport_environment\fR
+/* .IP \fBexport_environment\fR
+/* Lists of names of environment parameters that can be imported
+/* from (exported to) non-Postfix processes.
/* .IP \fBmail_owner\fR
/* The owner of the mail queue and of most Postfix processes.
/* .IP \fBcommand_directory\fR
#include <myflock.h>
#include <watchdog.h>
#include <clean_env.h>
+#include <argv.h>
/* Global library. */
int fd_limit = open_limit(0);
VSTRING *why;
WATCHDOG *watchdog;
+ ARGV *import_env;
/*
* Initialize.
if (getenv(CONF_ENV_DEBUG))
debug_me = 1;
- /*
- * Ad-hoc environment filter, to enforce consistent behavior whether
- * Postfix is started by hand, or at system boot time.
- */
- clean_env();
-
/*
* Don't die when a process goes away unexpectedly.
*/
* files.
*/
master_vars_init();
+
+ /*
+ * Environment import filter, to enforce consistent behavior whether
+ * Postfix is started by hand, or at system boot time. The argument list
+ * specifies what environment parameters to preserve.
+ */
+ import_env = argv_split(var_import_environ, ", \t\r\n");
+ clean_env(import_env->argv);
+ argv_free(import_env);
+
if ((inherited_limit = get_file_limit()) < (off_t) var_message_limit) {
msg_warn("file size limit %lu < message_size_limit %lu -- reset",
(unsigned long) inherited_limit, (unsigned long) var_message_limit);
#include <recipient_list.h>
#include <bounce.h>
#include <defer.h>
+#include <abounce.h>
#include <rec_type.h>
/* Application-specific. */
#include "qmgr.h"
+ /*
+ * A bunch of call-back routines.
+ */
+static void qmgr_active_done_2_bounce_flush(int, char *);
+static void qmgr_active_done_2_generic(QMGR_MESSAGE *);
+static void qmgr_active_done_3_defer_flush(int, char *);
+static void qmgr_active_done_3_defer_warn(int, char *);
+static void qmgr_active_done_3_generic(QMGR_MESSAGE *);
+
/* qmgr_active_corrupt - move corrupted file out of the way */
static void qmgr_active_corrupt(const char *queue_id)
{
char *myname = "qmgr_active_done";
struct stat st;
- const char *path;
- int delay;
if (msg_verbose)
msg_info("%s: %s", myname, message->queue_id);
* Don't bounce when the bounce log is empty. The bounce process obviously
* failed, and the delivery agent will have requested that the message be
* deferred.
+ *
+ * Bounces are sent asynchronously to avoid stalling while the cleanup
+ * daemon waits for the qmgr to accept the "new mail" trigger.
*/
if (stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_BOUNCE, message->queue_id), &st) == 0) {
if (st.st_size == 0) {
} else {
if (msg_verbose)
msg_info("%s: bounce %s", myname, message->queue_id);
- message->flags |= bounce_flush(BOUNCE_FLAG_KEEP,
- message->queue_name,
- message->queue_id,
- message->errors_to);
+ abounce_flush(BOUNCE_FLAG_KEEP,
+ message->queue_name,
+ message->queue_id,
+ message->errors_to,
+ qmgr_active_done_2_bounce_flush,
+ (char *) message);
+ return;
}
}
+ /*
+ * Asynchronous processing does not reach this point.
+ */
+ qmgr_active_done_2_generic(message);
+}
+
+/* qmgr_active_done_2_bounce_flush - process abounce_flush() status */
+
+static void qmgr_active_done_2_bounce_flush(int status, char *context)
+{
+ QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+ /*
+ * Process abounce_flush() status and continue processing.
+ */
+ message->flags |= status;
+ qmgr_active_done_2_generic(message);
+}
+
+/* qmgr_active_done_2_generic - continue processing */
+
+static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
+{
+ char *myname = "qmgr_active_done_2_generic";
+ const char *path;
+ struct stat st;
+
/*
* A delivery agent marks a queue file as corrupt by changing its
* attributes, and by pretending that delivery was deferred.
/*
* If we get to this point we have tried all recipients for this message.
* If the message is too old, try to bounce it.
+ *
+ * Bounces are sent asynchronously to avoid stalling while the cleanup
+ * daemon waits for the qmgr to accept the "new mail" trigger.
*/
#define HOUR 3600
#define DAY 86400
if (event_time() > message->arrival_time + var_max_queue_time * DAY) {
if (msg_verbose)
msg_info("%s: too old, bouncing %s", myname, message->queue_id);
- message->flags = defer_flush(BOUNCE_FLAG_KEEP,
- message->queue_name,
- message->queue_id,
- message->errors_to);
+ adefer_flush(BOUNCE_FLAG_KEEP,
+ message->queue_name,
+ message->queue_id,
+ message->errors_to,
+ qmgr_active_done_3_defer_flush,
+ (char *) message);
+ return;
} else if (message->warn_time > 0
&& event_time() > message->warn_time) {
if (msg_verbose)
msg_info("%s: sending defer warning for %s", myname, message->queue_id);
- if (defer_warn(BOUNCE_FLAG_KEEP,
- message->queue_name,
- message->queue_id,
- message->errors_to) == 0) {
- qmgr_message_update_warn(message);
- }
+ adefer_warn(BOUNCE_FLAG_KEEP,
+ message->queue_name,
+ message->queue_id,
+ message->errors_to,
+ qmgr_active_done_3_defer_warn,
+ (char *) message);
+ return;
}
}
+ /*
+ * Asynchronous processing does not reach this point.
+ */
+ qmgr_active_done_3_generic(message);
+}
+
+/* qmgr_active_done_3_defer_warn - continue after adefer_warn() completion */
+
+static void qmgr_active_done_3_defer_warn(int status, char *context)
+{
+ QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+ /*
+ * Process adefer_warn() completion status and continue processing.
+ */
+ if (status == 0)
+ qmgr_message_update_warn(message);
+ qmgr_active_done_3_generic(message);
+}
+
+/* qmgr_active_done_3_defer_flush - continue after adefer_flush() completion */
+
+static void qmgr_active_done_3_defer_flush(int status, char *context)
+{
+ QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+ /*
+ * Process adefer_flush() status and continue processing.
+ */
+ message->flags = status;
+ qmgr_active_done_3_generic(message);
+}
+
+/* qmgr_active_done_3_generic - continue processing */
+
+static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
+{
+ char *myname = "qmgr_active_done_3_generic";
+ int delay;
+
/*
* Some recipients need to be tried again. Move the queue file time
* stamps into the future by the amount of time that the message is
/* .SH Miscellaneous
/* .ad
/* .fi
+/* .IP \fBexport_environment\fR
+/* List of names of environment parameters that can be exported
+/* to non-Postfix processes.
/* .IP \fBmail_owner\fR
/* The process privileges used while not running an external command.
/* .SH "Resource controls"
ARGV *expanded_argv = 0;
int deliver_status;
int command_status;
+ ARGV *export_env;
#define DELIVER_MSG_CLEANUP() { \
vstring_free(why); \
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SENDER, request->sender);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_NEXTHOP, request->nexthop);
expanded_argv = expand_argv(attr.command, rcpt_list, request->data_size);
+ export_env = argv_split(var_export_environ, ", \t\r\n");
command_status = pipe_command(request->fp, why,
PIPE_CMD_UID, attr.uid,
PIPE_CMD_ARGV, expanded_argv->argv,
PIPE_CMD_TIME_LIMIT, conf.time_limit,
PIPE_CMD_EOL, STR(attr.eol),
+ PIPE_CMD_EXPORT, export_env->argv,
PIPE_CMD_END);
+ argv_free(export_env);
deliver_status = eval_command_status(command_status, service, request,
request->fp, vstring_str(why));
/* See the Postfix \fBmain.cf\fR file for syntax details and for
/* default values. Use the \fBpostfix reload\fR command after a
/* configuration change.
+/* .IP \fBimport_environment\fR
+/* List of names of environment parameters that can be imported
+/* from non-Postfix processes.
/* .IP \fBqueue_directory\fR
/* Top-level directory of the Postfix queue. This is also the root
/* directory of Postfix daemons that run chrooted.
#include <vstring.h>
#include <msg_vstream.h>
#include <msg_syslog.h>
+#include <argv.h>
/* Global library. */
};
char **expected;
uid_t uid = getuid();
+ ARGV *import_env;
/*
* Be consistent with file permissions.
/*
* Strip the environment so we don't have to trust the C library.
*/
- clean_env();
+ import_env = argv_split(var_import_environ, ", \t\r\n");
+ clean_env(import_env->argv);
+ argv_free(import_env);
/*
* Set up logging. Censor the process name: it is provided by the user.
postlock.o: ../../include/vstream.h
postlock.o: ../../include/msg_vstream.h
postlock.o: ../../include/iostuff.h
-postlock.o: ../../include/safe_open.h
postlock.o: ../../include/mail_params.h
postlock.o: ../../include/dot_lockfile.h
postlock.o: ../../include/deliver_flock.h
postlock.o: ../../include/mbox_conf.h
postlock.o: ../../include/argv.h
postlock.o: ../../include/mbox_open.h
+postlock.o: ../../include/safe_open.h
#include <recipient_list.h>
#include <bounce.h>
#include <defer.h>
+#include <abounce.h>
#include <rec_type.h>
/* Application-specific. */
#include "qmgr.h"
+ /*
+ * A bunch of call-back routines.
+ */
+static void qmgr_active_done_2_bounce_flush(int, char *);
+static void qmgr_active_done_2_generic(QMGR_MESSAGE *);
+static void qmgr_active_done_3_defer_flush(int, char *);
+static void qmgr_active_done_3_defer_warn(int, char *);
+static void qmgr_active_done_3_generic(QMGR_MESSAGE *);
+
/* qmgr_active_corrupt - move corrupted file out of the way */
static void qmgr_active_corrupt(const char *queue_id)
{
char *myname = "qmgr_active_done";
struct stat st;
- const char *path;
- int delay;
if (msg_verbose)
msg_info("%s: %s", myname, message->queue_id);
* Don't bounce when the bounce log is empty. The bounce process obviously
* failed, and the delivery agent will have requested that the message be
* deferred.
+ *
+ * Bounces are sent asynchronously to avoid stalling while the cleanup
+ * daemon waits for the qmgr to accept the "new mail" trigger.
*/
if (stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_BOUNCE, message->queue_id), &st) == 0) {
if (st.st_size == 0) {
} else {
if (msg_verbose)
msg_info("%s: bounce %s", myname, message->queue_id);
- message->flags |= bounce_flush(BOUNCE_FLAG_KEEP,
- message->queue_name,
- message->queue_id,
- message->errors_to);
+ abounce_flush(BOUNCE_FLAG_KEEP,
+ message->queue_name,
+ message->queue_id,
+ message->errors_to,
+ qmgr_active_done_2_bounce_flush,
+ (char *) message);
+ return;
}
}
+ /*
+ * Asynchronous processing does not reach this point.
+ */
+ qmgr_active_done_2_generic(message);
+}
+
+/* qmgr_active_done_2_bounce_flush - process abounce_flush() status */
+
+static void qmgr_active_done_2_bounce_flush(int status, char *context)
+{
+ QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+ /*
+ * Process abounce_flush() status and continue processing.
+ */
+ message->flags |= status;
+ qmgr_active_done_2_generic(message);
+}
+
+/* qmgr_active_done_2_generic - continue processing */
+
+static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
+{
+ char *myname = "qmgr_active_done_2_generic";
+ const char *path;
+ struct stat st;
+
/*
* A delivery agent marks a queue file as corrupt by changing its
* attributes, and by pretending that delivery was deferred.
/*
* If we get to this point we have tried all recipients for this message.
* If the message is too old, try to bounce it.
+ *
+ * Bounces are sent asynchronously to avoid stalling while the cleanup
+ * daemon waits for the qmgr to accept the "new mail" trigger.
*/
#define HOUR 3600
#define DAY 86400
if (event_time() > message->arrival_time + var_max_queue_time * DAY) {
if (msg_verbose)
msg_info("%s: too old, bouncing %s", myname, message->queue_id);
- message->flags = defer_flush(BOUNCE_FLAG_KEEP,
- message->queue_name,
- message->queue_id,
- message->errors_to);
+ adefer_flush(BOUNCE_FLAG_KEEP,
+ message->queue_name,
+ message->queue_id,
+ message->errors_to,
+ qmgr_active_done_3_defer_flush,
+ (char *) message);
+ return;
} else if (message->warn_time > 0
&& event_time() > message->warn_time) {
if (msg_verbose)
msg_info("%s: sending defer warning for %s", myname, message->queue_id);
- if (defer_warn(BOUNCE_FLAG_KEEP,
- message->queue_name,
- message->queue_id,
- message->errors_to) == 0) {
- qmgr_message_update_warn(message);
- }
+ adefer_warn(BOUNCE_FLAG_KEEP,
+ message->queue_name,
+ message->queue_id,
+ message->errors_to,
+ qmgr_active_done_3_defer_warn,
+ (char *) message);
+ return;
}
}
+ /*
+ * Asynchronous processing does not reach this point.
+ */
+ qmgr_active_done_3_generic(message);
+}
+
+/* qmgr_active_done_3_defer_warn - continue after adefer_warn() completion */
+
+static void qmgr_active_done_3_defer_warn(int status, char *context)
+{
+ QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+ /*
+ * Process adefer_warn() completion status and continue processing.
+ */
+ if (status == 0)
+ qmgr_message_update_warn(message);
+ qmgr_active_done_3_generic(message);
+}
+
+/* qmgr_active_done_3_defer_flush - continue after adefer_flush() completion */
+
+static void qmgr_active_done_3_defer_flush(int status, char *context)
+{
+ QMGR_MESSAGE *message = (QMGR_MESSAGE *) context;
+
+ /*
+ * Process adefer_flush() status and continue processing.
+ */
+ message->flags = status;
+ qmgr_active_done_3_generic(message);
+}
+
+/* qmgr_active_done_3_generic - continue processing */
+
+static void qmgr_active_done_3_generic(QMGR_MESSAGE *message)
+{
+ char *myname = "qmgr_active_done_3_generic";
+ int delay;
+
/*
* Some recipients need to be tried again. Move the queue file time
* stamps into the future by the amount of time that the message is
smtp_chat.o: ../../include/mail_addr.h
smtp_chat.o: ../../include/post_mail.h
smtp_chat.o: ../../include/cleanup_user.h
+smtp_chat.o: ../../include/mail_error.h
+smtp_chat.o: ../../include/name_mask.h
smtp_chat.o: smtp.h
smtp_connect.o: smtp_connect.c
smtp_connect.o: ../../include/sys_defs.h
/* .SH Miscellaneous
/* .ad
/* .fi
+/* .IP \fBexport_environment\fR
+/* List of names of environment parameters that can be exported
+/* to non-Postfix processes.
/* .IP \fBmail_owner\fR
/* The process privileges used while not running an external command.
/* .SH Resource control
char *myname = "spawn_service";
static SPAWN_ATTR attr;
WAIT_STATUS_T status;
+ ARGV *export_env;
/*
* This routine runs whenever a client connects to the UNIX-domain socket
/*
* Execute the command.
*/
+ export_env = argv_split(var_export_environ, ", \t\r\n");
status = spawn_command(SPAWN_CMD_STDIN, vstream_fileno(client_stream),
SPAWN_CMD_STDOUT, vstream_fileno(client_stream),
SPAWN_CMD_STDERR, vstream_fileno(client_stream),
SPAWN_CMD_GID, attr.gid,
SPAWN_CMD_ARGV, attr.argv,
SPAWN_CMD_TIME_LIMIT, attr.time_limit,
+ SPAWN_CMD_EXPORT, export_env->argv,
SPAWN_CMD_END);
+ argv_free(export_env);
/*
* Warn about unsuccessful completion.
clean_env.o: clean_env.c
clean_env.o: sys_defs.h
clean_env.o: msg.h
+clean_env.o: argv.h
+clean_env.o: safe.h
clean_env.o: clean_env.h
close_on_exec.o: close_on_exec.c
close_on_exec.o: sys_defs.h
myflock.o: myflock.c
myflock.o: sys_defs.h
myflock.o: msg.h
-myflock.o: vstring.h
-myflock.o: vbuf.h
myflock.o: myflock.h
mymalloc.o: mymalloc.c
mymalloc.o: sys_defs.h
/* SYNOPSIS
/* #include <clean_env.h>
/*
-/* void clean_env()
+/* void clean_env(export_list)
+/* const char **export_list;
/* DESCRIPTION
/* clean_env() reduces the process environment to the bare minimum.
-/* In the initial version, rules are hard-coded. This will be
-/* made configurable.
+/* The function takes a null-terminated list of arguments.
+/* Each argument specifies the name of an environment variable
+/* that should be preserved.
+/* DIAGNOSTICS
+/* Fatal error: out of memory.
+/* SEE ALSO
+/* safe_getenv(3), guarded getenv()
/* LICENSE
/* .ad
/* .fi
/* Utility library. */
#include <msg.h>
+#include <argv.h>
+#include <safe.h>
#include <clean_env.h>
/* clean_env - clean up the environment */
-void clean_env(void)
+void clean_env(char **export_list)
{
- char *TZ;
- char *DISPLAY;
- char *XAUTHORITY;
- char *HOME;
- char *PURIFYOPTIONS;
extern char **environ;
+ ARGV *save_list;
+ char *value;
+ char **cpp;
/*
- * Preserve selected environment variables. This list will be
- * configurable.
+ * Preserve selected environment variables.
*/
- TZ = getenv("TZ");
- DISPLAY = getenv("DISPLAY");
- XAUTHORITY = getenv("XAUTHORITY");
- HOME = getenv("HOME");
- PURIFYOPTIONS = getenv("PURIFYOPTIONS");
+ save_list = argv_alloc(10);
+ for (cpp = export_list; *cpp; cpp++)
+ if ((value = safe_getenv(*cpp)) != 0)
+ argv_add(save_list, *cpp, value, (char *) 0);
+ argv_terminate(save_list);
/*
* Truncate the process environment, if available. On some systems
/*
* Restore preserved environment variables.
*/
- if (TZ && setenv("TZ", TZ, 1))
- msg_fatal("setenv: %m");
- if (DISPLAY && setenv("DISPLAY", DISPLAY, 1))
- msg_fatal("setenv: %m");
- if (XAUTHORITY && setenv("XAUTHORITY", XAUTHORITY, 1))
- msg_fatal("setenv: %m");
- if (HOME && setenv("HOME", HOME, 1))
- msg_fatal("setenv: %m");
- if (PURIFYOPTIONS && setenv("PURIFYOPTIONS", PURIFYOPTIONS, 1))
- msg_fatal("setenv: %m");
+ for (cpp = save_list->argv; *cpp; cpp += 2)
+ if (setenv(cpp[0], cpp[1], 1))
+ msg_fatal("setenv: %m");
/*
- * Update the process environment with configurable initial values.
+ * Cleanup.
*/
+ argv_free(save_list);
}
/*
* External interface.
*/
-extern void clean_env(void);
+extern void clean_env(char **);
/* LICENSE
/* .ad
/* Additional environment information, in the form of a null-terminated
/* list of name, value, name, value, ... elements. By default only the
/* command search path is initialized to _PATH_DEFPATH.
+/* .IP "SPAWN_CMD_EXPORT (char **)"
+/* Null-terminated array of names of environment parameters that can
+/* be exported. By default, everything is exported.
/* .IP "SPAWN_CMD_STDIN (int)"
/* .IP "SPAWN_CMD_STDOUT (int)"
/* .IP "SPAWN_CMD_STDERR (int)"
uid_t uid; /* privileges */
gid_t gid; /* privileges */
char **env; /* extra environment */
+ char **export; /* exportable environment */
char *shell; /* command shell */
int time_limit; /* command time limit */
};
args->uid = (uid_t) - 1;
args->gid = (gid_t) - 1;
args->env = 0;
+ args->export = 0;
args->shell = 0;
args->time_limit = 0;
case SPAWN_CMD_ENV:
args->env = va_arg(ap, char **);
break;
+ case SPAWN_CMD_EXPORT:
+ args->export = va_arg(ap, char **);
+ break;
case SPAWN_CMD_SHELL:
args->shell = va_arg(ap, char *);
break;
* Environment plumbing. Always reset the command search path. XXX
* That should probably be done by clean_env().
*/
- clean_env();
+ if (args.export)
+ clean_env(args.export);
if (setenv("PATH", _PATH_DEFPATH, 1))
msg_fatal("%s: setenv: %m", myname);
if (args.env)
#define SPAWN_CMD_TIME_LIMIT 8 /* time limit */
#define SPAWN_CMD_ENV 9 /* extra environment */
#define SPAWN_CMD_SHELL 10 /* alternative shell */
+#define SPAWN_CMD_EXPORT 11 /* exportable parameters */
extern WAIT_STATUS_T spawn_command(int,...);
#define HAS_FLOCK_LOCK
#define HAS_FCNTL_LOCK
#define INTERNAL_LOCK MYFLOCK_STYLE_FLOCK
+#define DEF_MAILBOX_LOCK "flock"
#define HAS_SUN_LEN
#define HAS_FSYNC
#define HAS_DB
#endif
#if defined(NETBSD1)
+#undef DEF_MAILBOX_LOCK
#define DEF_MAILBOX_LOCK "flock, dotlock"
-#endif
-
-#ifndef DEF_MAILBOX_LOCK
-#define DEF_MAILBOX_LOCK "flock"
#endif
/*
extern VSTREAM *PRINTFLIKE(1, 2) vstream_printf(const char *,...);
extern VSTREAM *PRINTFLIKE(2, 3) vstream_fprintf(VSTREAM *, const char *,...);
-extern VSTREAM *vstream_popen(const char *, int);
-extern VSTREAM *vstream_popen_vargs(int,...);
+extern VSTREAM *vstream_popen(int,...);
extern int vstream_pclose(VSTREAM *);
#define vstream_ispipe(vp) ((vp)->pid != 0)
#define VSTREAM_POPEN_ENV 5 /* extra environment */
#define VSTREAM_POPEN_SHELL 6 /* alternative shell */
#define VSTREAM_POPEN_WAITPID_FN 7 /* child catcher, waitpid() compat. */
+#define VSTREAM_POPEN_EXPORT 8 /* exportable environment */
extern VSTREAM *vstream_vfprintf(VSTREAM *, const char *, va_list);
/* SYNOPSIS
/* #include <vstream.h>
/*
-/* VSTREAM *vstream_popen(command, flags)
-/* cont char *command;
+/* VSTREAM *vstream_popen(flags, key, value, ...)
/* int flags;
+/* int key;
/*
/* int vstream_pclose(stream)
/* VSTREAM *stream;
-/*
-/* VSTREAM *vstream_popen_vargs(key, value, ...)
-/* int key;
/* DESCRIPTION
-/* vstream_popen() opens a one-way or two-way stream to the specified
-/* \fIcommand\fR, which is executed by a child process. The \fIflags\fR
+/* vstream_popen() opens a one-way or two-way stream to a user-specified
+/* command, which is executed by a child process. The \fIflags\fR
/* argument is as with vstream_fopen(). The child's standard input and
/* standard output are redirected to the stream, which is based on a
-/* socketpair or other suitable local IPC.
-/*
-/* vstream_popen_vargs() offers the user more control over the
-/* child process and over how it is managed. The key argument
-/* specifies what value will follow. pipe_command() takes a list
-/* of (key, value) arguments, terminated by VSTREAM_POPEN_END. The
-/* following is a listing of key codes together with the expected
-/* value type.
+/* socketpair or other suitable local IPC. vstream_popen() takes a list
+/* of (key, value) arguments, terminated by VSTREAM_POPEN_END. The key
+/* argument specifies what value will follow. The following is a listing
+/* of key codes together with the expected value type.
/* .RS
/* .IP "VSTREAM_POPEN_COMMAND (char *)"
/* Specifies the command to execute as a string. The string is
/* Additional environment information, in the form of a null-terminated
/* list of name, value, name, value, ... elements. By default only the
/* command search path is initialized to _PATH_DEFPATH.
+/* .IP "VSTREAM_POPEN_EXPORT (char **)"
+/* Null-terminated array of names of environment parameters
+/* that can be exported. By default, everything is exported.
/* .IP "VSTREAM_POPEN_UID (int)"
/* The user ID to execute the command as. The user ID must be non-zero.
/* .IP "VSTREAM_POPEN_GID (int)"
gid_t gid;
int privileged;
char **env;
+ char **export;
char *shell;
VSTREAM_WAITPID_FN waitpid_fn;
} VSTREAM_POPEN_ARGS;
args->gid = 0;
args->privileged = 0;
args->env = 0;
+ args->export = 0;
args->shell = 0;
args->waitpid_fn = 0;
case VSTREAM_POPEN_ENV:
args->env = va_arg(ap, char **);
break;
+ case VSTREAM_POPEN_EXPORT:
+ args->export = va_arg(ap, char **);
+ break;
case VSTREAM_POPEN_SHELL:
args->shell = va_arg(ap, char *);
break;
msg_panic("%s: privileged gid", myname);
}
-/* vstream_popen_vargs - open stream to child process */
+/* vstream_popen - open stream to child process */
-VSTREAM *vstream_popen_vargs(int flags,...)
+VSTREAM *vstream_popen(int flags,...)
{
- char *myname = "vstream_popen_vargs";
+ char *myname = "vstream_popen";
VSTREAM_POPEN_ARGS args;
va_list ap;
VSTREAM *stream;
* Environment plumbing. Always reset the command search path. XXX
* That should probably be done by clean_env().
*/
- clean_env();
+ if (args.export)
+ clean_env(args.export);
if (setenv("PATH", _PATH_DEFPATH, 1))
msg_fatal("%s: setenv: %m", myname);
if (args.env)
}
}
-/* vstream_popen - retro-compatible wrapper for new interface */
-
-VSTREAM *vstream_popen(const char *command, int flags)
-{
- return (vstream_popen_vargs(flags,
- VSTREAM_POPEN_COMMAND, command,
- VSTREAM_POPEN_END));
-}
-
/* vstream_pclose - close stream to child process */
int vstream_pclose(VSTREAM *stream)