-TDICT_PCRE_REGEXP
-TDICT_PCRE_RULE
-TDICT_PGSQL
+-TDICT_PIPE
-TDICT_PROXY
+-TDICT_RAND
+-TDICT_RANDOM
-TDICT_REGEXP
-TDICT_REGEXP_EXPAND_CONTEXT
-TDICT_REGEXP_IF_RULE
-TDICT_SOCKMAP
-TDICT_SOCKMAP_REFC_HANDLE
-TDICT_SQLITE
--TDICT_STACK
-TDICT_SURROGATE
-TDICT_TCP
-TDICT_TEXT
the "ln -n" option is not universally implemented, so we
remove the old symlink first. Problem reported by Viktor.
File: postfix-install.
+
+20140603
+
+ Cleanup: use the OpenSSL session id accessor (available
+ since OpenSSL 0.9.8 or so) instead of groping a session
+ object directly. Viktor Dukhovni. File: tls_server.c.
+
+20140605
+
+ Feature: the pipe(8) daemon logs some command output after
+ successful delivery as "dsn=2.0.0, status=sent (delivered
+ via XXX service (YYY))" where XXX is the master.cf service
+ name, and YYY is command output. Files: pipe/command.c,
+ pipe.c.
+
+20140613
+
+ Feature: the "pipeline" table implements a table pipeline.
+ Example "pipeline:!type_1:name_1!...!type_n:name_n". The
+ ASCII character after "pipeline:" will be used as the
+ separator between the lookup tables that follow (do not use
+ space, ",", ":" or non-ASCII). Each "pipeline:" query is
+ given to the first table. Each lookup result becomes the
+ query for the next table in the pipeline, and the last table
+ produces the final result. When any table lookup produces
+ no result, the pipeline produces no result. Files:
+ dict_pipe.[hc], dict_open.c, postlink, DATABASE_README.html,
+ postconf.c.
+
+20140617
+
+ Feature: the "random" table performs random selection.
+ Example: "random:!result_1!...!result_n". Each table query
+ returns a random choice from the specified results. The
+ ASCII character after "random:" will be used as the separator
+ between the results that follow (do not use space, ",", ":"
+ or non-ASCII). Files: dict_random.[hc], dict_open.c,
+ postlink, DATABASE_README.html, postconf.c.
+
+20140618
+
+ Cleanup: INFO action in access(5) tables, for consistency
+ with header/body_checks. Viktor Dukhovni. Files:
+ smtpd/smtpd_check.c, proto/access.
A lookup table based on Perl Compatible Regular Expressions. The file
format is described in pcre_table(5). The lookup table name as used in
"pcre:table" is the name of the regular expression file.
+ p\bpi\bip\bpe\bel\bli\bin\bne\be (read-only)
+ A pipeline of lookup tables. Example: "p\bpi\bip\bpe\bel\bli\bin\bne\be:\b:!type_1:name_1! ...
+ !type_n:name_n". Each "pipeline:" query is given to the first table.
+ Each lookup result becomes the query for the next table in the
+ pipeline, and the last table produces the final result. When any table
+ lookup produces no result, the pipeline produces no result. The ASCII
+ character after "pipeline:" will be used as the separator between the
+ lookup tables that follow (do not use space, ",", ":" or non-ASCII).
p\bpg\bgs\bsq\bql\bl (read-only)
PostgreSQL database client. Configuration details are given in
pgsql_table(5).
p\bpr\bro\box\bxy\by
Postfix proxymap(8) client for shared access to Postfix databases. The
lookup table name syntax is "proxy:type:table".
+ r\bra\ban\bnd\bdo\bom\bm (read-only)
+ An in-memory table that performs random selection. Example: "r\bra\ban\bnd\bdo\bom\bm:\b:
+ !result_1! ... !result_n". Each table query returns a random choice
+ from the specified results. The ASCII character after "random:" will be
+ used as the separator between the results that follow (do not use
+ space, ",", ":" or non-ASCII).
r\bre\beg\bge\bex\bxp\bp (read-only)
A lookup table based on regular expressions. The file format is
described in regexp_table(5). The lookup table name as used in "regexp:
(mantools/srctoman - makedefs | nroff -man | less) with information
about build options that are not described in the INSTALL instructions.
+Incompatible changes with snapshot 20140618
+===========================================
+
+The pipe(8) delivery agent will now log a limited amount of command
+output upon successful delivery, and will report that output in
+"SUCCESS" delivery status reports. This is another good reason to
+disable inbound DSN requests at the Internet perimeter.
+
+Major changes with snapshot 20140618
+====================================
+
+This introduces several lookup tables with unusual properties.
+
+random table
+------------
+
+The "random" lookup table performs random selection. This may be
+used to implement load balancing, for example:
+
+/etc/postfix/transport:
+ # Deliver my own domain as usual.
+ example.com :
+ .example.com :
+
+/etc/postfix/main.cf:
+ transport_maps =
+ # Deliver my own domain as usual.
+ hash:/etc/postfix/transport
+ # Deliver other domains via randomly-selected relayhosts
+ random:!smtp:smtp0.example.com!smtp:smtp1.example.com
+
+A variant of this can randomly select SMTP clients with different
+smtp_bind_address settings.
+
+The ASCII character after "random:" will be used as the separator
+between the results that follow (do not use space, ",", ":" or
+non-ASCII).
+
+Some future version may support the form random:/path/to/file,
+to load the list of random values, one per line, from a textfile.
+
+To implement different weights, specify lookup results multiple
+times. For example, to choose smtp:smtp1.example.com twice as often
+as smtp:smtp0.example.com, specify smtp:smtp1.example.com twice.
+
+pipeline table
+--------------
+
+As the name suggests, the "pipeline" table implements a pipeline
+of lookup tables. The name of the table specifies the pipeline as
+a sequence of tables. For example, the following prevents SMTP mail
+to system accounts that have "nologin" as their login shell:
+
+ /etc/postfix/main.cf:
+ local_recipient_maps =
+ pipeline:!unix:passwd.byname!pcre:/etc/postfix/no-nologin.pcre
+ alias_maps
+
+ /etc/postfix/no-nologin.pcre:
+ !/nologin/ whatever
+
+The ASCII character after "pipeline:" will be used as the separator
+between the lookup tables that follow (do not use space, ",", ":"
+or non-ASCII).
+
+Each "pipeline:" query is given to the first table. Each table
+lookup result becomes the query for the next table in the pipeline,
+and the last table produces the final result. When any table lookup
+produces no result, the entire pipeline produces no result.
+
+Some future version may support the form pipeline:/path/to/file,
+to load the list of lookup tables, one per line, from a textfile.
+
Incompatible changes with snapshot 20140530
===========================================
Things to do after the stable release:
+ Don't accept AUTH or other features that are not announced
+ in the EHLO response.
+
+ Per-Milter error action.
+
+ Suggested at Mailserver conference: Postscreen RDNS-based
+ reputation (but this introduces dependency on random DNS
+ servers).
+
Discourage the use of "after 220" tests in POSTSCREEN_README
and the documentation of individual parameter settings.
#
# This feature is available in Postfix 2.1 and later.
#
+# INFO optional text...
+# Log an informational record with the optional text,
+# together with client information and if available,
+# with helo, sender, recipient and protocol informa-
+# tion.
+#
+# This feature is available in Postfix 2.12 and
+# later.
+#
# WARN optional text...
# Log a warning with the optional text, together with
# client information and if available, with helo,
#
# if /pattern/flags
#
-# endif Match the input string against the patterns between
-# if and endif, if and only if the same input string
-# also matches /pattern/. The if..endif can nest.
+# endif If the input string matches /pattern/, then match
+# that input string against the patterns between if
+# and endif. The if..endif can nest.
#
# Note: do not prepend whitespace to patterns inside
# if..endif.
#
# if !/pattern/flags
#
-# endif Match the input string against the patterns between
-# if and endif, if and only if the same input string
-# does not match /pattern/. The if..endif can nest.
+# endif If the input string does not match /pattern/, then
+# match that input string against the patterns
+# between if and endif. The if..endif can nest.
#
# blank lines and comments
# Empty lines and whitespace-only lines are ignored,
name as used in "<a href="pcre_table.5.html">pcre</a>:table" is the name of the regular expression
file. </dd>
+<dt> <b>pipeline</b> (read-only) </dt>
+
+<dd> A pipeline of lookup tables. Example:
+"<b><a href="DATABASE_README.html#types">pipeline</a>:</b><i>!type_1:name_1! ... !type_n:name_n</i>". Each
+"<a href="DATABASE_README.html#types">pipeline</a>:" query is given to the first table. Each lookup result
+becomes the query for the next table in the pipeline, and the last
+table produces the final result. When any table lookup produces
+no result, the pipeline produces no result. The ASCII character
+after "<a href="DATABASE_README.html#types">pipeline</a>:" will be used as the separator between the lookup
+tables that follow (do not use space, ",", ":" or non-ASCII). </dd>
+
<dt> <b>pgsql</b> (read-only) </dt>
<dd> PostgreSQL database client. Configuration details are given
databases. The lookup table name syntax is "<a href="proxymap.8.html">proxy</a>:<a href="DATABASE_README.html">type:table</a>".
</dd>
+<dt> <b>random</b> (read-only) </dt>
+
+<dd> An in-memory table that performs random selection. Example:
+"<b><a href="DATABASE_README.html#types">random</a>:</b><i>!result_1! ... !result_n</i>". Each table query
+returns a random choice from the specified results. The ASCII
+character after "<a href="DATABASE_README.html#types">random</a>:" will be used as the separator between the
+results that follow (do not use space, ",", ":" or non-ASCII).
+</dd>
+
<dt> <b>regexp</b> (read-only) </dt>
<dd> A lookup table based on regular expressions. The file format
This feature is available in Postfix 2.1 and later.
+ <b>INFO</b> <i>optional text...</i>
+ Log an informational record with the optional text, together
+ with client information and if available, with helo, sender,
+ recipient and protocol information.
+
+ This feature is available in Postfix 2.12 and later.
+
<b>WARN</b> <i>optional text...</i>
Log a warning with the optional text, together with client
information and if available, with helo, sender, recipient and
<b>if /</b><i>pattern</i><b>/</b><i>flags</i>
- <b>endif</b> Match the input string against the patterns between <b>if</b> and
- <b>endif</b>, if and only if the same input string also matches /<i>pat-</i>
- <i>tern</i>/. The <b>if</b>..<b>endif</b> can nest.
+ <b>endif</b> If the input string matches /<i>pattern</i>/, then match that input
+ string against the patterns between <b>if</b> and <b>endif</b>. The <b>if</b>..<b>endif</b>
+ can nest.
Note: do not prepend whitespace to patterns inside <b>if</b>..<b>endif</b>.
<b>if !/</b><i>pattern</i><b>/</b><i>flags</i>
- <b>endif</b> Match the input string against the patterns between <b>if</b> and
- <b>endif</b>, if and only if the same input string does <b>not</b> match /<i>pat-</i>
- <i>tern</i>/. The <b>if</b>..<b>endif</b> can nest.
+ <b>endif</b> If the input string does not match /<i>pattern</i>/, then match that
+ input string against the patterns between <b>if</b> and <b>endif</b>. The
+ <b>if</b>..<b>endif</b> can nest.
blank lines and comments
Empty lines and whitespace-only lines are ignored, as are lines
<b>if /</b><i>pattern</i><b>/</b><i>flags</i>
- <b>endif</b> Match the input string against the patterns between <b>if</b> and
- <b>endif</b>, if and only if that same input string also matches <i>pat-</i>
- <i>tern</i>. The <b>if</b>..<b>endif</b> can nest.
+ <b>endif</b> If the input string matches /<i>pattern</i>/, then match that input
+ string against the patterns between <b>if</b> and <b>endif</b>. The <b>if</b>..<b>endif</b>
+ can nest.
Note: do not prepend whitespace to patterns inside <b>if</b>..<b>endif</b>.
<b>if !/</b><i>pattern</i><b>/</b><i>flags</i>
- <b>endif</b> Match the input string against the patterns between <b>if</b> and
- <b>endif</b>, if and only if that same input string does <b>not</b> match <i>pat-</i>
- <i>tern</i>. The <b>if</b>..<b>endif</b> can nest.
+ <b>endif</b> If the input string does not match /<i>pattern</i>/, then match that
+ input string against the patterns between <b>if</b> and <b>endif</b>. The
+ <b>if</b>..<b>endif</b> can nest.
Note: do not prepend whitespace to patterns inside <b>if</b>..<b>endif</b>.
tion.
In the case of a non-zero exit status, a limited amount of command out-
- put is reported in an delivery status notification. When the output
- begins with a 4.X.X or 5.X.X enhanced status code, the status code
- takes precedence over the non-zero exit status (Postfix version 2.3 and
- later).
+ put is logged, and reported in a delivery status notification. When
+ the output begins with a 4.X.X or 5.X.X enhanced status code, the sta-
+ tus code takes precedence over the non-zero exit status (Postfix ver-
+ sion 2.3 and later).
- Problems and transactions are logged to <b>syslogd</b>(8). Corrupted message
+ After successful delivery (zero exit status) a limited amount of com-
+ mand output is logged, and reported in "success" delivery status noti-
+ fications (Postfix 2.12 and later). This command output is not exam-
+ ined for the presence of an enhanced status code.
+
+ Problems and transactions are logged to <b>syslogd</b>(8). Corrupted message
files are marked so that the queue manager can move them to the <b>corrupt</b>
queue for further inspection.
<b>SECURITY</b>
- This program needs a dual personality 1) to access the private Postfix
- queue and IPC mechanisms, and 2) to execute external commands as the
+ This program needs a dual personality 1) to access the private Postfix
+ queue and IPC mechanisms, and 2) to execute external commands as the
specified user. It is therefore security sensitive.
<b>CONFIGURATION PARAMETERS</b>
Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="pipe.8.html"><b>pipe</b>(8)</a> processes run
- for only a limited amount of time. Use the command "<b>postfix reload</b>" to
+ for only a limited amount of time. Use the command "<b>postfix reload</b>" to
speed up a change.
- The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
+ The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
more details including examples.
<b>RESOURCE AND RATE CONTROLS</b>
<b><a href="postconf.5.html#transport_destination_concurrency_limit"><i>transport</i>_destination_concurrency_limit</a> ($<a href="postconf.5.html#default_destination_concurrency_limit">default_destination_concur</a>-</b>
<b><a href="postconf.5.html#default_destination_concurrency_limit">rency_limit</a>)</b>
Limit the number of parallel deliveries to the same destination,
- for delivery via the named <i>transport</i>. The limit is enforced by
+ for delivery via the named <i>transport</i>. The limit is enforced by
the Postfix queue manager.
<b><a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a> ($<a href="postconf.5.html#default_destination_recipient_limit">default_destination_recipi</a>-</b>
<b><a href="postconf.5.html#default_destination_recipient_limit">ent_limit</a>)</b>
- Limit the number of recipients per message delivery, for deliv-
+ Limit the number of recipients per message delivery, for deliv-
ery via the named <i>transport</i>. The limit is enforced by the Post-
fix queue manager.
<b><a href="postconf.5.html#transport_time_limit"><i>transport</i>_time_limit</a> ($<a href="postconf.5.html#command_time_limit">command_time_limit</a>)</b>
- Limit the time for delivery to external command, for delivery
- via the named <i>transport</i>. The limit is enforced by the pipe
+ Limit the time for delivery to external command, for delivery
+ via the named <i>transport</i>. The limit is enforced by the pipe
delivery agent.
- Postfix 2.4 and later support a suffix that specifies the time
- unit: s (seconds), m (minutes), h (hours), d (days), w (weeks).
+ Postfix 2.4 and later support a suffix that specifies the time
+ unit: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is seconds.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to handle a
+ How much time a Postfix daemon process may take to handle a
request before it is terminated by a built-in watchdog timer.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- The maximal number of digits after the decimal point when log-
+ The maximal number of digits after the decimal point when log-
ging sub-second delay values.
<b><a href="postconf.5.html#export_environment">export_environment</a> (see 'postconf -d' output)</b>
- The list of environment variables that a Postfix process will
+ The list of environment variables that a Postfix process will
export to non-Postfix processes.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
- The time limit for sending or receiving information over an
+ The time limit for sending or receiving information over an
internal communication channel.
<b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
- The UNIX system account that owns the Postfix queue and most
+ The UNIX system account that owns the Postfix queue and most
Postfix daemon processes.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix daemon process
+ The maximum amount of time that an idle Postfix daemon process
waits for an incoming connection before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
- The set of characters that can separate a user name from its
- extension (example: user+foo), or a .forward file name from its
+ The set of characters that can separate a user name from its
+ extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo).
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- The mail system name that is prepended to the process name in
- syslog records, so that "smtpd" becomes, for example, "post-
+ The mail system name that is prepended to the process name in
+ syslog records, so that "smtpd" becomes, for example, "post-
fix/smtpd".
Available in Postfix version 2.12 and later:
<b><a href="postconf.5.html#pipe_delivery_status_filter">pipe_delivery_status_filter</a> ($<a href="postconf.5.html#default_delivery_status_filter">default_delivery_status_filter</a>)</b>
- Optional filter for the <a href="pipe.8.html"><b>pipe</b>(8)</a> delivery agent to change the
+ Optional filter for the <a href="pipe.8.html"><b>pipe</b>(8)</a> delivery agent to change the
delivery status code or explanatory text of successful or unsuc-
cessful deliveries.
PostgreSQL database client. This is described in
<a href="pgsql_table.5.html"><b>pgsql_table</b>(5)</a>.
+ <b>pipeline</b> (read-only)
+ A pipeline of lookup tables. Example: "<b><a href="DATABASE_README.html#types">pipe-</b>
+ <b>line</a>:</b><i>!type</i><b>_</b><i>1:name</i><b>_</b><i>1! ... !type</i><b>_</b><i>n:name</i><b>_</b><i>n</i>". Each "<a href="DATABASE_README.html#types">pipe-
+ line</a>:" query is given to the first table. Each lookup
+ result becomes the query for the next table in the pipe-
+ line, and the last table produces the final result. When
+ any table lookup produces no result, the pipeline pro-
+ duces no result. The ASCII character after "<a href="DATABASE_README.html#types">pipeline</a>:"
+ will be used as the separator between the lookup tables
+ that follow (do not use space, ",", ":" or non-ASCII).
+
<b>proxy</b> Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> client for shared access to Postfix
databases. The table name syntax is <i>type</i><b>:</b><i>name</i>.
+ <b>random</b> (read-only)
+ An in-memory table that performs random selection. Exam-
+ ple: "<b><a href="DATABASE_README.html#types">random</a>:</b><i>!result</i><b>_</b><i>1! ... !result</i><b>_</b><i>n</i>". Each table query
+ returns a random choice from the specified results. The
+ ASCII character after "<a href="DATABASE_README.html#types">random</a>:" will be used as the sepa-
+ rator between the results that follow (do not use space,
+ ",", ":" or non-ASCII).
+
<b>regexp</b> (read-only)
- A lookup table based on regular expressions. The file
+ A lookup table based on regular expressions. The file
format is described in <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a>.
<b>sdbm</b> An indexed file type based on hashing. Available on sys-
tems with support for SDBM databases.
<b>socketmap</b> (read-only)
- Sendmail-style socketmap client. The table name is
- <b>inet</b>:<i>host</i>:<i>port</i>:<i>name</i> for a TCP/IP server, or <b>unix</b>:<i>path-</i>
- <i>name</i>:<i>name</i> for a UNIX-domain server. This is described in
+ Sendmail-style socketmap client. The table name is
+ <b>inet</b>:<i>host</i>:<i>port</i>:<i>name</i> for a TCP/IP server, or <b>unix</b>:<i>path-</i>
+ <i>name</i>:<i>name</i> for a UNIX-domain server. This is described in
<a href="socketmap_table.5.html"><b>socketmap_table</b>(5)</a>.
<b>sqlite</b> (read-only)
SQLite database. This is described in <a href="sqlite_table.5.html"><b>sqlite_table</b>(5)</a>.
<b>static</b> (read-only)
- A table that always returns its name as lookup result.
+ A table that always returns its name as lookup result.
For example, <b><a href="DATABASE_README.html#types">static</a>:foobar</b> always returns the string <b>foo-</b>
<b>bar</b> as lookup result.
TCP/IP client. The protocol is described in <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
<b>texthash</b> (read-only)
- Produces similar results as <a href="DATABASE_README.html#types">hash</a>: files, except that you
- don't need to run the <a href="postmap.1.html"><b>postmap</b>(1)</a> command before you can
- use the file, and that it does not detect changes after
+ Produces similar results as <a href="DATABASE_README.html#types">hash</a>: files, except that you
+ don't need to run the <a href="postmap.1.html"><b>postmap</b>(1)</a> command before you can
+ use the file, and that it does not detect changes after
the file is read.
<b>unix</b> (read-only)
- A limited view of the UNIX authentication database. The
+ A limited view of the UNIX authentication database. The
following tables are implemented:
<b>unix:passwd.byname</b>
- The table is the UNIX password database. The key
- is a login name. The result is a password file
+ The table is the UNIX password database. The key
+ is a login name. The result is a password file
entry in <b>passwd</b>(5) format.
<b>unix:group.byname</b>
The table is the UNIX group database. The key is a
- group name. The result is a group file entry in
+ group name. The result is a group file entry in
<b>group</b>(5) format.
- Other table types may exist depending on how Postfix was built.
+ Other table types may exist depending on how Postfix was built.
- <b>-M</b> Show <a href="master.5.html"><b>master.cf</b></a> file contents instead of <a href="postconf.5.html"><b>main.cf</b></a> file contents.
+ <b>-M</b> Show <a href="master.5.html"><b>master.cf</b></a> file contents instead of <a href="postconf.5.html"><b>main.cf</b></a> file contents.
Specify <b>-Mf</b> to fold long lines for human readability.
Specify zero or more arguments, each with a <i>service-name</i> or <i>ser-</i>
- <i>vice-name/service-type</i> pair, where <i>service-name</i> is the first
- field of a <a href="master.5.html">master.cf</a> entry and <i>service-type</i> is one of (<b>inet</b>,
+ <i>vice-name/service-type</i> pair, where <i>service-name</i> is the first
+ field of a <a href="master.5.html">master.cf</a> entry and <i>service-type</i> is one of (<b>inet</b>,
<b>unix</b>, <b>fifo</b>, or <b>pass</b>).
- If <i>service-name</i> or <i>service-name/service-type</i> is specified, only
- the matching <a href="master.5.html">master.cf</a> entries will be output. For example,
- "<b>postconf -Mf smtp</b>" will output all services named "smtp", and
- "<b>postconf -Mf smtp/inet</b>" will output only the smtp service that
- listens on the network. Trailing service type fields that are
+ If <i>service-name</i> or <i>service-name/service-type</i> is specified, only
+ the matching <a href="master.5.html">master.cf</a> entries will be output. For example,
+ "<b>postconf -Mf smtp</b>" will output all services named "smtp", and
+ "<b>postconf -Mf smtp/inet</b>" will output only the smtp service that
+ listens on the network. Trailing service type fields that are
omitted will be handled as "*" wildcard fields.
This feature is available with Postfix 2.9 and later. The syntax
- was changed from "<i>name.type</i>" to "<i>name/type</i>", and "*" wildcard
+ was changed from "<i>name.type</i>" to "<i>name/type</i>", and "*" wildcard
support was added with Postfix 2.11.
<b>-n</b> Show only configuration parameters that have explicit <i>name=value</i>
- settings in <a href="postconf.5.html"><b>main.cf</b></a>. Specify <b>-nf</b> to fold long lines for human
+ settings in <a href="postconf.5.html"><b>main.cf</b></a>. Specify <b>-nf</b> to fold long lines for human
readability (Postfix 2.9 and later).
<b>-o</b> <i>name=value</i>
This feature is available with Postfix 2.11 and later.
- <b>-P</b> Show <a href="master.5.html"><b>master.cf</b></a> service parameter settings (by default all ser-
+ <b>-P</b> Show <a href="master.5.html"><b>master.cf</b></a> service parameter settings (by default all ser-
vices and all parameters). formatted as one "<i>ser-</i>
- <i>vice/type/parameter=value</i>" per line. Specify <b>-Pf</b> to fold long
+ <i>vice/type/parameter=value</i>" per line. Specify <b>-Pf</b> to fold long
lines.
- Specify one or more "<i>service/type/parameter</i>" instances on the
- <a href="postconf.1.html"><b>postconf</b>(1)</a> command line to limit the output to parameters of
- interest. Trailing parameter name or service type fields that
+ Specify one or more "<i>service/type/parameter</i>" instances on the
+ <a href="postconf.1.html"><b>postconf</b>(1)</a> command line to limit the output to parameters of
+ interest. Trailing parameter name or service type fields that
are omitted will be handled as "*" wildcard fields.
This feature is available with Postfix 2.11 and later.
<b>-t</b> [<i>template</i><b>_</b><i>file</i>]
- Display the templates for text that appears at the beginning of
- delivery status notification (DSN) messages, without expanding
+ Display the templates for text that appears at the beginning of
+ delivery status notification (DSN) messages, without expanding
$<b>name</b> expressions.
To override the built-in templates, specify a template file name
- at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line, or specify a file
+ at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line, or specify a file
name in <a href="postconf.5.html"><b>main.cf</b></a> with the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter.
- To force selection of the built-in templates, specify an empty
- template file name on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line (in shell
+ To force selection of the built-in templates, specify an empty
+ template file name on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line (in shell
language: "").
This feature is available with Postfix 2.3 and later.
- <b>-v</b> Enable verbose logging for debugging purposes. Multiple <b>-v</b>
+ <b>-v</b> Enable verbose logging for debugging purposes. Multiple <b>-v</b>
options make the software increasingly verbose.
- <b>-x</b> Expand <i>$name</i> in <a href="postconf.5.html"><b>main.cf</b></a> or <a href="master.5.html"><b>master.cf</b></a> parameter values. The
+ <b>-x</b> Expand <i>$name</i> in <a href="postconf.5.html"><b>main.cf</b></a> or <a href="master.5.html"><b>master.cf</b></a> parameter values. The
expansion is recursive.
This feature is available with Postfix 2.10 and later.
- <b>-X</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and remove the parameters
+ <b>-X</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and remove the parameters
named on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line. Specify a list of param-
eter names, not "<i>name=value</i>" pairs.
- With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
- or more service entries as specified with "<i>service/type</i>" on the
+ With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
+ or more service entries as specified with "<i>service/type</i>" on the
<a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
- With <b>-P</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
+ With <b>-P</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
or more service parameter settings (-o parameter=value settings)
as specied with "<i>service/type/parameter</i>" on the <a href="postconf.1.html"><b>postconf</b>(1)</a> com-
mand line.
into place. Specify quotes to protect special characters on the
<a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
- There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
+ There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
tion.
- This feature is available with Postfix 2.10 and later. Support
+ This feature is available with Postfix 2.10 and later. Support
for -M and -P was added with Postfix 2.11.
<b>-#</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and comment out the parame-
eters revert to their default values. Specify a list of parame-
ter names, not "<i>name=value</i>" pairs.
- With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and comment out
- one or more service entries as specified with "<i>service/type</i>" on
+ With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and comment out
+ one or more service entries as specified with "<i>service/type</i>" on
the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
In all cases the file is copied to a temporary file then renamed
into place. Specify quotes to protect special characters on the
<a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
- There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
+ There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
tion.
- This feature is available with Postfix 2.6 and later. Support
+ This feature is available with Postfix 2.6 and later. Support
for -M was added with Postfix 2.11.
<b>DIAGNOSTICS</b>
Directory with Postfix configuration files.
<b>CONFIGURATION PARAMETERS</b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
gram.
- The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
+ The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
more details including examples.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
- Pathname of a configuration file with bounce message templates.
+ Pathname of a configuration file with bounce message templates.
<b>FILES</b>
/etc/postfix/<a href="postconf.5.html">main.cf</a>, Postfix configuration parameters
<b>if /</b><i>pattern</i><b>/</b><i>flags</i>
- <b>endif</b> Match the input string against the patterns between <b>if</b> and
- <b>endif</b>, if and only if that same input string also matches <i>pat-</i>
- <i>tern</i>. The <b>if</b>..<b>endif</b> can nest.
+ <b>endif</b> If the input string matches /<i>pattern</i>/, then match that input
+ string against the patterns between <b>if</b> and <b>endif</b>. The <b>if</b>..<b>endif</b>
+ can nest.
Note: do not prepend whitespace to patterns inside <b>if</b>..<b>endif</b>.
<b>if !/</b><i>pattern</i><b>/</b><i>flags</i>
- <b>endif</b> Match the input string against the patterns between <b>if</b> and
- <b>endif</b>, if and only if that same input string does <b>not</b> match <i>pat-</i>
- <i>tern</i>. The <b>if</b>..<b>endif</b> can nest.
+ <b>endif</b> If the input string does not match /<i>pattern</i>/, then match that
+ input string against the patterns between <b>if</b> and <b>endif</b>. The
+ <b>if</b>..<b>endif</b> can nest.
Note: do not prepend whitespace to patterns inside <b>if</b>..<b>endif</b>.
# NAME
# makedefs 1
# SUMMARY
-# makefile configuration utility
+# Postfix makefile configuration utility
# SYNOPSIS
# \fBmake makefiles \fIname=value...\fR
# DESCRIPTION
# The \fBmakedefs\fR command identifies the compilation
-# environment, and emits macro definitions on the standard output
-# stream that can be prepended to template Makefiles.
+# environment, and emits macro definitions on the standard
+# output stream that can be prepended to template Makefiles.
+# These macros implement an internal interface and are subject
+# to change without notice.
#
# Default settings can be overruled by specifying them as
-# environment variables. Use quotes if variables contain
-# whitespace or shell meta characters.
+# environment variables (or as name=value pairs on the "make"
+# command line). Use quotes if variables contain whitespace
+# or shell meta characters.
# .IP \fBAUXLIBS=\fIobject_library...\fR
# Specifies one or more non-default object libraries. Postfix
# 2,12 and later specify some of their database library
# .IP \fBshared=no\fR
# Enable (disable) Postfix builds with shared libraries
# typically named $shlib_directory/libpostfix-*.so.*.
+#
+# This feature was introduced with Postfix 2.12.
# .IP \fBdynamicmaps=yes\fR
# .IP \fBdynamicmaps=no\fR
# Enable (disable) Postfix builds with the configuration file
-# $plugin_directory/dynamicmaps.cf for dynamically-loadable
+# $plugin_directory/dynamicmaps.cf and dynamically-loadable
# database plugins typically named postfix-*.so.*. The setting
# "dynamicmaps=yes" implicitly enables Postfix shared libraries.
+#
+# This feature was introduced with Postfix 2.12.
# .IP \fIinstallation_parameter\fB=\fIvalue\fR...
# Override the compiled-in default value of the specified
# installation parameter(s). The following parameters are
#
# See the postconf(5) manpage for a description of these
# parameters.
+#
+# This feature was introduced with Postfix 2.12.
# .IP \fBSHLIB_VERSION=\fIversion\fR
# Specifies a non-default shared-library version for Postfix
# libraries and database plugins. By default, the version
# equals the default value for the $mail_version parameter.
+#
+# This feature was introduced with Postfix 2.12.
# .IP \fBWARN=\fIwarning_flags\fR
# Specifies non-default gcc compiler warning options for use when
# "make" is invoked in a source subdirectory only.
{ for (n = 1; n <= NF; n++)
if ($n ~ /^-dhas_/)
if (seen[name = substr($n, 7)]++ == 0)
- names = name " " names }
- END { print names }
+ printf(" %s", name) }
'`
# Propagate AUXLIBS_FOO or merge them into global AUXLIBS (i.e. SYSLIBS).
.IP "\fBpgsql\fR (read-only)"
PostgreSQL database client. This is described in
\fBpgsql_table\fR(5).
+.IP "\fBpipeline\fR (read-only)"
+A pipeline of lookup tables. Example:
+"\fBpipeline:\fI!type_1:name_1! ... !type_n:name_n\fR".
+Each "pipeline:" query is given to the first table. Each
+lookup result becomes the query for the next table in the
+pipeline, and the last table produces the final result.
+When any table lookup produces no result, the pipeline
+produces no result. The ASCII character after "pipeline:"
+will be used as the separator between the lookup tables
+that follow (do not use space, ",", ":" or non-ASCII).
.IP "\fBproxy\fR"
Postfix \fBproxymap\fR(8) client for shared access to Postfix
databases. The table name syntax is \fItype\fB:\fIname\fR.
+.IP "\fBrandom\fR (read-only)"
+An in-memory table that performs random selection. Example:
+"\fBrandom:\fI!result_1! ... !result_n\fR". Each table query
+returns a random choice from the specified results. The
+ASCII character after "random:" will be used as the separator
+between the results that follow (do not use space, ",", ":"
+or non-ASCII).
.IP "\fBregexp\fR (read-only)"
A lookup table based on regular expressions. The file format
is described in \fBregexp_table\fR(5).
all recipients of the message.
.sp
This feature is available in Postfix 2.1 and later.
+.IP "\fBINFO \fIoptional text...\fR
+Log an informational record with the optional text, together
+with client information and if available, with helo, sender,
+recipient and protocol information.
+.sp
+This feature is available in Postfix 2.12 and later.
.IP "\fBWARN \fIoptional text...\fR
Log a warning with the optional text, together with client information
and if available, with helo, sender, recipient and protocol information.
execute the corresponding \fIaction\fR.
.IP "\fBif /\fIpattern\fB/\fIflags\fR"
.IP "\fBendif\fR"
-Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if the same input string also
-matches /\fIpattern\fR/. The \fBif\fR..\fBendif\fR can nest.
+If the input string matches /\fIpattern\fR/, then match that
+input string against the patterns between \fBif\fR and
+\fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
.sp
Note: do not prepend whitespace to patterns inside
\fBif\fR..\fBendif\fR.
.IP "\fBif !/\fIpattern\fB/\fIflags\fR"
.IP "\fBendif\fR"
-Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if the same input string does
-\fBnot\fR match /\fIpattern\fR/. The \fBif\fR..\fBendif\fR
-can nest.
+If the input string does not match /\fIpattern\fR/, then
+match that input string against the patterns between \fBif\fR
+and \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
.IP "blank lines and comments"
Empty lines and whitespace-only lines are ignored, as
are lines whose first non-whitespace character is a `#'.
the corresponding \fIresult\fR value.
.IP "\fBif /\fIpattern\fB/\fIflags\fR"
.IP "\fBendif\fR"
-Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if that same input string also matches
-\fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+If the input string matches /\fIpattern\fR/, then match that
+input string against the patterns between \fBif\fR and
+\fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
.sp
Note: do not prepend whitespace to patterns inside
\fBif\fR..\fBendif\fR.
This feature is available in Postfix 2.1 and later.
.IP "\fBif !/\fIpattern\fB/\fIflags\fR"
.IP "\fBendif\fR"
-Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if that same input string does \fBnot\fR
-match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+If the input string does not match /\fIpattern\fR/, then
+match that input string against the patterns between \fBif\fR
+and \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
.sp
Note: do not prepend whitespace to patterns inside
\fBif\fR..\fBendif\fR.
use the corresponding \fIresult\fR value.
.IP "\fBif /\fIpattern\fB/\fIflags\fR"
.IP "\fBendif\fR"
-Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if that same input string also
-matches \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+If the input string matches /\fIpattern\fR/, then match that
+input string against the patterns between \fBif\fR and
+\fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
.sp
Note: do not prepend whitespace to patterns inside
\fBif\fR..\fBendif\fR.
This feature is available in Postfix 2.1 and later.
.IP "\fBif !/\fIpattern\fB/\fIflags\fR"
.IP "\fBendif\fR"
-Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if that same input string does
-\fBnot\fR match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+If the input string does not match /\fIpattern\fR/, then
+match that input string against the patterns between \fBif\fR
+and \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
.sp
Note: do not prepend whitespace to patterns inside
\fBif\fR..\fBendif\fR.
Exit status 0 means normal successful completion.
In the case of a non-zero exit status, a limited amount of
-command output is reported in an delivery status notification.
-When the output begins with a 4.X.X or 5.X.X enhanced status
-code, the status code takes precedence over the non-zero
-exit status (Postfix version 2.3 and later).
+command output is logged, and reported in a delivery status
+notification. When the output begins with a 4.X.X or 5.X.X
+enhanced status code, the status code takes precedence over
+the non-zero exit status (Postfix version 2.3 and later).
+
+After successful delivery (zero exit status) a limited
+amount of command output is logged, and reported in "success"
+delivery status notifications (Postfix 2.12 and later).
+This command output is not examined for the presence of an
+enhanced status code.
Problems and transactions are logged to \fBsyslogd\fR(8).
Corrupted message files are marked so that the queue manager
s/\b(nisplus):/<a href="nisplus_table.5.html">$1<\/a>:/g;
s/\b(pcre):/<a href="pcre_table.5.html">$1<\/a>:/g;
s/\b(pgsql):/<a href="pgsql_table.5.html">$1<\/a>:/g;
+ s;\b(pipe[-</bB>]*\n*[ <bB>]*line):;<a href="DATABASE_README.html#types">$1<\/a>:;g;
s/\b(proxy):/<a href="proxymap.8.html">$1<\/a>:/g;
+ s/\b(random):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
s/\b(regexp):/<a href="regexp_table.5.html">$1<\/a>:/g;
s/\b(sdbm):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
s/\b(socketmap):/<a href="socketmap_table.html">$1<\/a>:/g;
--- /dev/null
+#!/bin/sh
+
+# Run a program with the new libraries, not the installed ones.
+
+export LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/lib
+
+"$@"
name as used in "pcre:table" is the name of the regular expression
file. </dd>
+<dt> <b>pipeline</b> (read-only) </dt>
+
+<dd> A pipeline of lookup tables. Example:
+"<b>pipeline:</b><i>!type_1:name_1! ... !type_n:name_n</i>". Each
+"pipeline:" query is given to the first table. Each lookup result
+becomes the query for the next table in the pipeline, and the last
+table produces the final result. When any table lookup produces
+no result, the pipeline produces no result. The ASCII character
+after "pipeline:" will be used as the separator between the lookup
+tables that follow (do not use space, ",", ":" or non-ASCII). </dd>
+
<dt> <b>pgsql</b> (read-only) </dt>
<dd> PostgreSQL database client. Configuration details are given
databases. The lookup table name syntax is "proxy:type:table".
</dd>
+<dt> <b>random</b> (read-only) </dt>
+
+<dd> An in-memory table that performs random selection. Example:
+"<b>random:</b><i>!result_1! ... !result_n</i>". Each table query
+returns a random choice from the specified results. The ASCII
+character after "random:" will be used as the separator between the
+results that follow (do not use space, ",", ":" or non-ASCII).
+</dd>
+
<dt> <b>regexp</b> (read-only) </dt>
<dd> A lookup table based on regular expressions. The file format
# all recipients of the message.
# .sp
# This feature is available in Postfix 2.1 and later.
+# .IP "\fBINFO \fIoptional text...\fR
+# Log an informational record with the optional text, together
+# with client information and if available, with helo, sender,
+# recipient and protocol information.
+# .sp
+# This feature is available in Postfix 2.12 and later.
# .IP "\fBWARN \fIoptional text...\fR
# Log a warning with the optional text, together with client information
# and if available, with helo, sender, recipient and protocol information.
# execute the corresponding \fIaction\fR.
# .IP "\fBif /\fIpattern\fB/\fIflags\fR"
# .IP "\fBendif\fR"
-# Match the input string against the patterns between \fBif\fR
-# and \fBendif\fR, if and only if the same input string also
-# matches /\fIpattern\fR/. The \fBif\fR..\fBendif\fR can nest.
+# If the input string matches /\fIpattern\fR/, then match that
+# input string against the patterns between \fBif\fR and
+# \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
# .sp
# Note: do not prepend whitespace to patterns inside
# \fBif\fR..\fBendif\fR.
# .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
# .IP "\fBendif\fR"
-# Match the input string against the patterns between \fBif\fR
-# and \fBendif\fR, if and only if the same input string does
-# \fBnot\fR match /\fIpattern\fR/. The \fBif\fR..\fBendif\fR
-# can nest.
+# If the input string does not match /\fIpattern\fR/, then
+# match that input string against the patterns between \fBif\fR
+# and \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
# .IP "blank lines and comments"
# Empty lines and whitespace-only lines are ignored, as
# are lines whose first non-whitespace character is a `#'.
# the corresponding \fIresult\fR value.
# .IP "\fBif /\fIpattern\fB/\fIflags\fR"
# .IP "\fBendif\fR"
-# Match the input string against the patterns between \fBif\fR
-# and \fBendif\fR, if and only if that same input string also matches
-# \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+# If the input string matches /\fIpattern\fR/, then match that
+# input string against the patterns between \fBif\fR and
+# \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
# .sp
# Note: do not prepend whitespace to patterns inside
# \fBif\fR..\fBendif\fR.
# This feature is available in Postfix 2.1 and later.
# .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
# .IP "\fBendif\fR"
-# Match the input string against the patterns between \fBif\fR
-# and \fBendif\fR, if and only if that same input string does \fBnot\fR
-# match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+# If the input string does not match /\fIpattern\fR/, then
+# match that input string against the patterns between \fBif\fR
+# and \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
# .sp
# Note: do not prepend whitespace to patterns inside
# \fBif\fR..\fBendif\fR.
# use the corresponding \fIresult\fR value.
# .IP "\fBif /\fIpattern\fB/\fIflags\fR"
# .IP "\fBendif\fR"
-# Match the input string against the patterns between \fBif\fR
-# and \fBendif\fR, if and only if that same input string also
-# matches \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+# If the input string matches /\fIpattern\fR/, then match that
+# input string against the patterns between \fBif\fR and
+# \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
# .sp
# Note: do not prepend whitespace to patterns inside
# \fBif\fR..\fBendif\fR.
# This feature is available in Postfix 2.1 and later.
# .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
# .IP "\fBendif\fR"
-# Match the input string against the patterns between \fBif\fR
-# and \fBendif\fR, if and only if that same input string does
-# \fBnot\fR match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
+# If the input string does not match /\fIpattern\fR/, then
+# match that input string against the patterns between \fBif\fR
+# and \fBendif\fR. The \fBif\fR..\fBendif\fR can nest.
# .sp
# Note: do not prepend whitespace to patterns inside
# \fBif\fR..\fBendif\fR.
/* dymap_read_conf - read dynamicmaps.cf-like file */
-static void dymap_read_conf(const char *path, const char *base)
+static void dymap_read_conf(const char *path, const char *path_base)
{
VSTREAM *fp;
VSTRING *buf;
msg_fatal("%s, line %d: unsupported syntax \"%s\"",
path, linenum, argv->argv[0]);
if (argv->argv[1][0] != '/') {
- cp = concatenate(base, "/", argv->argv[1], (char *) 0);
+ cp = concatenate(path_base, "/", argv->argv[1], (char *) 0);
argv_replace_one(argv, 1, cp);
myfree(cp);
}
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20140531"
+#define MAIL_RELEASE_DATE "20140618"
#define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT
/* An open message queue file, positioned at the start of the actual
/* message content.
/* .IP why
-/* Delivery status information.
+/* Delivery status information. The reason attribute may contain
+/* a limited portion of command output, among other free text.
/* .IP key
/* Specifies what value will follow. pipe_command() takes a list
/* of (key, value) arguments, terminated by PIPE_CMD_END. The
vstring_sprintf_append(why->reason, ": \"%s\"", args.command);
return (PIPE_STAT_BOUNCE);
} else {
+ vstring_strcpy(why->reason, log_buf);
return (PIPE_STAT_OK);
}
}
/* Exit status 0 means normal successful completion.
/*
/* In the case of a non-zero exit status, a limited amount of
-/* command output is reported in an delivery status notification.
-/* When the output begins with a 4.X.X or 5.X.X enhanced status
-/* code, the status code takes precedence over the non-zero
-/* exit status (Postfix version 2.3 and later).
+/* command output is logged, and reported in a delivery status
+/* notification. When the output begins with a 4.X.X or 5.X.X
+/* enhanced status code, the status code takes precedence over
+/* the non-zero exit status (Postfix version 2.3 and later).
+/*
+/* After successful delivery (zero exit status) a limited
+/* amount of command output is logged, and reported in "success"
+/* delivery status notifications (Postfix 2.12 and later).
+/* This command output is not examined for the presence of an
+/* enhanced status code.
/*
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* Corrupted message files are marked so that the queue manager
int status;
int result = 0;
int n;
+ char *saved_text;
/*
* Depending on the result, bounce or defer the message, and mark the
*/
switch (command_status) {
case PIPE_STAT_OK:
+ /* Save the command output before dsb_update() clobbers it. */
+ vstring_truncate(why->reason, trimblanks(STR(why->reason),
+ VSTRING_LEN(why->reason)) - STR(why->reason));
+ if (VSTRING_LEN(why->reason) > 0) {
+ VSTRING_TERMINATE(why->reason);
+ saved_text =
+ vstring_export(vstring_sprintf(
+ vstring_alloc(VSTRING_LEN(why->reason)),
+ " (%.100s)", STR(why->reason)));
+ } else
+ saved_text = mystrdup(""); /* uses shared R/O storage */
dsb_update(why, "2.0.0", (attr->flags & PIPE_OPT_FINAL_DELIVERY) ?
"delivered" : "relayed", DSB_SKIP_RMTA, DSB_SKIP_REPLY,
- "delivered via %s service", service);
+ "delivered via %s service%s", service, saved_text);
+ myfree(saved_text);
(void) DSN_FROM_DSN_BUF(why);
for (n = 0; n < request->rcpt_list.len; n++) {
rcpt = request->rcpt_list.info + n;
/* .IP "\fBpgsql\fR (read-only)"
/* PostgreSQL database client. This is described in
/* \fBpgsql_table\fR(5).
+/* .IP "\fBpipeline\fR (read-only)"
+/* A pipeline of lookup tables. Example:
+/* "\fBpipeline:\fI!type_1:name_1! ... !type_n:name_n\fR".
+/* Each "pipeline:" query is given to the first table. Each
+/* lookup result becomes the query for the next table in the
+/* pipeline, and the last table produces the final result.
+/* When any table lookup produces no result, the pipeline
+/* produces no result. The ASCII character after "pipeline:"
+/* will be used as the separator between the lookup tables
+/* that follow (do not use space, ",", ":" or non-ASCII).
/* .IP "\fBproxy\fR"
/* Postfix \fBproxymap\fR(8) client for shared access to Postfix
/* databases. The table name syntax is \fItype\fB:\fIname\fR.
+/* .IP "\fBrandom\fR (read-only)"
+/* An in-memory table that performs random selection. Example:
+/* "\fBrandom:\fI!result_1! ... !result_n\fR". Each table query
+/* returns a random choice from the specified results. The
+/* ASCII character after "random:" will be used as the separator
+/* between the results that follow (do not use space, ",", ":"
+/* or non-ASCII).
/* .IP "\fBregexp\fR (read-only)"
/* A lookup table based on regular expressions. The file format
/* is described in \fBregexp_table\fR(5).
vstream_longjmp(state->client, SMTP_ERR_QUIET);
}
+ /*
+ * INFO. Text is optional.
+ */
+ if (STREQUAL(value, "INFO", cmd_len)) {
+ log_whatsup(state, "info", cmd_text);
+ return (SMTPD_CHECK_DUNNO);
+ }
+
/*
* WARN. Text is optional.
*/
*/
static const char server_session_id_context[] = "Postfix/TLS";
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+#define GET_SID(s, v, lptr) ((v) = SSL_SESSION_get_id((s), (lptr)))
+
+#else /* Older OpenSSL releases */
+#define GET_SID(s, v, lptr) \
+ do { (v) = (s)->session_id; *(lptr) = (s)->session_id_length; } while (0)
+
+#endif /* OPENSSL_VERSION_NUMBER */
+
/* get_server_session_cb - callback to retrieve session from server cache */
static SSL_SESSION *get_server_session_cb(SSL *ssl, unsigned char *session_id,
{
VSTRING *cache_id;
SSL_SESSION *session = SSL_get_session(TLScontext->con);
+ const unsigned char *sid;
+ unsigned int sid_length;
SSL_CTX_remove_session(ctx, session);
if (TLScontext->cache_type == 0)
return;
- GEN_CACHE_ID(cache_id, session->session_id, session->session_id_length,
- TLScontext->serverid);
+ GET_SID(session, sid, &sid_length);
+ GEN_CACHE_ID(cache_id, sid, sid_length, TLScontext->serverid);
if (TLScontext->log_mask & TLS_LOG_CACHE)
msg_info("%s: remove session %s from %s cache", TLScontext->namaddr,
VSTRING *cache_id;
TLS_SESS_STATE *TLScontext;
VSTRING *session_data;
+ const unsigned char *sid;
+ unsigned int sid_length;
if ((TLScontext = SSL_get_ex_data(ssl, TLScontext_index)) == 0)
msg_panic("%s: null TLScontext in new session callback", myname);
- GEN_CACHE_ID(cache_id, session->session_id, session->session_id_length,
- TLScontext->serverid);
+ GET_SID(session, sid, &sid_length);
+ GEN_CACHE_ID(cache_id, sid, sid_length, TLScontext->serverid);
if (TLScontext->log_mask & TLS_LOG_CACHE)
msg_info("%s: save session %s to %s cache", TLScontext->namaddr,
ip_match.c nbbio.c base32_code.c dict_test.c \
dict_fail.c msg_rate_delay.c dict_surrogate.c warn_stat.c \
dict_sockmap.c line_number.c recv_pass_attr.c pass_accept.c \
- poll_fd.c timecmp.c slmdb.c
+ poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
ip_match.o nbbio.o base32_code.o dict_test.o \
dict_fail.o msg_rate_delay.o dict_surrogate.o warn_stat.o \
dict_sockmap.o line_number.o recv_pass_attr.o pass_accept.o \
- poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ)
+ poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
edit_file.h dict_cache.h dict_thash.h ip_match.h nbbio.h base32_code.h \
dict_fail.h warn_stat.h dict_sockmap.h line_number.h timecmp.h \
- slmdb.h compat_va_copy.h
+ slmdb.h compat_va_copy.h dict_pipe.h dict_random.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
dict_open.o: dict_nisplus.h
dict_open.o: dict_open.c
dict_open.o: dict_pcre.h
+dict_open.o: dict_random.h
dict_open.o: dict_regexp.h
dict_open.o: dict_sdbm.h
dict_open.o: dict_sockmap.h
+dict_open.o: dict_pipe.h
dict_open.o: dict_static.h
dict_open.o: dict_tcp.h
dict_open.o: dict_thash.h
dict_pcre.o: vstream.h
dict_pcre.o: vstring.h
dict_pcre.o: warn_stat.h
+dict_random.o: argv.h
+dict_random.o: dict.h
+dict_random.o: dict_random.c
+dict_random.o: dict_random.h
+dict_random.o: msg.h
+dict_random.o: myflock.h
+dict_random.o: mymalloc.h
+dict_random.o: myrand.h
+dict_random.o: sys_defs.h
+dict_random.o: vbuf.h
+dict_random.o: vstream.h
+dict_random.o: vstring.h
dict_regexp.o: argv.h
dict_regexp.o: dict.h
dict_regexp.o: dict_regexp.c
dict_sockmap.o: vbuf.h
dict_sockmap.o: vstream.h
dict_sockmap.o: vstring.h
+dict_pipe.o: argv.h
+dict_pipe.o: dict.h
+dict_pipe.o: dict_pipe.c
+dict_pipe.o: dict_pipe.h
+dict_pipe.o: htable.h
+dict_pipe.o: msg.h
+dict_pipe.o: myflock.h
+dict_pipe.o: mymalloc.h
+dict_pipe.o: stringops.h
+dict_pipe.o: sys_defs.h
+dict_pipe.o: vbuf.h
+dict_pipe.o: vstream.h
+dict_pipe.o: vstring.h
dict_static.o: argv.h
dict_static.o: dict.h
dict_static.o: dict_static.c
dict_tcp.o: vstring_vstream.h
dict_test.o: argv.h
dict_test.o: dict.h
+dict_test.o: dict_lmdb.h
dict_test.o: dict_test.c
dict_test.o: msg.h
dict_test.o: msg_vstream.h
load_file.o: vstream.h
load_file.o: warn_stat.h
load_lib.o: load_lib.c
-load_lib.o: load_lib.h
-load_lib.o: msg.h
load_lib.o: sys_defs.h
lowercase.o: lowercase.c
lowercase.o: stringops.h
#define DICT_OWNER_TRUSTED (!1) /* ex: root-owned config file */
#define DICT_OWNER_UNTRUSTED (!0) /* ex: non-root config file */
+#define DICT_OWNER_AGGREGATE(dst, src) do { \
+ if ((src).status == DICT_OWNER_UNKNOWN) { \
+ (dst).status = (src).status; \
+ (dst).uid = ~0; \
+ } else if ((src).status == DICT_OWNER_UNTRUSTED) { \
+ (dst).status = (src).status; \
+ (dst).uid = ~0; \
+ } \
+ } while (0)
+
/*
* Generic dictionary interface - in reality, a dictionary extends this
* structure with private members to maintain internal state.
#include <dict_thash.h>
#include <dict_sockmap.h>
#include <dict_fail.h>
+#include <dict_pipe.h>
+#include <dict_random.h>
#include <stringops.h>
#include <split_at.h>
#include <htable.h>
DICT_TYPE_THASH, dict_thash_open,
DICT_TYPE_SOCKMAP, dict_sockmap_open,
DICT_TYPE_FAIL, dict_fail_open,
+ DICT_TYPE_PIPE, dict_pipe_open,
+ DICT_TYPE_RANDOM, dict_random_open,
#ifndef USE_DYNAMIC_MAPS
#ifdef HAS_PCRE
DICT_TYPE_PCRE, dict_pcre_open,
--- /dev/null
+/*++
+/* NAME
+/* dict_pipe 3
+/* SUMMARY
+/* dictionary manager interface for pipelined tables
+/* SYNOPSIS
+/* #include <dict_pipe.h>
+/*
+/* DICT *dict_pipe_open(name, open_flags, dict_flags)
+/* const char *name;
+/* int open_flags;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_pipe_open() opens a pipeline of one or more tables.
+/* Example: "\fBpipeline:\fI!type_1:name_1! ... !type_n:name_n\fR".
+/*
+/* Each "pipeline:" query is given to the first table. Each
+/* lookup result becomes the query for the next table in the
+/* pipeline, and the last table produces the final result.
+/* When any table lookup produces no result, the pipeline
+/* produces no result.
+/*
+/* The ASCII character after "pipeline:" will be used as the
+/* separator between the lookup tables that follow (do not use
+/* space, ",", ":" or non-ASCII).
+/*
+/* The open_flags and dict_flags arguments are passed on to
+/* the underlying dictionaries.
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include "mymalloc.h"
+#include "htable.h"
+#include "dict.h"
+#include "dict_pipe.h"
+#include "stringops.h"
+#include "vstring.h"
+
+/* Application-specific. */
+
+typedef struct {
+ DICT dict; /* generic members */
+ ARGV *map_pipe; /* pipelined tables */
+ VSTRING *qr_buf; /* query/reply buffer */
+} DICT_PIPE;
+
+#define STR(x) vstring_str(x)
+
+/* dict_pipe_lookup - search pipelined tables */
+
+static const char *dict_pipe_lookup(DICT *dict, const char *query)
+{
+ const char myname[] = "dict_pipe_lookup";
+ DICT_PIPE *dict_pipe = (DICT_PIPE *) dict;
+ DICT *map;
+ char **cpp;
+ char *dict_type_name;
+ const char *result = 0;
+
+ vstring_strcpy(dict_pipe->qr_buf, query);
+ for (cpp = dict_pipe->map_pipe->argv; (dict_type_name = *cpp) != 0; cpp++) {
+ if ((map = dict_handle(dict_type_name)) == 0)
+ msg_panic("%s: dictionary \"%s\" not found", myname, dict_type_name);
+ if ((result = dict_get(map, STR(dict_pipe->qr_buf))) == 0)
+ DICT_ERR_VAL_RETURN(dict, map->error, result);
+ vstring_strcpy(dict_pipe->qr_buf, result);
+ }
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, STR(dict_pipe->qr_buf));
+}
+
+/* dict_pipe_close - disassociate from pipelined tables */
+
+static void dict_pipe_close(DICT *dict)
+{
+ DICT_PIPE *dict_pipe = (DICT_PIPE *) dict;
+ char **cpp;
+ char *dict_type_name;
+
+ for (cpp = dict_pipe->map_pipe->argv; (dict_type_name = *cpp) != 0; cpp++)
+ dict_unregister(dict_type_name);
+ argv_free(dict_pipe->map_pipe);
+ vstring_free(dict_pipe->qr_buf);
+ dict_free(dict);
+}
+
+/* dict_pipe_open - open pipelined tables */
+
+DICT *dict_pipe_open(const char *name, int open_flags, int dict_flags)
+{
+ const char myname[] = "dict_pipe_open";
+ DICT_PIPE *dict_pipe;
+ char *saved_name = 0;
+ char *dict_type_name;
+ ARGV *argv = 0;
+ char **cpp;
+ DICT *dict;
+ int match_flags = 0;
+ struct DICT_OWNER aggr_owner;
+ char delim[2];
+
+ /*
+ * Clarity first. Let the optimizer worry about redundant code.
+ */
+#define DICT_PIPE_RETURN(x) do { \
+ if (saved_name != 0) \
+ myfree(saved_name); \
+ if (argv != 0) \
+ argv_free(argv); \
+ return (x); \
+ } while (0)
+
+ /*
+ * Sanity checks.
+ */
+ if (open_flags != O_RDONLY)
+ DICT_PIPE_RETURN(dict_surrogate(DICT_TYPE_PIPE, name,
+ open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_PIPE, name));
+ if (name[0] == ':')
+ DICT_PIPE_RETURN(dict_surrogate(DICT_TYPE_PIPE, name,
+ open_flags, dict_flags,
+ "invalid list delimiter \"%c\" in \"%s:%s\"",
+ name[0], DICT_TYPE_PIPE, name));
+
+ /*
+ * Split the table name on the user-specified delimiter.
+ */
+ delim[0] = name[0]; /* XXX ASCII delimiter */
+ delim[1] = 0;
+ saved_name = mystrdup(name + 1); /* XXX ASCII delimiter */
+ if (*saved_name == 0)
+ DICT_PIPE_RETURN(dict_surrogate(DICT_TYPE_PIPE, name,
+ open_flags, dict_flags,
+ "bad syntax: \"%s:%s\"; need \"%s:%stype:name%s...\"",
+ DICT_TYPE_PIPE, name,
+ DICT_TYPE_PIPE, delim, delim));
+
+ /*
+ * The least-trusted table in the pipeline determines the over-all trust
+ * level. The first table determines the pattern-matching flags.
+ */
+ aggr_owner.status = DICT_OWNER_TRUSTED;
+ aggr_owner.uid = 0;
+ argv = argv_split(saved_name, delim);
+ for (cpp = argv->argv; (dict_type_name = *cpp) != 0; cpp++) {
+ if (msg_verbose)
+ msg_info("%s: %s", myname, dict_type_name);
+ if (strchr(dict_type_name, ':') == 0)
+ DICT_PIPE_RETURN(dict_surrogate(DICT_TYPE_PIPE, name,
+ open_flags, dict_flags,
+ "bad syntax: \"%s\" in \"%s:%s\"; "
+ "need \"type:name\"",
+ dict_type_name, DICT_TYPE_PIPE,
+ name));
+ if ((dict = dict_handle(dict_type_name)) == 0)
+ dict = dict_open(dict_type_name, open_flags, dict_flags);
+ dict_register(dict_type_name, dict);
+ DICT_OWNER_AGGREGATE(aggr_owner, dict->owner);
+ if (cpp == argv->argv)
+ match_flags = dict->flags & (DICT_FLAG_FIXED | DICT_FLAG_PATTERN);
+ }
+
+ /*
+ * Bundle up the result.
+ */
+ dict_pipe =
+ (DICT_PIPE *) dict_alloc(DICT_TYPE_PIPE, name, sizeof(*dict_pipe));
+ dict_pipe->dict.lookup = dict_pipe_lookup;
+ dict_pipe->dict.close = dict_pipe_close;
+ dict_pipe->dict.flags = dict_flags | match_flags;
+ dict_pipe->dict.owner = aggr_owner;
+ dict_pipe->qr_buf = vstring_alloc(100);
+ dict_pipe->map_pipe = argv;
+ argv = 0;
+ DICT_PIPE_RETURN(DICT_DEBUG (&dict_pipe->dict));
+}
--- /dev/null
+#ifndef _DICT_PIPE_H_INCLUDED_
+#define _DICT_PIPE_H_INCLUDED_
+
+/*++
+/* NAME
+/* dict_pipe 3h
+/* SUMMARY
+/* dictionary manager interface for pipelined tables
+/* SYNOPSIS
+/* #include <dict_pipe.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+
+ /*
+ * External interface.
+ */
+#define DICT_TYPE_PIPE "pipeline"
+
+extern DICT *dict_pipe_open(const char *, int, int);
+
+/* 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
--- /dev/null
+/*++
+/* NAME
+/* dict_random 3
+/* SUMMARY
+/* dictionary manager interface for randomized tables
+/* SYNOPSIS
+/* #include <dict_random.h>
+/*
+/* DICT *dict_random_open(name, open_flags, dict_flags)
+/* const char *name;
+/* int open_flags;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_random_open() opens an in-memory, read-only, table.
+/* Example: "\fBrandom:\fI!result_1! ... !result_n\fR".
+/*
+/* Each table query returns a random choice from the specified
+/* results. Other table access methods are not supported.
+/*
+/* The ASCII character after "random:" will be used as the
+/* separator between the results that follow (do not use space,
+/* ",", ":" or non-ASCII).
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <myrand.h>
+#include <dict_random.h>
+
+/* Application-specific. */
+
+typedef struct {
+ DICT dict; /* generic members */
+ ARGV *replies; /* reply values */
+} DICT_RANDOM;
+
+#define STR(x) vstring_str(x)
+
+/* dict_random_lookup - find randomized-table entry */
+
+static const char *dict_random_lookup(DICT *dict, const char *unused_query)
+{
+ DICT_RANDOM *dict_random = (DICT_RANDOM *) dict;
+
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE,
+ dict_random->replies->argv[myrand() % dict_random->replies->argc]);
+}
+
+/* dict_random_close - disassociate from randomized table */
+
+static void dict_random_close(DICT *dict)
+{
+ DICT_RANDOM *dict_random = (DICT_RANDOM *) dict;
+
+ argv_free(dict_random->replies);
+ dict_free(dict);
+}
+
+/* dict_random_open - open a randomized table */
+
+DICT *dict_random_open(const char *name, int open_flags, int dict_flags)
+{
+ DICT_RANDOM *dict_random;
+ char *saved_name = 0;
+ char delim[2];
+
+ /*
+ * Clarity first. Let the optimizer worry about redundant code.
+ */
+#define DICT_RANDOM_RETURN(x) do { \
+ if (saved_name != 0) \
+ myfree(saved_name); \
+ return (x); \
+ } while (0)
+
+ /*
+ * Sanity checks.
+ */
+ if (open_flags != O_RDONLY)
+ DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name,
+ open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_RANDOM, name));
+
+ /*
+ * Split the name on the user-specified delimiter.
+ */
+ delim[0] = name[0]; /* XXX ASCII delimiter */
+ delim[1] = 0;
+ saved_name = mystrdup(name + 1); /* XXX ASCII delimiter */
+ if (*saved_name == 0)
+ DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name,
+ open_flags, dict_flags,
+ "bad syntax: \"%s:%s\"; need \"%s:%svalue%s...\"",
+ DICT_TYPE_RANDOM, name,
+ DICT_TYPE_RANDOM, delim, delim));
+
+ /*
+ * Bundle up the result.
+ */
+ dict_random =
+ (DICT_RANDOM *) dict_alloc(DICT_TYPE_RANDOM, name, sizeof(*dict_random));
+ dict_random->dict.lookup = dict_random_lookup;
+ dict_random->dict.close = dict_random_close;
+ dict_random->dict.flags = dict_flags | DICT_FLAG_PATTERN;
+ dict_random->replies = argv_split(saved_name, delim);
+ dict_random->dict.owner.status = DICT_OWNER_TRUSTED;
+ dict_random->dict.owner.uid = 0;
+
+ DICT_RANDOM_RETURN(DICT_DEBUG(&dict_random->dict));
+}
--- /dev/null
+#ifndef _DICT_RANDOM_H_INCLUDED_
+#define _DICT_RANDOM_H_INCLUDED_
+
+/*++
+/* NAME
+/* dict_random 3h
+/* SUMMARY
+/* dictionary manager interface for ramdomized tables
+/* SYNOPSIS
+/* #include <dict_random.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+
+ /*
+ * External interface.
+ */
+#define DICT_TYPE_RANDOM "random"
+
+extern DICT *dict_random_open(const char *, int, int);
+
+/* 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