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
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>

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,8 +59,8 @@ 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-

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

@ -50,6 +50,9 @@ extern int rec_pad(VSTREAM *, int, int);
#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");
}
if (prev_type == REC_TYPE_CONT && !TEXT_RECORD(rec_type))
/* 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_OFFSET)
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;
}
/*
* 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) {
/* 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_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));
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);
}
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.