]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.7-20090524
authorWietse Venema <wietse@porcupine.org>
Sun, 24 May 2009 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:35:28 +0000 (06:35 +0000)
21 files changed:
postfix/HISTORY
postfix/WISHLIST
postfix/html/postcat.1.html
postfix/html/postfix-wrapper.5.html
postfix/man/man1/postcat.1
postfix/man/man5/postfix-wrapper.5
postfix/proto/postfix-wrapper
postfix/src/cleanup/cleanup.c
postfix/src/global/mail_version.h
postfix/src/global/record.c
postfix/src/global/record.h
postfix/src/postcat/Makefile.in
postfix/src/postcat/b_test.ref [new file with mode: 0644]
postfix/src/postcat/bh_test.ref [new file with mode: 0644]
postfix/src/postcat/default_test.ref [new file with mode: 0644]
postfix/src/postcat/e_test.ref [new file with mode: 0644]
postfix/src/postcat/eb_test.ref [new file with mode: 0644]
postfix/src/postcat/eh_test.ref [new file with mode: 0644]
postfix/src/postcat/h_test.ref [new file with mode: 0644]
postfix/src/postcat/postcat.c
postfix/src/postcat/test-queue-file [new file with mode: 0644]

index dd04f009a7709c327a7791c3d3bfde6c183d9e98..1cb92710327c1b9fba97ec963bca00d2522779e3 100644 (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.
index 3a097008fd38db296d659db595a4d2913f9eb0b6..b3e7caf4aad367ce4c37bdf646f640db49a66a86 100644 (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.
index e5b841e239c2562a70566390b60844c9b2e5f4ea..cfd23409ab016a0f5368733ca470616afa12798e 100644 (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>
index 925fd207e2bca3fd23a8d09d710d9c48d0bead67..d84edda8871dbd3e31eb0f4577a7aa6a6d99396f 100644 (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>
index 4c40c6b4f6aa02f9278aa6d19226523a3232ed79..0a83ee41c22dbe4c6c20e06fec7109f2830fdb29 100644 (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
index d43a0a990e81db2902761c88962447f08acdb10b..75f69ad00eae64c1d170d0a7c37687780633d7dc 100644 (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
index abf3f56be47fb8c8794b7c9384de0db908f9887d..67c82a0787403e3e09d572c93e6652ac8a3d6ba3 100644 (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
index 0289931e9038996358cb6a37fdaa17ee8c31bd95..36f4f7948a4b1260654530ae79f80b5933caed44 100644 (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;
index b08b75bb63ee24ac1ddaaf961fe396c34e8c1eb8..f045565a408921eb96e421b7c7a9f02a422402ee 100644 (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
index b82548ce55e5ca17d3fbcb34a07e82f0bd7eb559..9686d35c85821365b439cb6df41e8a8d9868c61d 100644 (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
 /*     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.
 /*
index 472da46c93d674da7e365eab9ec4a2d0c2257ad2..c685436b1b401193cc89799535a86d8181ecd73f 100644 (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)
 
index 237bf60922f1df50e5e950303a47f9b148d26f1b..1b08ad60be3b3f5032591b2564f0b0fba2d0ae3c 100644 (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
diff --git a/postfix/src/postcat/b_test.ref b/postfix/src/postcat/b_test.ref
new file mode 100644 (file)
index 0000000..bacff0c
--- /dev/null
@@ -0,0 +1,2 @@
+
+text
diff --git a/postfix/src/postcat/bh_test.ref b/postfix/src/postcat/bh_test.ref
new file mode 100644 (file)
index 0000000..bfe9e2d
--- /dev/null
@@ -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
diff --git a/postfix/src/postcat/default_test.ref b/postfix/src/postcat/default_test.ref
new file mode 100644 (file)
index 0000000..eede38b
--- /dev/null
@@ -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 ***
diff --git a/postfix/src/postcat/e_test.ref b/postfix/src/postcat/e_test.ref
new file mode 100644 (file)
index 0000000..308b0df
--- /dev/null
@@ -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 ***
diff --git a/postfix/src/postcat/eb_test.ref b/postfix/src/postcat/eb_test.ref
new file mode 100644 (file)
index 0000000..b61beb2
--- /dev/null
@@ -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 ***
diff --git a/postfix/src/postcat/eh_test.ref b/postfix/src/postcat/eh_test.ref
new file mode 100644 (file)
index 0000000..3142553
--- /dev/null
@@ -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 ***
diff --git a/postfix/src/postcat/h_test.ref b/postfix/src/postcat/h_test.ref
new file mode 100644 (file)
index 0000000..e1a8025
--- /dev/null
@@ -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!
index 1db3d506b2eb321be4d69048ffadfa0d71bbb934..6838776a06b61b09266e3620103c1e3d06fae465 100644 (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
 /*     \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. */
 
 #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) {
diff --git a/postfix/src/postcat/test-queue-file b/postfix/src/postcat/test-queue-file
new file mode 100644 (file)
index 0000000..4979c1d
Binary files /dev/null and b/postfix/src/postcat/test-queue-file differ