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

postfix-2.7-20090524

This commit is contained in:
Wietse Venema 2009-05-24 00:00:00 -05:00 committed by Viktor Dukhovni
parent 6d9a9adc5c
commit e95efc78fc
21 changed files with 507 additions and 164 deletions

View File

@ -15242,3 +15242,20 @@ Apologies for any names omitted.
The queue file would be corrupted when the delay_warning_time
record was marked as "done" after sending the "your mail
is delayed" notice. File: qmgr/qmgr_message.c.
20090522
Bugfix (introduced: Postfix 2.3). The cleanup server
rejected mail with records of type REC_TYPE_DRCP (recipient
deleted by Milter), but such records could be present in
mail re-submitted with "postsuper -r". Found during code
review. Files: global/record.h, cleanup/cleanup_envelope.c.
20090524
Feature: new postcat options: -e (print envelope), -h (print
header), and -b (print body). Specify "postcat -bh" to
suppress information about envelope records, and "postcat
-h" to get the message header only. With large messages,
"postcat -h" is much faster than manually stripping the
message body from the output. File: postcat/postcat.c.

View File

@ -2,14 +2,6 @@ Wish list:
Remove this file from the stable release.
The cleanup server rejects mail with REC_TYPE_DRCP (recipient
deleted by Milter). What happens after "postsuper -r" with
such mail? If it is rejected, the mail is discarded.
With "mixed recipient and other" queue files that have many
recpients, can qmgr_message_read() set message->rcpt_offset
multiple times? If it does, then recipients will be skipped.
Apply header_checks and body_checks when Milters add or
modify the message content. Use case: Milters that add
spamminess headers.

View File

@ -10,7 +10,7 @@ POSTCAT(1) POSTCAT(1)
postcat - show Postfix queue file contents
<b>SYNOPSIS</b>
<b>postcat</b> [<b>-oqv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>files</i>...]
<b>postcat</b> [<b>-bhmoqv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>files</i>...]
<b>DESCRIPTION</b>
The <a href="postcat.1.html"><b>postcat</b>(1)</a> command prints the contents of the named
@ -18,13 +18,36 @@ POSTCAT(1) POSTCAT(1)
in Postfix queue file format. If no <i>files</i> are specified on
the command line, the program reads from standard input.
By default, <a href="postcat.1.html"><b>postcat</b>(1)</a> behaves as if all three options <b>-b</b>,
<b>-e</b>, and <b>-h</b> are given. To view message content only, spec-
ify <b>-bh</b> (Postfix 2.7 and later).
Options:
<b>-b</b> Show body content. The <b>-b</b> option starts producing
output at the first non-header line, and stops when
the end of the message is reached.
This feature is available in Postfix version 2.7
and later.
<b>-c</b> <i>config</i><b>_</b><i>dir</i>
The <a href="postconf.5.html"><b>main.cf</b></a> configuration file is in the named
The <a href="postconf.5.html"><b>main.cf</b></a> configuration file is in the named
directory instead of the default configuration
directory.
<b>-e</b> Show message envelope content.
This feature is available in Postfix version 2.7
and later.
<b>-h</b> Show message header content. The <b>-h</b> option pro-
duces output from the beginning of the message up
to, but not including, the first non-header line.
This feature is available in Postfix version 2.7
and later.
<b>-o</b> Print the queue file offset of each record.
<b>-q</b> Search the Postfix queue for the named <i>files</i>
@ -33,7 +56,7 @@ POSTCAT(1) POSTCAT(1)
Available in Postfix version 2.0 and later.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
tiple <b>-v</b> options make the software increasingly
tiple <b>-v</b> options make the software increasingly
verbose.
<b>DIAGNOSTICS</b>
@ -44,18 +67,18 @@ POSTCAT(1) POSTCAT(1)
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
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
to this program.
The text below provides only a parameter summary. See
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
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue direc-
The location of the Postfix top-level queue direc-
tory.
<b>FILES</b>
@ -65,7 +88,7 @@ POSTCAT(1) POSTCAT(1)
<a href="postconf.5.html">postconf(5)</a>, Postfix configuration
<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>

View File

@ -10,8 +10,8 @@ POSTFIX-WRAPPER(5) POSTFIX-WRAPPER(5)
postfix-wrapper - Postfix multi-instance API
<b>DESCRIPTION</b>
Postfix versions 2.6 and later provide support for multi-
ple Postfix instances. Instances share executable files
Support for managing multiple Postfix instances is avail-
able as of version 2.6. Instances share executable files
and documentation, but have their own directories for con-
figuration, queue and data files.
@ -59,53 +59,53 @@ POSTFIX-WRAPPER(5) POSTFIX-WRAPPER(5)
environment variable (the -c command-line option has
higher precedence).
When no Postfix instance information is specified, the
<a href="postfix.1.html">postfix(1)</a> command will operate on all Postfix instances.
Otherwise, the <a href="postfix.1.html">postfix(1)</a> command will operate on all
Postfix instances.
<b>ENABLING POSTFIX(1) MULTI-INSTANCE MODE</b>
By default, the <a href="postfix.1.html">postfix(1)</a> command operates in single-
instance mode. In this mode the command invokes the post-
fix-script file directly (currently installed in the dae-
mon directory). This file contains the commands that
start or stop one Postfix instance, that upgrade the con-
By default, the <a href="postfix.1.html">postfix(1)</a> command operates in single-
instance mode. In this mode the command invokes the post-
fix-script file directly (currently installed in the dae-
mon directory). This file contains the commands that
start or stop one Postfix instance, that upgrade the con-
figuration of one Postfix instance, and so on.
When the <a href="postfix.1.html">postfix(1)</a> command operates in multi-instance
mode as discussed below, the command needs to execute
start, stop, etc. commands for each Postfix instance.
This multiplication of commands is handled by a multi-
When the <a href="postfix.1.html">postfix(1)</a> command operates in multi-instance
mode as discussed below, the command needs to execute
start, stop, etc. commands for each Postfix instance.
This multiplication of commands is handled by a multi-
instance manager program.
Turning on <a href="postfix.1.html">postfix(1)</a> multi-instance mode goes as follows:
in the default Postfix instance's <a href="postconf.5.html">main.cf</a> file, 1) specify
the pathname of a multi-instance manager program with the
<a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> parameter; 2) populate the
<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter with the configura-
tion directory pathnames of additional Postfix instances.
the pathname of a multi-instance manager program with the
<a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> parameter; 2) populate the
<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter with the configura-
tion directory pathnames of additional Postfix instances.
For example:
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> = $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper
<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> = /etc/postfix-test
The $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper file implements a
simple manager and contains instructions for creating
Postfix instances by hand. The <a href="postmulti.1.html">postmulti(1)</a> command pro-
vides a more extensive implementation including support
The $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper file implements a
simple manager and contains instructions for creating
Postfix instances by hand. The <a href="postmulti.1.html">postmulti(1)</a> command pro-
vides a more extensive implementation including support
for life-cycle management.
The <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> and other <a href="postconf.5.html">main.cf</a> parame-
The <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> and other <a href="postconf.5.html">main.cf</a> parame-
ters are listed below in the CONFIGURATION PARAMETERS sec-
tion.
In multi-instance mode, the <a href="postfix.1.html">postfix(1)</a> command invokes the
$<a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> command instead of the postfix-
script file. This multi-instance manager in turn executes
the <a href="postfix.1.html">postfix(1)</a> command in single-instance mode for each
$<a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> command instead of the postfix-
script file. This multi-instance manager in turn executes
the <a href="postfix.1.html">postfix(1)</a> command in single-instance mode for each
Postfix instance.
To illustrate the main ideas behind multi-instance opera-
tion, below is an example of a simple but useful multi-
To illustrate the main ideas behind multi-instance opera-
tion, below is an example of a simple but useful multi-
instance manager implementation:
#!/bin/sh
@ -139,124 +139,124 @@ POSTFIX-WRAPPER(5) POSTFIX-WRAPPER(5)
<b>PER-INSTANCE MULTI-INSTANCE MANAGER CONTROLS</b>
Each Postfix instance has its own <a href="postconf.5.html">main.cf</a> file with param-
eters that control how the multi-instance manager operates
on that instance. This section discusses the most impor-
on that instance. This section discusses the most impor-
tant settings.
The setting "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes" allows the
multi-instance manager to start (stop, etc.) the corre-
sponding Postfix instance. For safety reasons, this set-
multi-instance manager to start (stop, etc.) the corre-
sponding Postfix instance. For safety reasons, this set-
ting is not the default.
The default setting "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = no" is useful
for manual testing with "postfix -c <i>/path/name</i> start" etc.
The multi-instance manager will not start such an
instance, and it will skip commands such as "stop" or
"flush" that require a running Postfix instance. The
The multi-instance manager will not start such an
instance, and it will skip commands such as "stop" or
"flush" that require a running Postfix instance. The
multi-instance manager will execute commands such as
"check", "set-permissions" or "upgrade-configuration", and
it will replace "start" by "check" so that problems will
it will replace "start" by "check" so that problems will
be reported even when the instance is disabled.
<b>MAINTAINING SHARED AND NON-SHARED FILES</b>
Some files are shared between Postfix instances, such as
Some files are shared between Postfix instances, such as
executables and manpages, and some files are per-instance,
such as configuration files, mail queue files, and data
files. See the NON-SHARED FILES section below for a list
such as configuration files, mail queue files, and data
files. See the NON-SHARED FILES section below for a list
of per-instance files.
Before Postfix multi-instance support was implemented, the
executables, manpages, etc., have always been maintained
executables, manpages, etc., have always been maintained
as part of the default Postfix instance.
With multi-instance support, we simply continue to do
this. Specifically, a Postfix instance will not check or
update shared files when that instance's <a href="postconf.5.html#config_directory">config_directory</a>
value is listed with the default <a href="postconf.5.html">main.cf</a> file's
With multi-instance support, we simply continue to do
this. Specifically, a Postfix instance will not check or
update shared files when that instance's <a href="postconf.5.html#config_directory">config_directory</a>
value is listed with the default <a href="postconf.5.html">main.cf</a> file's
<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter.
The consequence of this approach is that the default Post-
fix instance should be checked and updated before any
fix instance should be checked and updated before any
other instances.
<b>MULTI-INSTANCE API SUMMARY</b>
Only the multi-instance manager implements support for the
<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> configuration parameter. The multi-
instance manager will start only Postfix instances whose
<a href="postconf.5.html">main.cf</a> file has "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes". A setting
<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> configuration parameter. The multi-
instance manager will start only Postfix instances whose
<a href="postconf.5.html">main.cf</a> file has "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes". A setting
of "no" allows a Postfix instance to be tested by hand.
The <a href="postfix.1.html">postfix(1)</a> command operates on only one Postfix
instance when the -c option is specified, or when
instance when the -c option is specified, or when
MAIL_CONFIG is present in the process environment. This is
necessary to terminate recursion.
Otherwise, when the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter
value is non-empty, the <a href="postfix.1.html">postfix(1)</a> command executes the
command specified with the <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> parame-
ter, instead of executing the commands in postfix-script.
Otherwise, when the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter
value is non-empty, the <a href="postfix.1.html">postfix(1)</a> command executes the
command specified with the <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> parame-
ter, instead of executing the commands in postfix-script.
The multi-instance manager skips commands such as "stop"
or "reload" that require a running Postfix instance, when
an instance does not have "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes".
The multi-instance manager skips commands such as "stop"
or "reload" that require a running Postfix instance, when
an instance does not have "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes".
This avoids false error messages.
The multi-instance manager replaces a "start" command by
"check" when a Postfix instance's <a href="postconf.5.html">main.cf</a> file does not
The multi-instance manager replaces a "start" command by
"check" when a Postfix instance's <a href="postconf.5.html">main.cf</a> file does not
have "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes". This substitution
ensures that problems will be reported even when the
ensures that problems will be reported even when the
instance is disabled.
No Postfix command or script will update or check shared
files when its <a href="postconf.5.html#config_directory">config_directory</a> value is listed in the
default <a href="postconf.5.html">main.cf</a>'s <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter
value. Therefore, the default instance should be checked
and updated before any Postfix instances that depend on
No Postfix command or script will update or check shared
files when its <a href="postconf.5.html#config_directory">config_directory</a> value is listed in the
default <a href="postconf.5.html">main.cf</a>'s <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter
value. Therefore, the default instance should be checked
and updated before any Postfix instances that depend on
it.
Set-gid commands such as <a href="postdrop.1.html">postdrop(1)</a> and <a href="postqueue.1.html">postqueue(1)</a>
effectively append the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parame-
ter value to the legacy <a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a>
parameter value. The commands use this information to
determine whether a -c option or MAIL_CONFIG environment
Set-gid commands such as <a href="postdrop.1.html">postdrop(1)</a> and <a href="postqueue.1.html">postqueue(1)</a>
effectively append the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parame-
ter value to the legacy <a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a>
parameter value. The commands use this information to
determine whether a -c option or MAIL_CONFIG environment
setting specifies a legitimate value.
The legacy <a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a> parameter remains
necessary for non-default Postfix instances that are run-
ning different versions of Postfix, or that are not man-
The legacy <a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a> parameter remains
necessary for non-default Postfix instances that are run-
ning different versions of Postfix, or that are not man-
aged together with the default Postfix instance.
<b>ENVIRONMENT VARIABLES</b>
MAIL_CONFIG
When present, this forces the <a href="postfix.1.html">postfix(1)</a> command to
operate only on the specified Postfix instance.
This environment variable is exported by the <a href="postfix.1.html">post-</a>
<a href="postfix.1.html">fix(1)</a> -c option, so that <a href="postfix.1.html">postfix(1)</a> commands in
operate only on the specified Postfix instance.
This environment variable is exported by the <a href="postfix.1.html">post-</a>
<a href="postfix.1.html">fix(1)</a> -c option, so that <a href="postfix.1.html">postfix(1)</a> commands in
descendant processes will work correctly.
<b>CONFIGURATION PARAMETERS</b>
The text below provides only a parameter summary. See
The text below provides only a parameter summary. See
<a href="postconf.5.html">postconf(5)</a> for more details.
<b><a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> (empty)</b>
An optional list of non-default Postfix configura-
An optional list of non-default Postfix configura-
tion directories; these directories belong to addi-
tional Postfix instances that share the Postfix
tional Postfix instances that share the Postfix
executable files and documentation with the default
Postfix instance, and that are started, stopped,
Postfix instance, and that are started, stopped,
etc., together with the default Postfix instance.
<b><a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> (empty)</b>
The pathname of a multi-instance manager command
that the <a href="postfix.1.html"><b>postfix</b>(1)</a> command invokes when the
<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter value is non-
The pathname of a multi-instance manager command
that the <a href="postfix.1.html"><b>postfix</b>(1)</a> command invokes when the
<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter value is non-
empty.
<b><a href="postconf.5.html#multi_instance_name">multi_instance_name</a> (empty)</b>
The optional instance name of this Postfix
The optional instance name of this Postfix
instance.
<b><a href="postconf.5.html#multi_instance_group">multi_instance_group</a> (empty)</b>
The optional instance group name of this Postfix
The optional instance group name of this Postfix
instance.
<b><a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> (no)</b>
@ -265,7 +265,7 @@ POSTFIX-WRAPPER(5) POSTFIX-WRAPPER(5)
<b>NON-SHARED FILES</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
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#data_directory">data_directory</a> (see 'postconf -d' output)</b>
@ -273,7 +273,7 @@ POSTFIX-WRAPPER(5) POSTFIX-WRAPPER(5)
example: caches, pseudo-random numbers).
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue direc-
The location of the Postfix top-level queue direc-
tory.
<b>SEE ALSO</b>
@ -282,7 +282,7 @@ POSTFIX-WRAPPER(5) POSTFIX-WRAPPER(5)
$<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper simple multi-instance 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>

View File

@ -8,7 +8,7 @@ show Postfix queue file contents
.SH "SYNOPSIS"
.na
.nf
\fBpostcat\fR [\fB-oqv\fR] [\fB-c \fIconfig_dir\fR] [\fIfiles\fR...]
\fBpostcat\fR [\fB-bhmoqv\fR] [\fB-c \fIconfig_dir\fR] [\fIfiles\fR...]
.SH DESCRIPTION
.ad
.fi
@ -18,10 +18,30 @@ to be in Postfix queue file format. If no
\fIfiles\fR are specified on the command line, the program
reads from standard input.
By default, \fBpostcat\fR(1) behaves as if all three options
\fB-b\fR, \fB-e\fR, and \fB-h\fR are given. To view message
content only, specify \fB-bh\fR (Postfix 2.7 and later).
Options:
.IP \fB-b\fR
Show body content. The \fB-b\fR option starts producing
output at the first non-header line, and stops when the end
of the message is reached.
.sp
This feature is available in Postfix version 2.7 and later.
.IP "\fB-c \fIconfig_dir\fR"
The \fBmain.cf\fR configuration file is in the named directory
instead of the default configuration directory.
.IP \fB-e\fR
Show message envelope content.
.sp
This feature is available in Postfix version 2.7 and later.
.IP \fB-h\fR
Show message header content. The \fB-h\fR option produces
output from the beginning of the message up to, but not
including, the first non-header line.
.sp
This feature is available in Postfix version 2.7 and later.
.IP \fB-o\fR
Print the queue file offset of each record.
.IP \fB-q\fR

View File

@ -8,8 +8,8 @@ Postfix multi-instance API
.SH DESCRIPTION
.ad
.fi
Postfix versions 2.6 and later provide support for multiple
Postfix instances. Instances share executable files and
Support for managing multiple Postfix instances is available
as of version 2.6. Instances share executable files and
documentation, but have their own directories for configuration,
queue and data files.
@ -62,8 +62,8 @@ Alternatively, the postfix(1) command accepts the instance's
configuration directory via the MAIL_CONFIG environment
variable (the -c command-line option has higher precedence).
When no Postfix instance information is specified, the
postfix(1) command will operate on all Postfix instances.
Otherwise, the postfix(1) command will operate on all Postfix
instances.
.SH "ENABLING POSTFIX(1) MULTI-INSTANCE MODE"
.na
.nf

View File

@ -4,8 +4,8 @@
# SUMMARY
# Postfix multi-instance API
# DESCRIPTION
# Postfix versions 2.6 and later provide support for multiple
# Postfix instances. Instances share executable files and
# Support for managing multiple Postfix instances is available
# as of version 2.6. Instances share executable files and
# documentation, but have their own directories for configuration,
# queue and data files.
#
@ -54,8 +54,8 @@
# configuration directory via the MAIL_CONFIG environment
# variable (the -c command-line option has higher precedence).
#
# When no Postfix instance information is specified, the
# postfix(1) command will operate on all Postfix instances.
# Otherwise, the postfix(1) command will operate on all Postfix
# instances.
# ENABLING POSTFIX(1) MULTI-INSTANCE MODE
# .ad
# .fi

View File

@ -462,8 +462,7 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
state->errs |= CLEANUP_STAT_BAD;
break;
}
if (type == REC_TYPE_PTR || type == REC_TYPE_DTXT
|| type == REC_TYPE_DRCP) {
if (REC_GET_HIDDEN_TYPE(type)) {
msg_warn("%s: record type %d not allowed - discarding this message",
state->queue_id, type);
state->errs |= CLEANUP_STAT_BAD;

View File

@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20090519"
#define MAIL_RELEASE_DATE "20090524"
#define MAIL_VERSION_NUMBER "2.7"
#ifdef SNAPSHOT

View File

@ -61,6 +61,9 @@
/* REC_SPACE_NEED(buflen, reclen)
/* ssize_t buflen;
/* ssize_t reclen;
/*
/* REC_GET_HIDDEN_TYPE(type)
/* int type;
/* DESCRIPTION
/* This module reads and writes typed variable-length records.
/* Each record contains a 1-byte type code (0..255), a length
@ -89,6 +92,10 @@
/* enables the REC_FLAG_FOLLOW_PTR, REC_FLAG_SKIP_DTXT
/* and REC_FLAG_SEEK_END features.
/*
/* REC_GET_HIDDEN_TYPE() is an unsafe macro that returns
/* non-zero when the specified record type is "not exposed"
/* by rec_get().
/*
/* rec_put() stores the specified record and returns the record
/* type, or REC_TYPE_ERROR in case of problems.
/*

View File

@ -42,14 +42,17 @@ extern int rec_pad(VSTREAM *, int, int);
#define REC_PUT_BUF(v, t, b) rec_put((v), (t), vstring_str(b), VSTRING_LEN(b))
#define REC_FLAG_NONE (0)
#define REC_FLAG_FOLLOW_PTR (1<<0) /* follow PTR records */
#define REC_FLAG_SKIP_DTXT (1<<1) /* skip DTXT records */
#define REC_FLAG_SEEK_END (1<<2) /* seek EOF after END record */
#define REC_FLAG_NONE (0)
#define REC_FLAG_FOLLOW_PTR (1<<0) /* follow PTR records */
#define REC_FLAG_SKIP_DTXT (1<<1) /* skip DTXT records */
#define REC_FLAG_SEEK_END (1<<2) /* seek EOF after END record */
#define REC_FLAG_DEFAULT \
(REC_FLAG_FOLLOW_PTR | REC_FLAG_SKIP_DTXT | REC_FLAG_SEEK_END)
#define REC_GET_HIDDEN_TYPE(t) \
((t) == REC_TYPE_PTR || (t) == REC_TYPE_DTXT)
#define rec_get(fp, buf, limit) \
rec_get_raw((fp), (buf), (limit), REC_FLAG_DEFAULT)

View File

@ -22,7 +22,7 @@ Makefile: Makefile.in
test: $(TESTPROG)
tests:
tests: default_test ebh_test e_test b_test h_test eb_test eh_test bh_test
root_tests:
@ -47,6 +47,46 @@ clean:
tidy: clean
default_test: test-queue-file default_test.ref
./postcat test-queue-file >postcat.tmp 2>&1
diff default_test.ref postcat.tmp
rm -f postcat.tmp
ebh_test: test-queue-file default_test.ref
./postcat -ebh test-queue-file >postcat.tmp 2>&1
diff default_test.ref postcat.tmp
rm -f postcat.tmp
e_test: test-queue-file e_test.ref
./postcat -e test-queue-file >postcat.tmp 2>&1
diff e_test.ref postcat.tmp
rm -f postcat.tmp
b_test: test-queue-file b_test.ref
./postcat -b test-queue-file >postcat.tmp 2>&1
diff b_test.ref postcat.tmp
rm -f postcat.tmp
h_test: test-queue-file h_test.ref
./postcat -h test-queue-file >postcat.tmp 2>&1
diff h_test.ref postcat.tmp
rm -f postcat.tmp
eb_test: test-queue-file eb_test.ref
./postcat -eb test-queue-file >postcat.tmp 2>&1
diff eb_test.ref postcat.tmp
rm -f postcat.tmp
eh_test: test-queue-file eh_test.ref
./postcat -eh test-queue-file >postcat.tmp 2>&1
diff eh_test.ref postcat.tmp
rm -f postcat.tmp
bh_test: test-queue-file bh_test.ref
./postcat -bh test-queue-file >postcat.tmp 2>&1
diff bh_test.ref postcat.tmp
rm -f postcat.tmp
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
@ -59,6 +99,8 @@ depend: $(MAKES)
# do not edit below this line - it is generated by 'make depend'
postcat.o: ../../include/attr.h
postcat.o: ../../include/iostuff.h
postcat.o: ../../include/is_header.h
postcat.o: ../../include/lex_822.h
postcat.o: ../../include/mail_conf.h
postcat.o: ../../include/mail_params.h
postcat.o: ../../include/mail_proto.h

View File

@ -0,0 +1,2 @@
text

View File

@ -0,0 +1,9 @@
Received: by hades.porcupine.org (Postfix, from userid 1001)
id DE040290405; Sun, 21 Jan 2007 13:33:08 -0500 (EST)
From: me@porcupine.org
To: you@porcupine.org
Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
Subject: hey!
text

View File

@ -0,0 +1,21 @@
*** ENVELOPE RECORDS test-queue-file ***
message_size: 332 182 1 0 332
message_arrival_time: Sun Jan 21 13:32:59 2007
create_time: Sun Jan 21 13:33:08 2007
named_attribute: rewrite_context=local
sender_fullname: Wietse Venema
sender: me@porcupine.org
*** MESSAGE CONTENTS test-queue-file ***
Received: by hades.porcupine.org (Postfix, from userid 1001)
id DE040290405; Sun, 21 Jan 2007 13:33:08 -0500 (EST)
From: me@porcupine.org
To: you@porcupine.org
Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
Subject: hey!
text
*** HEADER EXTRACTED test-queue-file ***
original_recipient: you@porcupine.org
recipient: you@porcupine.org
*** MESSAGE FILE END test-queue-file ***

View File

@ -0,0 +1,12 @@
*** ENVELOPE RECORDS test-queue-file ***
message_size: 332 182 1 0 332
message_arrival_time: Sun Jan 21 13:32:59 2007
create_time: Sun Jan 21 13:33:08 2007
named_attribute: rewrite_context=local
sender_fullname: Wietse Venema
sender: me@porcupine.org
*** MESSAGE CONTENTS test-queue-file ***
*** HEADER EXTRACTED test-queue-file ***
original_recipient: you@porcupine.org
recipient: you@porcupine.org
*** MESSAGE FILE END test-queue-file ***

View File

@ -0,0 +1,14 @@
*** ENVELOPE RECORDS test-queue-file ***
message_size: 332 182 1 0 332
message_arrival_time: Sun Jan 21 13:32:59 2007
create_time: Sun Jan 21 13:33:08 2007
named_attribute: rewrite_context=local
sender_fullname: Wietse Venema
sender: me@porcupine.org
*** MESSAGE CONTENTS test-queue-file ***
text
*** HEADER EXTRACTED test-queue-file ***
original_recipient: you@porcupine.org
recipient: you@porcupine.org
*** MESSAGE FILE END test-queue-file ***

View File

@ -0,0 +1,19 @@
*** ENVELOPE RECORDS test-queue-file ***
message_size: 332 182 1 0 332
message_arrival_time: Sun Jan 21 13:32:59 2007
create_time: Sun Jan 21 13:33:08 2007
named_attribute: rewrite_context=local
sender_fullname: Wietse Venema
sender: me@porcupine.org
*** MESSAGE CONTENTS test-queue-file ***
Received: by hades.porcupine.org (Postfix, from userid 1001)
id DE040290405; Sun, 21 Jan 2007 13:33:08 -0500 (EST)
From: me@porcupine.org
To: you@porcupine.org
Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
Subject: hey!
*** HEADER EXTRACTED test-queue-file ***
original_recipient: you@porcupine.org
recipient: you@porcupine.org
*** MESSAGE FILE END test-queue-file ***

View File

@ -0,0 +1,7 @@
Received: by hades.porcupine.org (Postfix, from userid 1001)
id DE040290405; Sun, 21 Jan 2007 13:33:08 -0500 (EST)
From: me@porcupine.org
To: you@porcupine.org
Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
Subject: hey!

View File

@ -4,7 +4,7 @@
/* SUMMARY
/* show Postfix queue file contents
/* SYNOPSIS
/* \fBpostcat\fR [\fB-oqv\fR] [\fB-c \fIconfig_dir\fR] [\fIfiles\fR...]
/* \fBpostcat\fR [\fB-bhmoqv\fR] [\fB-c \fIconfig_dir\fR] [\fIfiles\fR...]
/* DESCRIPTION
/* The \fBpostcat\fR(1) command prints the contents of the named
/* \fIfiles\fR in human-readable form. The files are expected
@ -12,10 +12,30 @@
/* \fIfiles\fR are specified on the command line, the program
/* reads from standard input.
/*
/* By default, \fBpostcat\fR(1) behaves as if all three options
/* \fB-b\fR, \fB-e\fR, and \fB-h\fR are given. To view message
/* content only, specify \fB-bh\fR (Postfix 2.7 and later).
/*
/* Options:
/* .IP \fB-b\fR
/* Show body content. The \fB-b\fR option starts producing
/* output at the first non-header line, and stops when the end
/* of the message is reached.
/* .sp
/* This feature is available in Postfix version 2.7 and later.
/* .IP "\fB-c \fIconfig_dir\fR"
/* The \fBmain.cf\fR configuration file is in the named directory
/* instead of the default configuration directory.
/* .IP \fB-e\fR
/* Show message envelope content.
/* .sp
/* This feature is available in Postfix version 2.7 and later.
/* .IP \fB-h\fR
/* Show message header content. The \fB-h\fR option produces
/* output from the beginning of the message up to, but not
/* including, the first non-header line.
/* .sp
/* This feature is available in Postfix version 2.7 and later.
/* .IP \fB-o\fR
/* Print the queue file offset of each record.
/* .IP \fB-q\fR
@ -71,6 +91,7 @@
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h> /* sscanf() */
/* Utility library. */
@ -90,11 +111,26 @@
#include <mail_params.h>
#include <mail_version.h>
#include <mail_proto.h>
#include <is_header.h>
#include <lex_822.h>
/* Application-specific. */
#define PC_FLAG_QUEUE (1<<0) /* search queue */
#define PC_FLAG_OFFSET (1<<1) /* print record offsets */
#define PC_FLAG_SEARCH_QUEUE (1<<0) /* search queue */
#define PC_FLAG_PRINT_OFFSET (1<<1) /* print record offsets */
#define PC_FLAG_PRINT_ENV (1<<2) /* print envelope records */
#define PC_FLAG_PRINT_HEADER (1<<3) /* print header records */
#define PC_FLAG_PRINT_BODY (1<<4) /* print body records */
#define PC_MASK_PRINT_TEXT (PC_FLAG_PRINT_HEADER | PC_FLAG_PRINT_BODY)
#define PC_MASK_PRINT_ALL (PC_FLAG_PRINT_ENV | PC_MASK_PRINT_TEXT)
/*
* State machine.
*/
#define PC_STATE_ENV 0 /* initial or extracted envelope */
#define PC_STATE_HEADER 1 /* primary header */
#define PC_STATE_BODY 2 /* other */
#define STR vstring_str
#define LEN VSTRING_LEN
@ -107,14 +143,16 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
int rec_type;
struct timeval tv;
time_t time;
int first = 1;
int ch;
off_t offset;
int in_message = 0;
const char *error_text;
char *attr_name;
char *attr_value;
int rec_flags = (msg_verbose ? REC_FLAG_NONE : REC_FLAG_DEFAULT);
int state; /* state machine, input type */
int do_print; /* state machine, output control */
long data_offset; /* state machine, read optimization */
long data_size; /* state machine, read optimization */
#define TEXT_RECORD(rec_type) \
(rec_type == REC_TYPE_CONT || rec_type == REC_TYPE_NORM)
@ -130,24 +168,149 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
vstream_ungetc(fp, ch);
}
/*
* Other preliminaries.
*/
if (flags & PC_FLAG_PRINT_ENV)
vstream_printf("*** ENVELOPE RECORDS %s ***\n",
VSTREAM_PATH(fp));
state = PC_STATE_ENV;
do_print = (flags & PC_FLAG_PRINT_ENV);
data_offset = data_size = -1;
/*
* Now look at the rest.
*/
do {
if (flags & PC_FLAG_OFFSET)
for (;;) {
if (flags & PC_FLAG_PRINT_OFFSET)
offset = vstream_ftell(fp);
rec_type = rec_get_raw(fp, buffer, 0, rec_flags);
if (rec_type == REC_TYPE_ERROR)
msg_fatal("record read error");
if (rec_type == REC_TYPE_EOF)
break;
if (first == 1) {
vstream_printf("*** ENVELOPE RECORDS %s ***\n", VSTREAM_PATH(fp));
first = 0;
/*
* First inspect records that have side effects on the (envelope,
* header, body) state machine or on the record reading order.
*
* XXX Comments marked "Optimization:" identify subtle code that will
* likely need to be revised when the queue file organization is
* changed.
*/
#define PRINT_MARKER(flags, fp, offset, text) do { \
if ((flags) & PC_FLAG_PRINT_OFFSET) \
vstream_printf("%9lu ", (unsigned long) (offset)); \
vstream_printf("*** %s %s ***\n", (text), VSTREAM_PATH(fp)); \
vstream_fflush(VSTREAM_OUT); \
} while (0)
#define PRINT_RECORD(flags, offset, type, value) do { \
if ((flags) & PC_FLAG_PRINT_OFFSET) \
vstream_printf("%9lu ", (unsigned long) (offset)); \
vstream_printf("%s: %s\n", rec_type_name(rec_type), (value)); \
vstream_fflush(VSTREAM_OUT); \
} while (0)
if (TEXT_RECORD(rec_type)) {
/* This is wrong when the message starts with whitespace. */
if (state == PC_STATE_HEADER && (flags & (PC_MASK_PRINT_TEXT))
&& prev_type != REC_TYPE_CONT && TEXT_RECORD(rec_type)
&& !(is_header(STR(buffer)) || IS_SPACE_TAB(STR(buffer)[0]))) {
/* Update the state machine. */
state = PC_STATE_BODY;
do_print = (flags & PC_FLAG_PRINT_BODY);
/* Optimization: terminate if nothing left to print. */
if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV) == 0)
break;
/* Optimization: skip to extracted segment marker. */
if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV)
&& data_offset >= 0 && data_size >= 0
&& vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
msg_fatal("seek error: %m");
}
/* Optional output happens further down below. */
} else if (rec_type == REC_TYPE_MESG) {
/* Sanity check. */
if (state != PC_STATE_ENV)
msg_warn("%s: out-of-order message content marker",
VSTREAM_PATH(fp));
/* Optional output. */
if (flags & PC_FLAG_PRINT_ENV)
PRINT_MARKER(flags, fp, offset, "MESSAGE CONTENTS");
/* Optimization: skip to extracted segment marker. */
if ((flags & PC_MASK_PRINT_TEXT) == 0
&& data_offset >= 0 && data_size >= 0
&& vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
msg_fatal("seek error: %m");
/* Update the state machine, even when skipping. */
state = PC_STATE_HEADER;
do_print = (flags & PC_FLAG_PRINT_HEADER);
continue;
} else if (rec_type == REC_TYPE_XTRA) {
/* Sanity check. */
if (state != PC_STATE_HEADER && state != PC_STATE_BODY)
msg_warn("%s: out-of-order extracted segment marker",
VSTREAM_PATH(fp));
/* Optional output (terminate preceding header/body line). */
if (do_print && prev_type == REC_TYPE_CONT)
VSTREAM_PUTCHAR('\n');
if (flags & PC_FLAG_PRINT_ENV)
PRINT_MARKER(flags, fp, offset, "HEADER EXTRACTED");
/* Update the state machine. */
state = PC_STATE_ENV;
do_print = (flags & PC_FLAG_PRINT_ENV);
/* Optimization: terminate if nothing left to print. */
if (do_print == 0)
break;
continue;
} else if (rec_type == REC_TYPE_END) {
/* Sanity check. */
if (state != PC_STATE_ENV)
msg_warn("%s: out-of-order message end marker",
VSTREAM_PATH(fp));
/* Optional output. */
if (flags & PC_FLAG_PRINT_ENV)
PRINT_MARKER(flags, fp, offset, "MESSAGE FILE END");
/* Terminate the state machine. */
break;
} else if (rec_type == REC_TYPE_PTR) {
/* Optional output. */
/* This record type is exposed only with '-v'. */
if (do_print)
PRINT_RECORD(flags, offset, rec_type, STR(buffer));
/* Skip to the pointer's target record. */
if (rec_goto(fp, STR(buffer)) == REC_TYPE_ERROR)
msg_fatal("bad pointer record, or input is not seekable");
continue;
} else if (rec_type == REC_TYPE_SIZE) {
if (data_size >= 0 || data_offset >= 0) {
msg_warn("file contains multiple size records");
} else {
if (sscanf(STR(buffer), "%ld %ld", &data_size, &data_offset) != 2
|| data_offset <= 0 || data_size <= 0)
msg_fatal("invalid size record: %.100s", STR(buffer));
/* Optional output (here since we update the state machine). */
if (do_print)
PRINT_RECORD(flags, offset, rec_type, STR(buffer));
/* Optimization: skip to the message header. */
if ((flags & PC_FLAG_PRINT_ENV) == 0) {
if (vstream_fseek(fp, data_offset, SEEK_SET) < 0)
msg_fatal("seek error: %m");
/* Update the state machine. */
state = PC_STATE_HEADER;
do_print = (flags & PC_FLAG_PRINT_HEADER);
}
}
continue;
}
if (prev_type == REC_TYPE_CONT && !TEXT_RECORD(rec_type))
VSTREAM_PUTCHAR('\n');
if (flags & PC_FLAG_OFFSET)
/*
* Don't inspect side-effect-free records that aren't printed.
*/
if (do_print == 0)
continue;
if (flags & PC_FLAG_PRINT_OFFSET)
vstream_printf("%9lu ", (unsigned long) offset);
switch (rec_type) {
case REC_TYPE_TIME:
@ -161,20 +324,14 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
vstream_printf("%s: %s", rec_type_name(rec_type),
asctime(localtime(&time)));
break;
case REC_TYPE_PTR: /* pointer */
vstream_printf("%s: ", rec_type_name(rec_type));
vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
VSTREAM_PUTCHAR('\n');
if (rec_goto(fp, STR(buffer)) == REC_TYPE_ERROR)
msg_fatal("bad pointer record, or input is not seekable");
break;
case REC_TYPE_CONT: /* REC_TYPE_FILT collision */
if (!in_message)
if (state == PC_STATE_ENV)
vstream_printf("%s: ", rec_type_name(rec_type));
else if (msg_verbose)
vstream_printf("unterminated_text: ");
vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
if (!in_message || msg_verbose || (flags & PC_FLAG_OFFSET) != 0) {
if (state == PC_STATE_ENV || msg_verbose
|| (flags & PC_FLAG_PRINT_OFFSET) != 0) {
rec_type = 0;
VSTREAM_PUTCHAR('\n');
}
@ -186,22 +343,10 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
VSTREAM_PUTCHAR('\n');
break;
case REC_TYPE_DTXT:
if (msg_verbose) {
vstream_printf("%s: ", rec_type_name(rec_type));
vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
VSTREAM_PUTCHAR('\n');
}
break;
case REC_TYPE_MESG:
vstream_printf("*** MESSAGE CONTENTS %s ***\n", VSTREAM_PATH(fp));
in_message = 1;
break;
case REC_TYPE_XTRA:
vstream_printf("*** HEADER EXTRACTED %s ***\n", VSTREAM_PATH(fp));
in_message = 0;
break;
case REC_TYPE_END:
vstream_printf("*** MESSAGE FILE END %s ***\n", VSTREAM_PATH(fp));
/* This record type is exposed only with '-v'. */
vstream_printf("%s: ", rec_type_name(rec_type));
vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
VSTREAM_PUTCHAR('\n');
break;
case REC_TYPE_ATTR:
error_text = split_nameval(STR(buffer), &attr_name, &attr_value);
@ -214,10 +359,10 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
time = atol(attr_value);
vstream_printf("%s: %s", MAIL_ATTR_CREATE_TIME,
asctime(localtime(&time)));
break;
} else {
vstream_printf("%s: %s=%s\n", rec_type_name(rec_type),
attr_name, attr_value);
}
vstream_printf("%s: %s=%s\n", rec_type_name(rec_type),
attr_name, attr_value);
break;
default:
vstream_printf("%s: %s\n", rec_type_name(rec_type), STR(buffer));
@ -229,7 +374,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
* In case the next record is broken.
*/
vstream_fflush(VSTREAM_OUT);
} while (rec_type != REC_TYPE_END);
}
}
/* usage - explain and terminate */
@ -284,17 +429,26 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
while ((ch = GETOPT(argc, argv, "c:oqv")) > 0) {
while ((ch = GETOPT(argc, argv, "bc:ehoqv")) > 0) {
switch (ch) {
case 'b':
flags |= PC_FLAG_PRINT_BODY;
break;
case 'c':
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
msg_fatal("out of memory");
break;
case 'e':
flags |= PC_FLAG_PRINT_ENV;
break;
case 'h':
flags |= PC_FLAG_PRINT_HEADER;
break;
case 'o':
flags |= PC_FLAG_OFFSET;
flags |= PC_FLAG_PRINT_OFFSET;
break;
case 'q':
flags |= PC_FLAG_QUEUE;
flags |= PC_FLAG_SEARCH_QUEUE;
break;
case 'v':
msg_verbose++;
@ -303,6 +457,8 @@ int main(int argc, char **argv)
usage(argv[0]);
}
}
if ((flags & PC_MASK_PRINT_ALL) == 0)
flags |= PC_MASK_PRINT_ALL;
/*
* Further initialization...
@ -327,7 +483,7 @@ int main(int argc, char **argv)
/*
* Copy the named queue files in the specified order.
*/
else if (flags & PC_FLAG_QUEUE) {
else if (flags & PC_FLAG_SEARCH_QUEUE) {
if (chdir(var_queue_dir))
msg_fatal("chdir %s: %m", var_queue_dir);
while (optind < argc) {

Binary file not shown.