mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 05:07:58 +00:00
postfix-3.1-20151129
This commit is contained in:
parent
fd122dde8c
commit
6b8ab5dd1f
@ -22010,3 +22010,18 @@ Apologies for any names omitted.
|
|||||||
Bitrot: OpenSSL API cleanups. Viktor Dukhovni. Files:
|
Bitrot: OpenSSL API cleanups. Viktor Dukhovni. Files:
|
||||||
.indent.pro, tls/tls.h, tls/tls_dane.c, tls/tls_fprint.c,
|
.indent.pro, tls/tls.h, tls/tls_dane.c, tls/tls_fprint.c,
|
||||||
tls/tls_misc.c, tls/tls_server.c, tls/tls_verify.c.
|
tls/tls_misc.c, tls/tls_server.c, tls/tls_verify.c.
|
||||||
|
|
||||||
|
20151124
|
||||||
|
|
||||||
|
Bugfix (introduced: Postfix 3.0): don't throttle a destination
|
||||||
|
after opportunistic TLS failure. Viktor Dukhovni and Wietse.
|
||||||
|
Files: smtp/smtp_proto.c, smtp/smtp.h, smtp/smtp_trouble.c.
|
||||||
|
|
||||||
|
20151128
|
||||||
|
|
||||||
|
Feature: JSON-formatted queue listing with "postqueue -j".
|
||||||
|
Output is a stream of JSON objects, one per queue file. To
|
||||||
|
simplify stream-mode parsing, each JSON object is followed by
|
||||||
|
a newline character. Files: postqueue/postqueue.c,
|
||||||
|
postqueue/postqueue.h, postqueue/showq_compat.c,
|
||||||
|
postqueue/showq_json.c, showq/showq.c.
|
||||||
|
@ -105,8 +105,8 @@ later.
|
|||||||
6 smtpd_starttls_timeout = ${stress?{10}:{300}}s
|
6 smtpd_starttls_timeout = ${stress?{10}:{300}}s
|
||||||
7 address_verify_poll_count = ${stress?{1}:{3}}
|
7 address_verify_poll_count = ${stress?{1}:{3}}
|
||||||
|
|
||||||
With Postfix versions before 3.0, replace ${stress?{x}:{y}} with ${stress?x}$
|
Postfix versions before 3.0 use the older form ${stress?x}${stress:y} instead
|
||||||
{stress:y}.
|
of the newer form ${stress?{x}:{y}}.
|
||||||
|
|
||||||
Translation:
|
Translation:
|
||||||
|
|
||||||
@ -149,8 +149,8 @@ Translation:
|
|||||||
$unverified_sender_tempfail_action. No mail should be lost, as long as this
|
$unverified_sender_tempfail_action. No mail should be lost, as long as this
|
||||||
measure is used only temporarily.
|
measure is used only temporarily.
|
||||||
|
|
||||||
The syntax of ${name?value} and ${name:value} is explained at the beginning of
|
The syntax of ${name?{value}:{value}}, ${name?value} and ${name:value} is
|
||||||
the postconf(5) manual page.
|
explained at the beginning of the postconf(5) manual page.
|
||||||
|
|
||||||
NOTE: Please keep in mind that the stress-adaptive feature is a fairly
|
NOTE: Please keep in mind that the stress-adaptive feature is a fairly
|
||||||
desperate measure to keep ssoommee legitimate mail flowing under overload
|
desperate measure to keep ssoommee legitimate mail flowing under overload
|
||||||
|
@ -168,8 +168,8 @@ default with Postfix 2.6 and later. </p>
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p> With Postfix versions before 3.0, replace ${stress?{x}:{y}}
|
<p> Postfix versions before 3.0 use the older form ${stress?x}${stress:y}
|
||||||
with ${stress?x}${stress:y}. </p>
|
instead of the newer form ${stress?{x}:{y}}. </p>
|
||||||
|
|
||||||
<p> Translation: <p>
|
<p> Translation: <p>
|
||||||
|
|
||||||
@ -219,8 +219,9 @@ as this measure is used only temporarily. </p>
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p> The syntax of ${name?value} and ${name:value} is explained at
|
<p> The syntax of ${name?{value}:{value}}, ${name?value} and
|
||||||
the beginning of the <a href="postconf.5.html">postconf(5)</a> manual page. </p>
|
${name:value} is explained at the beginning of the <a href="postconf.5.html">postconf(5)</a>
|
||||||
|
manual page. </p>
|
||||||
|
|
||||||
<p> NOTE: Please keep in mind that the stress-adaptive feature is
|
<p> NOTE: Please keep in mind that the stress-adaptive feature is
|
||||||
a fairly desperate measure to keep <b>some</b> legitimate mail
|
a fairly desperate measure to keep <b>some</b> legitimate mail
|
||||||
|
@ -10,11 +10,20 @@ POSTQUEUE(1) POSTQUEUE(1)
|
|||||||
postqueue - Postfix queue control
|
postqueue - Postfix queue control
|
||||||
|
|
||||||
<b>SYNOPSIS</b>
|
<b>SYNOPSIS</b>
|
||||||
|
<b>To flush the mail queue</b>:
|
||||||
|
|
||||||
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-f</b>
|
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-f</b>
|
||||||
|
|
||||||
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-i</b> <i>queue</i><b>_</b><i>id</i>
|
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-i</b> <i>queue</i><b>_</b><i>id</i>
|
||||||
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-p</b>
|
|
||||||
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-s</b> <i>site</i>
|
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-s</b> <i>site</i>
|
||||||
|
|
||||||
|
<b>To list the mail queue</b>:
|
||||||
|
|
||||||
|
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-j</b>
|
||||||
|
|
||||||
|
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-p</b>
|
||||||
|
|
||||||
<b>DESCRIPTION</b>
|
<b>DESCRIPTION</b>
|
||||||
The <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command implements the Postfix user interface for
|
The <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command implements the Postfix user interface for
|
||||||
queue management. It implements operations that are traditionally
|
queue management. It implements operations that are traditionally
|
||||||
@ -46,6 +55,51 @@ POSTQUEUE(1) POSTQUEUE(1)
|
|||||||
|
|
||||||
This feature is available with Postfix version 2.4 and later.
|
This feature is available with Postfix version 2.4 and later.
|
||||||
|
|
||||||
|
<b>-j</b> Produce a queue listing in JSON format, based on output from the
|
||||||
|
<a href="showq.8.html">showq(8)</a> daemon. The result is a stream of zero or more JSON
|
||||||
|
objects, one per queue file. Each object is followed by a new-
|
||||||
|
line character to support simple streaming parsers.
|
||||||
|
|
||||||
|
Object members have string values unless indicated otherwise.
|
||||||
|
Programs should ignore object members that are not listed here;
|
||||||
|
the list of members is expected to grow over time.
|
||||||
|
|
||||||
|
<b>queue_name</b>
|
||||||
|
The name of the queue where the message was found. Note
|
||||||
|
that the contents of the mail queue may change while it
|
||||||
|
is being listed; some messages may appear more than once,
|
||||||
|
and some messages may be missed.
|
||||||
|
|
||||||
|
<b>queue_id</b>
|
||||||
|
The queue file name. The name may be reused unless
|
||||||
|
"<a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a> = true".
|
||||||
|
|
||||||
|
<b>arrival_time</b>
|
||||||
|
The number of seconds since the start of the UNIX epoch.
|
||||||
|
|
||||||
|
<b>message_size</b>
|
||||||
|
The number of bytes in the message header and body. This
|
||||||
|
number does not include message envelope information. It
|
||||||
|
is approximately equal to the number of bytes that would
|
||||||
|
be transmitted via SMTP including the <CR><LF> line end-
|
||||||
|
ings.
|
||||||
|
|
||||||
|
<b>sender</b> The envelope sender address.
|
||||||
|
|
||||||
|
<b>recipients</b>
|
||||||
|
An array containing zero or more objects with members:
|
||||||
|
|
||||||
|
<b>address</b>
|
||||||
|
One recipient address.
|
||||||
|
|
||||||
|
<b>delay_reason</b>
|
||||||
|
If present, the reason for delayed delivery. Some
|
||||||
|
delayed recipients have no delay reason, for exam-
|
||||||
|
ple, when delivery is in progress or when the sys-
|
||||||
|
tem was stopped before it could record the reason.
|
||||||
|
|
||||||
|
This feature is available in Postfix 3.1 and later.
|
||||||
|
|
||||||
<b>-p</b> Produce a traditional sendmail-style queue listing. This option
|
<b>-p</b> Produce a traditional sendmail-style queue listing. This option
|
||||||
implements the traditional <b>mailq</b> command, by contacting the
|
implements the traditional <b>mailq</b> command, by contacting the
|
||||||
Postfix <a href="showq.8.html"><b>showq</b>(8)</a> daemon.
|
Postfix <a href="showq.8.html"><b>showq</b>(8)</a> daemon.
|
||||||
@ -82,6 +136,9 @@ POSTQUEUE(1) POSTQUEUE(1)
|
|||||||
This program is designed to run with set-group ID privileges, so that
|
This program is designed to run with set-group ID privileges, so that
|
||||||
it can connect to Postfix daemon processes.
|
it can connect to Postfix daemon processes.
|
||||||
|
|
||||||
|
<b>STANDARDS</b>
|
||||||
|
<a href="http://tools.ietf.org/html/rfc7159">RFC 7159</a> (JSON notation)
|
||||||
|
|
||||||
<b>DIAGNOSTICS</b>
|
<b>DIAGNOSTICS</b>
|
||||||
Problems are logged to <b>syslogd</b>(8) and to the standard error stream.
|
Problems are logged to <b>syslogd</b>(8) and to the standard error stream.
|
||||||
|
|
||||||
@ -169,5 +226,10 @@ POSTQUEUE(1) POSTQUEUE(1)
|
|||||||
P.O. Box 704
|
P.O. Box 704
|
||||||
Yorktown Heights, NY 10598, USA
|
Yorktown Heights, NY 10598, USA
|
||||||
|
|
||||||
|
Wietse Venema
|
||||||
|
Google, Inc.
|
||||||
|
111 8th Avenue
|
||||||
|
New York, NY 10011, USA
|
||||||
|
|
||||||
POSTQUEUE(1)
|
POSTQUEUE(1)
|
||||||
</pre> </body> </html>
|
</pre> </body> </html>
|
||||||
|
@ -13,17 +13,18 @@ SHOWQ(8) SHOWQ(8)
|
|||||||
<b>showq</b> [generic Postfix daemon options]
|
<b>showq</b> [generic Postfix daemon options]
|
||||||
|
|
||||||
<b>DESCRIPTION</b>
|
<b>DESCRIPTION</b>
|
||||||
The <a href="showq.8.html"><b>showq</b>(8)</a> daemon reports the Postfix mail queue status. It is the
|
The <a href="showq.8.html"><b>showq</b>(8)</a> daemon reports the Postfix mail queue status. The output
|
||||||
program that emulates the sendmail `mailq' command.
|
is meant to be formatted by the <a href="postqueue.1.html">postqueue(1)</a> command, as it emulates
|
||||||
|
the Sendmail `mailq' command.
|
||||||
|
|
||||||
The <a href="showq.8.html"><b>showq</b>(8)</a> daemon can also be run in stand-alone mode by the supe-
|
The <a href="showq.8.html"><b>showq</b>(8)</a> daemon can also be run in stand-alone mode by the supe-
|
||||||
ruser. This mode of operation is used to emulate the `mailq' command
|
ruser. This mode of operation is used to emulate the `mailq' command
|
||||||
while the Postfix mail system is down.
|
while the Postfix mail system is down.
|
||||||
|
|
||||||
<b>SECURITY</b>
|
<b>SECURITY</b>
|
||||||
The <a href="showq.8.html"><b>showq</b>(8)</a> daemon can run in a chroot jail at fixed low privilege,
|
The <a href="showq.8.html"><b>showq</b>(8)</a> daemon can run in a chroot jail at fixed low privilege,
|
||||||
and takes no input from the client. Its service port is accessible to
|
and takes no input from the client. Its service port is accessible to
|
||||||
local untrusted users, so the service can be susceptible to denial of
|
local untrusted users, so the service can be susceptible to denial of
|
||||||
service attacks.
|
service attacks.
|
||||||
|
|
||||||
<b>STANDARDS</b>
|
<b>STANDARDS</b>
|
||||||
@ -33,19 +34,19 @@ SHOWQ(8) SHOWQ(8)
|
|||||||
Problems and transactions are logged to <b>syslogd</b>(8).
|
Problems and transactions are logged to <b>syslogd</b>(8).
|
||||||
|
|
||||||
<b>CONFIGURATION PARAMETERS</b>
|
<b>CONFIGURATION PARAMETERS</b>
|
||||||
Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="showq.8.html"><b>showq</b>(8)</a> processes
|
Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="showq.8.html"><b>showq</b>(8)</a> processes
|
||||||
run for only a limited amount of time. Use the command "<b>postfix reload</b>"
|
run for only a limited amount of time. Use the command "<b>postfix reload</b>"
|
||||||
to speed up a change.
|
to speed up a change.
|
||||||
|
|
||||||
The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
|
The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
|
||||||
more details including examples.
|
more details including examples.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
|
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
|
||||||
figuration files.
|
figuration files.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
|
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
|
||||||
How much time a Postfix daemon process may take to handle a
|
How much time a Postfix daemon process may take to handle a
|
||||||
request before it is terminated by a built-in watchdog timer.
|
request before it is terminated by a built-in watchdog timer.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
|
<b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
|
||||||
@ -57,11 +58,11 @@ SHOWQ(8) SHOWQ(8)
|
|||||||
The recipient of mail addressed to the null address.
|
The recipient of mail addressed to the null address.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
|
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
|
||||||
The time limit for sending or receiving information over an
|
The time limit for sending or receiving information over an
|
||||||
internal communication channel.
|
internal communication channel.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
|
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
|
||||||
The maximum amount of time that an idle Postfix daemon process
|
The maximum amount of time that an idle Postfix daemon process
|
||||||
waits for an incoming connection before terminating voluntarily.
|
waits for an incoming connection before terminating voluntarily.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
|
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
|
||||||
@ -81,8 +82,8 @@ SHOWQ(8) SHOWQ(8)
|
|||||||
The syslog facility of Postfix logging.
|
The syslog facility of Postfix logging.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
|
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
|
||||||
The mail system name that is prepended to the process name in
|
The mail system name that is prepended to the process name in
|
||||||
syslog records, so that "smtpd" becomes, for example, "post-
|
syslog records, so that "smtpd" becomes, for example, "post-
|
||||||
fix/smtpd".
|
fix/smtpd".
|
||||||
|
|
||||||
Available in Postfix version 2.9 and later:
|
Available in Postfix version 2.9 and later:
|
||||||
@ -110,5 +111,10 @@ SHOWQ(8) SHOWQ(8)
|
|||||||
P.O. Box 704
|
P.O. Box 704
|
||||||
Yorktown Heights, NY 10598, USA
|
Yorktown Heights, NY 10598, USA
|
||||||
|
|
||||||
|
Wietse Venema
|
||||||
|
Google, Inc.
|
||||||
|
111 8th Avenue
|
||||||
|
New York, NY 10011, USA
|
||||||
|
|
||||||
SHOWQ(8)
|
SHOWQ(8)
|
||||||
</pre> </body> </html>
|
</pre> </body> </html>
|
||||||
|
@ -158,6 +158,11 @@
|
|||||||
# IBM T.J. Watson Research
|
# IBM T.J. Watson Research
|
||||||
# P.O. Box 704
|
# P.O. Box 704
|
||||||
# Yorktown Heights, NY 10598, USA
|
# Yorktown Heights, NY 10598, USA
|
||||||
|
#
|
||||||
|
# Wietse Venema
|
||||||
|
# Google, Inc.
|
||||||
|
# 111 8th Avenue
|
||||||
|
# New York, NY 10011, USA
|
||||||
#--
|
#--
|
||||||
|
|
||||||
# Emit system-dependent Makefile macro definitions to standard output.
|
# Emit system-dependent Makefile macro definitions to standard output.
|
||||||
|
@ -8,13 +8,19 @@ Postfix queue control
|
|||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
\fBTo flush the mail queue\fR:
|
||||||
|
|
||||||
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-f\fR
|
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-f\fR
|
||||||
.br
|
|
||||||
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-i \fIqueue_id\fR
|
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-i \fIqueue_id\fR
|
||||||
.br
|
|
||||||
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-p\fR
|
|
||||||
.br
|
|
||||||
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-s \fIsite\fR
|
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-s \fIsite\fR
|
||||||
|
|
||||||
|
\fBTo list the mail queue\fR:
|
||||||
|
|
||||||
|
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-j\fR
|
||||||
|
|
||||||
|
\fBpostqueue\fR [\fB\-v\fR] [\fB\-c \fIconfig_dir\fR] \fB\-p\fR
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
@ -46,6 +52,48 @@ This option implements the traditional \fBsendmail \-qI\fR
|
|||||||
command, by contacting the \fBflush\fR(8) server.
|
command, by contacting the \fBflush\fR(8) server.
|
||||||
|
|
||||||
This feature is available with Postfix version 2.4 and later.
|
This feature is available with Postfix version 2.4 and later.
|
||||||
|
.IP "\fB\-j\fR"
|
||||||
|
Produce a queue listing in JSON format, based on output
|
||||||
|
from the showq(8) daemon. The result is a stream of zero
|
||||||
|
or more JSON objects, one per queue file. Each object is
|
||||||
|
followed by a newline character to support simple streaming
|
||||||
|
parsers.
|
||||||
|
.sp
|
||||||
|
Object members have string values unless indicated otherwise.
|
||||||
|
Programs should ignore object members that are not listed
|
||||||
|
here; the list of members is expected to grow over time.
|
||||||
|
.RS
|
||||||
|
.IP \fBqueue_name\fB
|
||||||
|
The name of the queue where the message was found. Note
|
||||||
|
that the contents of the mail queue may change while it is
|
||||||
|
being listed; some messages may appear more than once, and
|
||||||
|
some messages may be missed.
|
||||||
|
.IP \fBqueue_id\fB
|
||||||
|
The queue file name. The name may be reused unless
|
||||||
|
"enable_long_queue_ids = true".
|
||||||
|
.IP \fBarrival_time\fB
|
||||||
|
The number of seconds since the start of the UNIX epoch.
|
||||||
|
.IP \fBmessage_size\fB
|
||||||
|
The number of bytes in the message header and body. This
|
||||||
|
number does not include message envelope information. It
|
||||||
|
is approximately equal to the number of bytes that would
|
||||||
|
be transmitted via SMTP including the <CR><LF> line endings.
|
||||||
|
.IP \fBsender\fB
|
||||||
|
The envelope sender address.
|
||||||
|
.IP \fBrecipients\fB
|
||||||
|
An array containing zero or more objects with members:
|
||||||
|
.RS
|
||||||
|
.IP \fBaddress\fB
|
||||||
|
One recipient address.
|
||||||
|
.IP \fBdelay_reason\fB
|
||||||
|
If present, the reason for delayed delivery. Some delayed
|
||||||
|
recipients have no delay reason, for example, when delivery
|
||||||
|
is in progress or when the system was stopped before it
|
||||||
|
could record the reason.
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
|
.IP
|
||||||
|
This feature is available in Postfix 3.1 and later.
|
||||||
.IP \fB\-p\fR
|
.IP \fB\-p\fR
|
||||||
Produce a traditional sendmail\-style queue listing.
|
Produce a traditional sendmail\-style queue listing.
|
||||||
This option implements the traditional \fBmailq\fR command,
|
This option implements the traditional \fBmailq\fR command,
|
||||||
@ -85,6 +133,10 @@ this option is available for the super\-user only.
|
|||||||
.fi
|
.fi
|
||||||
This program is designed to run with set\-group ID privileges, so
|
This program is designed to run with set\-group ID privileges, so
|
||||||
that it can connect to Postfix daemon processes.
|
that it can connect to Postfix daemon processes.
|
||||||
|
.SH "STANDARDS"
|
||||||
|
.na
|
||||||
|
.nf
|
||||||
|
RFC 7159 (JSON notation)
|
||||||
.SH DIAGNOSTICS
|
.SH DIAGNOSTICS
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
@ -187,3 +239,8 @@ Wietse Venema
|
|||||||
IBM T.J. Watson Research
|
IBM T.J. Watson Research
|
||||||
P.O. Box 704
|
P.O. Box 704
|
||||||
Yorktown Heights, NY 10598, USA
|
Yorktown Heights, NY 10598, USA
|
||||||
|
|
||||||
|
Wietse Venema
|
||||||
|
Google, Inc.
|
||||||
|
111 8th Avenue
|
||||||
|
New York, NY 10011, USA
|
||||||
|
@ -13,7 +13,8 @@ list the Postfix mail queue
|
|||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
The \fBshowq\fR(8) daemon reports the Postfix mail queue status.
|
The \fBshowq\fR(8) daemon reports the Postfix mail queue status.
|
||||||
It is the program that emulates the sendmail `mailq' command.
|
The output is meant to be formatted by the postqueue(1) command,
|
||||||
|
as it emulates the Sendmail `mailq' command.
|
||||||
|
|
||||||
The \fBshowq\fR(8) daemon can also be run in stand\-alone mode
|
The \fBshowq\fR(8) daemon can also be run in stand\-alone mode
|
||||||
by the superuser. This mode of operation is used to emulate
|
by the superuser. This mode of operation is used to emulate
|
||||||
@ -111,3 +112,8 @@ Wietse Venema
|
|||||||
IBM T.J. Watson Research
|
IBM T.J. Watson Research
|
||||||
P.O. Box 704
|
P.O. Box 704
|
||||||
Yorktown Heights, NY 10598, USA
|
Yorktown Heights, NY 10598, USA
|
||||||
|
|
||||||
|
Wietse Venema
|
||||||
|
Google, Inc.
|
||||||
|
111 8th Avenue
|
||||||
|
New York, NY 10011, USA
|
||||||
|
@ -183,6 +183,11 @@
|
|||||||
# IBM T.J. Watson Research
|
# IBM T.J. Watson Research
|
||||||
# P.O. Box 704
|
# P.O. Box 704
|
||||||
# Yorktown Heights, NY 10598, USA
|
# Yorktown Heights, NY 10598, USA
|
||||||
|
#
|
||||||
|
# Wietse Venema
|
||||||
|
# Google, Inc.
|
||||||
|
# 111 8th Avenue
|
||||||
|
# New York, NY 10011, USA
|
||||||
#--
|
#--
|
||||||
|
|
||||||
# Initialize.
|
# Initialize.
|
||||||
|
@ -168,8 +168,8 @@ default with Postfix 2.6 and later. </p>
|
|||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
<p> With Postfix versions before 3.0, replace ${stress?{x}:{y}}
|
<p> Postfix versions before 3.0 use the older form ${stress?x}${stress:y}
|
||||||
with ${stress?x}${stress:y}. </p>
|
instead of the newer form ${stress?{x}:{y}}. </p>
|
||||||
|
|
||||||
<p> Translation: <p>
|
<p> Translation: <p>
|
||||||
|
|
||||||
@ -219,8 +219,9 @@ as this measure is used only temporarily. </p>
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p> The syntax of ${name?value} and ${name:value} is explained at
|
<p> The syntax of ${name?{value}:{value}}, ${name?value} and
|
||||||
the beginning of the postconf(5) manual page. </p>
|
${name:value} is explained at the beginning of the postconf(5)
|
||||||
|
manual page. </p>
|
||||||
|
|
||||||
<p> NOTE: Please keep in mind that the stress-adaptive feature is
|
<p> NOTE: Please keep in mind that the stress-adaptive feature is
|
||||||
a fairly desperate measure to keep <b>some</b> legitimate mail
|
a fairly desperate measure to keep <b>some</b> legitimate mail
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20151031"
|
#define MAIL_RELEASE_DATE "20151129"
|
||||||
#define MAIL_VERSION_NUMBER "3.1"
|
#define MAIL_VERSION_NUMBER "3.1"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
SRCS = postqueue.c
|
SRCS = postqueue.c showq_compat.c showq_json.c
|
||||||
OBJS = postqueue.o
|
OBJS = postqueue.o showq_compat.o showq_json.o
|
||||||
HDRS =
|
HDRS = postqueue.h
|
||||||
TESTSRC =
|
TESTSRC =
|
||||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||||
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
|
||||||
@ -16,7 +16,7 @@ LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
|
|||||||
$(PROG): $(OBJS) $(LIBS)
|
$(PROG): $(OBJS) $(LIBS)
|
||||||
$(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
|
$(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
|
||||||
|
|
||||||
$(OBJS): ../../conf/makedefs.out
|
$(OBJS): ../../conf/makedefs.out postqueue.h
|
||||||
|
|
||||||
Makefile: Makefile.in
|
Makefile: Makefile.in
|
||||||
cat ../../conf/makedefs.out $? >$@
|
cat ../../conf/makedefs.out $? >$@
|
||||||
@ -84,6 +84,7 @@ postqueue.o: ../../include/mymalloc.h
|
|||||||
postqueue.o: ../../include/nvtable.h
|
postqueue.o: ../../include/nvtable.h
|
||||||
postqueue.o: ../../include/safe.h
|
postqueue.o: ../../include/safe.h
|
||||||
postqueue.o: ../../include/smtp_stream.h
|
postqueue.o: ../../include/smtp_stream.h
|
||||||
|
postqueue.o: ../../include/stringops.h
|
||||||
postqueue.o: ../../include/sys_defs.h
|
postqueue.o: ../../include/sys_defs.h
|
||||||
postqueue.o: ../../include/user_acl.h
|
postqueue.o: ../../include/user_acl.h
|
||||||
postqueue.o: ../../include/valid_hostname.h
|
postqueue.o: ../../include/valid_hostname.h
|
||||||
@ -93,3 +94,40 @@ postqueue.o: ../../include/vstream.h
|
|||||||
postqueue.o: ../../include/vstring.h
|
postqueue.o: ../../include/vstring.h
|
||||||
postqueue.o: ../../include/warn_stat.h
|
postqueue.o: ../../include/warn_stat.h
|
||||||
postqueue.o: postqueue.c
|
postqueue.o: postqueue.c
|
||||||
|
postqueue.o: postqueue.h
|
||||||
|
showq_compat.o: ../../include/attr.h
|
||||||
|
showq_compat.o: ../../include/check_arg.h
|
||||||
|
showq_compat.o: ../../include/htable.h
|
||||||
|
showq_compat.o: ../../include/iostuff.h
|
||||||
|
showq_compat.o: ../../include/mail_date.h
|
||||||
|
showq_compat.o: ../../include/mail_params.h
|
||||||
|
showq_compat.o: ../../include/mail_proto.h
|
||||||
|
showq_compat.o: ../../include/mail_queue.h
|
||||||
|
showq_compat.o: ../../include/msg.h
|
||||||
|
showq_compat.o: ../../include/mymalloc.h
|
||||||
|
showq_compat.o: ../../include/nvtable.h
|
||||||
|
showq_compat.o: ../../include/stringops.h
|
||||||
|
showq_compat.o: ../../include/sys_defs.h
|
||||||
|
showq_compat.o: ../../include/vbuf.h
|
||||||
|
showq_compat.o: ../../include/vstream.h
|
||||||
|
showq_compat.o: ../../include/vstring.h
|
||||||
|
showq_compat.o: postqueue.h
|
||||||
|
showq_compat.o: showq_compat.c
|
||||||
|
showq_json.o: ../../include/attr.h
|
||||||
|
showq_json.o: ../../include/check_arg.h
|
||||||
|
showq_json.o: ../../include/htable.h
|
||||||
|
showq_json.o: ../../include/iostuff.h
|
||||||
|
showq_json.o: ../../include/mail_date.h
|
||||||
|
showq_json.o: ../../include/mail_params.h
|
||||||
|
showq_json.o: ../../include/mail_proto.h
|
||||||
|
showq_json.o: ../../include/mail_queue.h
|
||||||
|
showq_json.o: ../../include/msg.h
|
||||||
|
showq_json.o: ../../include/mymalloc.h
|
||||||
|
showq_json.o: ../../include/nvtable.h
|
||||||
|
showq_json.o: ../../include/stringops.h
|
||||||
|
showq_json.o: ../../include/sys_defs.h
|
||||||
|
showq_json.o: ../../include/vbuf.h
|
||||||
|
showq_json.o: ../../include/vstream.h
|
||||||
|
showq_json.o: ../../include/vstring.h
|
||||||
|
showq_json.o: postqueue.h
|
||||||
|
showq_json.o: showq_json.c
|
||||||
|
@ -4,13 +4,19 @@
|
|||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* Postfix queue control
|
/* Postfix queue control
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
|
/* \fBTo flush the mail queue\fR:
|
||||||
|
/*
|
||||||
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-f\fR
|
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-f\fR
|
||||||
/* .br
|
/*
|
||||||
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-i \fIqueue_id\fR
|
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-i \fIqueue_id\fR
|
||||||
/* .br
|
/*
|
||||||
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-p\fR
|
|
||||||
/* .br
|
|
||||||
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
|
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
|
||||||
|
/*
|
||||||
|
/* \fBTo list the mail queue\fR:
|
||||||
|
/*
|
||||||
|
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-j\fR
|
||||||
|
/*
|
||||||
|
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-p\fR
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* The \fBpostqueue\fR(1) command implements the Postfix user interface
|
/* The \fBpostqueue\fR(1) command implements the Postfix user interface
|
||||||
/* for queue management. It implements operations that are
|
/* for queue management. It implements operations that are
|
||||||
@ -40,6 +46,48 @@
|
|||||||
/* command, by contacting the \fBflush\fR(8) server.
|
/* command, by contacting the \fBflush\fR(8) server.
|
||||||
/*
|
/*
|
||||||
/* This feature is available with Postfix version 2.4 and later.
|
/* This feature is available with Postfix version 2.4 and later.
|
||||||
|
/* .IP "\fB-j\fR"
|
||||||
|
/* Produce a queue listing in JSON format, based on output
|
||||||
|
/* from the showq(8) daemon. The result is a stream of zero
|
||||||
|
/* or more JSON objects, one per queue file. Each object is
|
||||||
|
/* followed by a newline character to support simple streaming
|
||||||
|
/* parsers.
|
||||||
|
/* .sp
|
||||||
|
/* Object members have string values unless indicated otherwise.
|
||||||
|
/* Programs should ignore object members that are not listed
|
||||||
|
/* here; the list of members is expected to grow over time.
|
||||||
|
/* .RS
|
||||||
|
/* .IP \fBqueue_name\fB
|
||||||
|
/* The name of the queue where the message was found. Note
|
||||||
|
/* that the contents of the mail queue may change while it is
|
||||||
|
/* being listed; some messages may appear more than once, and
|
||||||
|
/* some messages may be missed.
|
||||||
|
/* .IP \fBqueue_id\fB
|
||||||
|
/* The queue file name. The name may be reused unless
|
||||||
|
/* "enable_long_queue_ids = true".
|
||||||
|
/* .IP \fBarrival_time\fB
|
||||||
|
/* The number of seconds since the start of the UNIX epoch.
|
||||||
|
/* .IP \fBmessage_size\fB
|
||||||
|
/* The number of bytes in the message header and body. This
|
||||||
|
/* number does not include message envelope information. It
|
||||||
|
/* is approximately equal to the number of bytes that would
|
||||||
|
/* be transmitted via SMTP including the <CR><LF> line endings.
|
||||||
|
/* .IP \fBsender\fB
|
||||||
|
/* The envelope sender address.
|
||||||
|
/* .IP \fBrecipients\fB
|
||||||
|
/* An array containing zero or more objects with members:
|
||||||
|
/* .RS
|
||||||
|
/* .IP \fBaddress\fB
|
||||||
|
/* One recipient address.
|
||||||
|
/* .IP \fBdelay_reason\fB
|
||||||
|
/* If present, the reason for delayed delivery. Some delayed
|
||||||
|
/* recipients have no delay reason, for example, when delivery
|
||||||
|
/* is in progress or when the system was stopped before it
|
||||||
|
/* could record the reason.
|
||||||
|
/* .RE
|
||||||
|
/* .RE
|
||||||
|
/* .IP
|
||||||
|
/* This feature is available in Postfix 3.1 and later.
|
||||||
/* .IP \fB-p\fR
|
/* .IP \fB-p\fR
|
||||||
/* Produce a traditional sendmail-style queue listing.
|
/* Produce a traditional sendmail-style queue listing.
|
||||||
/* This option implements the traditional \fBmailq\fR command,
|
/* This option implements the traditional \fBmailq\fR command,
|
||||||
@ -77,6 +125,8 @@
|
|||||||
/* .fi
|
/* .fi
|
||||||
/* This program is designed to run with set-group ID privileges, so
|
/* This program is designed to run with set-group ID privileges, so
|
||||||
/* that it can connect to Postfix daemon processes.
|
/* that it can connect to Postfix daemon processes.
|
||||||
|
/* STANDARDS
|
||||||
|
/* RFC 7159 (JSON notation)
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* Problems are logged to \fBsyslogd\fR(8) and to the standard error
|
/* Problems are logged to \fBsyslogd\fR(8) and to the standard error
|
||||||
/* stream.
|
/* stream.
|
||||||
@ -161,6 +211,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -188,6 +243,7 @@
|
|||||||
#include <valid_hostname.h>
|
#include <valid_hostname.h>
|
||||||
#include <warn_stat.h>
|
#include <warn_stat.h>
|
||||||
#include <events.h>
|
#include <events.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
@ -208,6 +264,8 @@
|
|||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#include <postqueue.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING WARNING WARNING
|
* WARNING WARNING WARNING
|
||||||
*
|
*
|
||||||
@ -241,6 +299,7 @@
|
|||||||
#define PQ_MODE_FLUSH_QUEUE 2 /* flush queue */
|
#define PQ_MODE_FLUSH_QUEUE 2 /* flush queue */
|
||||||
#define PQ_MODE_FLUSH_SITE 3 /* flush site */
|
#define PQ_MODE_FLUSH_SITE 3 /* flush site */
|
||||||
#define PQ_MODE_FLUSH_FILE 4 /* flush message */
|
#define PQ_MODE_FLUSH_FILE 4 /* flush message */
|
||||||
|
#define PQ_MODE_JSON_LIST 5 /* JSON-format queue listing */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Silly little macros (SLMs).
|
* Silly little macros (SLMs).
|
||||||
@ -261,10 +320,9 @@ static const CONFIG_STR_TABLE str_table[] = {
|
|||||||
|
|
||||||
/* show_queue - show queue status */
|
/* show_queue - show queue status */
|
||||||
|
|
||||||
static void show_queue(void)
|
static void show_queue(int mode)
|
||||||
{
|
{
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
char buf[VSTREAM_BUFSIZE];
|
|
||||||
VSTREAM *showq;
|
VSTREAM *showq;
|
||||||
int n;
|
int n;
|
||||||
uid_t uid = getuid();
|
uid_t uid = getuid();
|
||||||
@ -277,19 +335,20 @@ static void show_queue(void)
|
|||||||
errstr, (long) uid);
|
errstr, (long) uid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connect to the show queue service. Terminate silently when piping into
|
* Connect to the show queue service.
|
||||||
* a program that terminates early.
|
|
||||||
*/
|
*/
|
||||||
if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
|
if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
|
||||||
while ((n = vstream_fread(showq, buf, sizeof(buf))) > 0) {
|
switch (mode) {
|
||||||
if (vstream_fwrite(VSTREAM_OUT, buf, n) != n
|
case PQ_MODE_MAILQ_LIST:
|
||||||
|| vstream_fflush(VSTREAM_OUT) != 0) {
|
showq_compat(showq);
|
||||||
if (errno == EPIPE)
|
break;
|
||||||
break;
|
case PQ_MODE_JSON_LIST:
|
||||||
msg_fatal("write error: %m");
|
showq_json(showq);
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
|
msg_panic("show_queue: unknown mode %d", mode);
|
||||||
}
|
}
|
||||||
if (vstream_fclose(showq) && errno != EPIPE)
|
if (vstream_fclose(showq))
|
||||||
msg_warn("close: %m");
|
msg_warn("close: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,21 +367,40 @@ static void show_queue(void)
|
|||||||
* directly. Just run the showq program in stand-alone mode.
|
* directly. Just run the showq program in stand-alone mode.
|
||||||
*/
|
*/
|
||||||
else if (geteuid() == 0) {
|
else if (geteuid() == 0) {
|
||||||
|
char *showq_path;
|
||||||
ARGV *argv;
|
ARGV *argv;
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
msg_warn("Mail system is down -- accessing queue directly");
|
msg_warn("Mail system is down -- accessing queue directly");
|
||||||
|
showq_path = concatenate(var_daemon_dir, "/", var_showq_service,
|
||||||
|
(char *) 0);
|
||||||
argv = argv_alloc(6);
|
argv = argv_alloc(6);
|
||||||
argv_add(argv, var_showq_service, "-u", "-S", (char *) 0);
|
argv_add(argv, showq_path, "-u", "-S", (char *) 0);
|
||||||
for (n = 0; n < msg_verbose; n++)
|
for (n = 0; n < msg_verbose; n++)
|
||||||
argv_add(argv, "-v", (char *) 0);
|
argv_add(argv, "-v", (char *) 0);
|
||||||
argv_terminate(argv);
|
argv_terminate(argv);
|
||||||
stat = mail_run_foreground(var_daemon_dir, argv->argv);
|
if ((showq = vstream_popen(O_RDONLY,
|
||||||
|
CA_VSTREAM_POPEN_ARGV(argv->argv),
|
||||||
|
CA_VSTREAM_POPEN_END)) == 0) {
|
||||||
|
stat = -1;
|
||||||
|
} else {
|
||||||
|
switch (mode) {
|
||||||
|
case PQ_MODE_MAILQ_LIST:
|
||||||
|
showq_compat(showq);
|
||||||
|
break;
|
||||||
|
case PQ_MODE_JSON_LIST:
|
||||||
|
showq_json(showq);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg_panic("show_queue: unknown mode %d", mode);
|
||||||
|
}
|
||||||
|
stat = vstream_pclose(showq);
|
||||||
|
}
|
||||||
argv_free(argv);
|
argv_free(argv);
|
||||||
if (stat != 0)
|
if (stat != 0)
|
||||||
msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
|
msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
|
||||||
"Error running %s/%s",
|
"Error running %s", showq_path);
|
||||||
var_daemon_dir, argv->argv[0]);
|
myfree(showq_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -500,7 +578,7 @@ int main(int argc, char **argv)
|
|||||||
* mail configuration read routine. Don't do complex things until we have
|
* mail configuration read routine. Don't do complex things until we have
|
||||||
* completed initializations.
|
* completed initializations.
|
||||||
*/
|
*/
|
||||||
while ((c = GETOPT(argc, argv, "c:fi:ps:v")) > 0) {
|
while ((c = GETOPT(argc, argv, "c:fi:jps:v")) > 0) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'c': /* non-default configuration */
|
case 'c': /* non-default configuration */
|
||||||
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
|
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
|
||||||
@ -517,6 +595,11 @@ int main(int argc, char **argv)
|
|||||||
mode = PQ_MODE_FLUSH_FILE;
|
mode = PQ_MODE_FLUSH_FILE;
|
||||||
id_to_flush = optarg;
|
id_to_flush = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'j':
|
||||||
|
if (mode != PQ_MODE_DEFAULT)
|
||||||
|
usage();
|
||||||
|
mode = PQ_MODE_JSON_LIST;
|
||||||
|
break;
|
||||||
case 'p': /* traditional mailq */
|
case 'p': /* traditional mailq */
|
||||||
if (mode != PQ_MODE_DEFAULT)
|
if (mode != PQ_MODE_DEFAULT)
|
||||||
usage();
|
usage();
|
||||||
@ -597,7 +680,8 @@ int main(int argc, char **argv)
|
|||||||
msg_panic("unknown operation mode: %d", mode);
|
msg_panic("unknown operation mode: %d", mode);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case PQ_MODE_MAILQ_LIST:
|
case PQ_MODE_MAILQ_LIST:
|
||||||
show_queue();
|
case PQ_MODE_JSON_LIST:
|
||||||
|
show_queue(mode);
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
case PQ_MODE_FLUSH_SITE:
|
case PQ_MODE_FLUSH_SITE:
|
||||||
|
35
postfix/src/postqueue/postqueue.h
Normal file
35
postfix/src/postqueue/postqueue.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* postqueue 5h
|
||||||
|
/* SUMMARY
|
||||||
|
/* postqueue internal interfaces
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <postqueue.h>
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* .nf
|
||||||
|
|
||||||
|
/*
|
||||||
|
* showq_compat.c
|
||||||
|
*/
|
||||||
|
extern void showq_compat(VSTREAM *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* showq_json.c
|
||||||
|
*/
|
||||||
|
extern void showq_json(VSTREAM *);
|
||||||
|
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
|
/*--*/
|
209
postfix/src/postqueue/showq_compat.c
Normal file
209
postfix/src/postqueue/showq_compat.c
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* showq_compat 8
|
||||||
|
/* SUMMARY
|
||||||
|
/* Sendmail mailq compatibitily adapter
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* void showq_compat(
|
||||||
|
/* VSTREAM *showq)
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* This function converts a record stream from the showq(8)
|
||||||
|
/* daemon to of an approximation of Sendmail mailq command
|
||||||
|
/* output.
|
||||||
|
/* DIAGNOSTICS
|
||||||
|
/* Fatal errors: out of memory, malformed showq(8) daemon output.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <vstring.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <msg.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <mail_proto.h>
|
||||||
|
#include <mail_queue.h>
|
||||||
|
#include <mail_date.h>
|
||||||
|
#include <mail_params.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#include <postqueue.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The enable_long_queue_ids parameter determines the output format.
|
||||||
|
*
|
||||||
|
* The historical output format for short queue IDs (inode number and time in
|
||||||
|
* microseconds modulo 1) is not suitable for large inode numbers, but we
|
||||||
|
* won't change it to avoid breaking compatibility with programs that parse
|
||||||
|
* this output.
|
||||||
|
*/
|
||||||
|
#define S_STRING_FORMAT "%-11s %7s %-20s %s\n"
|
||||||
|
#define S_SENDER_FORMAT "%-11s %7ld %20.20s %s\n"
|
||||||
|
#define S_HEADINGS "-Queue ID-", "--Size--", \
|
||||||
|
"----Arrival Time----", "-Sender/Recipient-------"
|
||||||
|
|
||||||
|
#define L_STRING_FORMAT "%-17s %8s %-19s %s\n"
|
||||||
|
#define L_SENDER_FORMAT "%-17s %8ld %19.19s %s\n"
|
||||||
|
#define L_HEADINGS "----Queue ID-----", "--Size--", \
|
||||||
|
"---Arrival Time----", "--Sender/Recipient------"
|
||||||
|
|
||||||
|
#define STR(x) vstring_str(x)
|
||||||
|
|
||||||
|
/* showq_message - report status for one message */
|
||||||
|
|
||||||
|
static unsigned long showq_message(VSTREAM *showq_stream)
|
||||||
|
{
|
||||||
|
static VSTRING *queue_name = 0;
|
||||||
|
static VSTRING *queue_id = 0;
|
||||||
|
static VSTRING *id_status = 0;
|
||||||
|
static VSTRING *addr = 0;
|
||||||
|
static VSTRING *why = 0;
|
||||||
|
long arrival_time;
|
||||||
|
long message_size;
|
||||||
|
int message_status;
|
||||||
|
char *saved_reason = mystrdup("");
|
||||||
|
const char *show_reason;
|
||||||
|
int padding;
|
||||||
|
int showq_status;
|
||||||
|
time_t time_t_arrival_time;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One-time initialization.
|
||||||
|
*/
|
||||||
|
if (queue_name == 0) {
|
||||||
|
queue_name = vstring_alloc(100);
|
||||||
|
queue_id = vstring_alloc(100);
|
||||||
|
id_status = vstring_alloc(100);
|
||||||
|
addr = vstring_alloc(100);
|
||||||
|
why = vstring_alloc(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the message properties and sender address.
|
||||||
|
*/
|
||||||
|
if (attr_scan(showq_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name),
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
|
||||||
|
RECV_ATTR_LONG(MAIL_ATTR_TIME, &arrival_time),
|
||||||
|
RECV_ATTR_LONG(MAIL_ATTR_SIZE, &message_size),
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_SENDER, addr),
|
||||||
|
ATTR_TYPE_END) != 5)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decorate queue file names in specific states, then print the result
|
||||||
|
* left-aligned, followed by other status info and the sender address
|
||||||
|
* which is already in externalized RFC 5321 form.
|
||||||
|
*/
|
||||||
|
message_status = (strcmp(STR(queue_name), MAIL_QUEUE_ACTIVE) == 0 ? '*' :
|
||||||
|
strcmp(STR(queue_name), MAIL_QUEUE_HOLD) == 0 ? '!' : ' ');
|
||||||
|
vstring_sprintf(id_status, "%s%c", STR(queue_id), message_status);
|
||||||
|
time_t_arrival_time = arrival_time;
|
||||||
|
vstream_printf(var_long_queue_ids ?
|
||||||
|
L_SENDER_FORMAT : S_SENDER_FORMAT, STR(id_status),
|
||||||
|
message_size, asctime(localtime(&time_t_arrival_time)),
|
||||||
|
STR(addr));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read zero or more (recipient, reason) pair(s) until attr_scan_more()
|
||||||
|
* consumes a terminator. If the showq daemon messes up, don't try to
|
||||||
|
* resynchronize.
|
||||||
|
*/
|
||||||
|
while ((showq_status = attr_scan_more(showq_stream)) > 0) {
|
||||||
|
if (attr_scan(showq_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_RECIP, addr),
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_WHY, why),
|
||||||
|
ATTR_TYPE_END) != 2)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't output a "(reason)" line when no recipient has a reason, or
|
||||||
|
* when the previous recipient has the same (non)reason as the
|
||||||
|
* current recipient. Do output a "(reason unavailable)" when the
|
||||||
|
* previous recipient has a reason, and the current recipient has
|
||||||
|
* none.
|
||||||
|
*/
|
||||||
|
if (strcmp(saved_reason, STR(why)) != 0) {
|
||||||
|
myfree(saved_reason);
|
||||||
|
saved_reason = mystrdup(STR(why));
|
||||||
|
show_reason = *saved_reason ? saved_reason : "reason unavailable";
|
||||||
|
if ((padding = 76 - strlen(show_reason)) < 0)
|
||||||
|
padding = 0;
|
||||||
|
vstream_printf("%*s(%s)\n", padding, "", show_reason);
|
||||||
|
}
|
||||||
|
vstream_printf(var_long_queue_ids ?
|
||||||
|
L_STRING_FORMAT : S_STRING_FORMAT,
|
||||||
|
"", "", "", STR(addr));
|
||||||
|
}
|
||||||
|
if (showq_status < 0)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
myfree(saved_reason);
|
||||||
|
return (message_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* showq_compat - legacy mailq-style output adapter */
|
||||||
|
|
||||||
|
void showq_compat(VSTREAM *showq_stream)
|
||||||
|
{
|
||||||
|
unsigned long file_count = 0;
|
||||||
|
unsigned long queue_size = 0;
|
||||||
|
int showq_status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process zero or more queue file objects until attr_scan_more()
|
||||||
|
* consumes a terminator.
|
||||||
|
*/
|
||||||
|
while ((showq_status = attr_scan_more(showq_stream)) > 0) {
|
||||||
|
if (file_count > 0) {
|
||||||
|
vstream_printf("\n");
|
||||||
|
} else if (var_long_queue_ids) {
|
||||||
|
vstream_printf(L_STRING_FORMAT, L_HEADINGS);
|
||||||
|
} else {
|
||||||
|
vstream_printf(S_STRING_FORMAT, S_HEADINGS);
|
||||||
|
}
|
||||||
|
queue_size += showq_message(showq_stream);
|
||||||
|
file_count++;
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
}
|
||||||
|
if (showq_status < 0)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print the queue summary.
|
||||||
|
*/
|
||||||
|
if (file_count == 0)
|
||||||
|
vstream_printf("Mail queue is empty\n");
|
||||||
|
else {
|
||||||
|
vstream_printf("\n-- %lu Kbytes in %lu Request%s.\n",
|
||||||
|
queue_size / 1024, file_count,
|
||||||
|
file_count == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
}
|
213
postfix/src/postqueue/showq_json.c
Normal file
213
postfix/src/postqueue/showq_json.c
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* showq_json 8
|
||||||
|
/* SUMMARY
|
||||||
|
/* JSON queue status formatter
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* void showq_json(
|
||||||
|
/* VSTREAM *showq)
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* This function converts showq(8) daemon output to JSON format.
|
||||||
|
/* DIAGNOSTICS
|
||||||
|
/* Fatal errors: out of memory, malformed showq(8) daemon output.
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <vstring.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <stringops.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <msg.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <mail_proto.h>
|
||||||
|
#include <mail_queue.h>
|
||||||
|
#include <mail_date.h>
|
||||||
|
#include <mail_params.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#include <postqueue.h>
|
||||||
|
|
||||||
|
#define STR(x) vstring_str(x)
|
||||||
|
#define LEN(x) VSTRING_LEN(x)
|
||||||
|
|
||||||
|
/* json_quote - quote JSON string */
|
||||||
|
|
||||||
|
static char *json_quote(VSTRING *result, const char *text)
|
||||||
|
{
|
||||||
|
unsigned char *cp;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use short escape sequences for common control characters. Note that
|
||||||
|
* RFC 4627 allows "/" (0x2F) to be sent without quoting. Differences
|
||||||
|
* with RFC 4627: we send DEL (0x7f) as \u007F; the result remains RFC
|
||||||
|
* 4627 complaint.
|
||||||
|
*/
|
||||||
|
VSTRING_RESET(result);
|
||||||
|
for (cp = (unsigned char *) text; (ch = *cp) != 0; cp++) {
|
||||||
|
if (UNEXPECTED(ISCNTRL(ch))) {
|
||||||
|
switch (ch) {
|
||||||
|
case '\b':
|
||||||
|
VSTRING_ADDCH(result, '\\');
|
||||||
|
VSTRING_ADDCH(result, 'b');
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
VSTRING_ADDCH(result, '\\');
|
||||||
|
VSTRING_ADDCH(result, 'f');
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
VSTRING_ADDCH(result, '\\');
|
||||||
|
VSTRING_ADDCH(result, 'n');
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
VSTRING_ADDCH(result, '\\');
|
||||||
|
VSTRING_ADDCH(result, 'r');
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
VSTRING_ADDCH(result, '\\');
|
||||||
|
VSTRING_ADDCH(result, 't');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vstring_sprintf(result, "\\u%04X", ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (ch) {
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
VSTRING_ADDCH(result, '\\');
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
default:
|
||||||
|
VSTRING_ADDCH(result, ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VSTRING_TERMINATE(result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force the result to be UTF-8 (with SMTPUTF8 enabled) or ASCII (with
|
||||||
|
* SMTPUTF8 disabled).
|
||||||
|
*/
|
||||||
|
printable(STR(result), '?');
|
||||||
|
return (STR(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* json_message - report status for one message */
|
||||||
|
|
||||||
|
static void format_json(VSTREAM *showq_stream)
|
||||||
|
{
|
||||||
|
static VSTRING *queue_name = 0;
|
||||||
|
static VSTRING *queue_id = 0;
|
||||||
|
static VSTRING *addr = 0;
|
||||||
|
static VSTRING *why = 0;
|
||||||
|
static VSTRING *quote_buf = 0;
|
||||||
|
long arrival_time;
|
||||||
|
long message_size;
|
||||||
|
int showq_status;
|
||||||
|
int rcpt_count = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One-time initialization.
|
||||||
|
*/
|
||||||
|
if (queue_name == 0) {
|
||||||
|
queue_name = vstring_alloc(100);
|
||||||
|
queue_id = vstring_alloc(100);
|
||||||
|
addr = vstring_alloc(100);
|
||||||
|
why = vstring_alloc(100);
|
||||||
|
quote_buf = vstring_alloc(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the message properties and sender address.
|
||||||
|
*/
|
||||||
|
if (attr_scan(showq_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name),
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
|
||||||
|
RECV_ATTR_LONG(MAIL_ATTR_TIME, &arrival_time),
|
||||||
|
RECV_ATTR_LONG(MAIL_ATTR_SIZE, &message_size),
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_SENDER, addr),
|
||||||
|
ATTR_TYPE_END) != 5)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
vstream_printf("{");
|
||||||
|
vstream_printf("\"queue_name\": \"%s\",",
|
||||||
|
json_quote(quote_buf, STR(queue_name)));
|
||||||
|
vstream_printf("\"queue_id\": \"%s\",",
|
||||||
|
json_quote(quote_buf, STR(queue_id)));
|
||||||
|
vstream_printf("\"arrival_time\": %ld,", arrival_time);
|
||||||
|
vstream_printf("\"message_size\": %ld,", message_size);
|
||||||
|
vstream_printf("\"sender\": \"%s\",",
|
||||||
|
json_quote(quote_buf, STR(addr)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read zero or more (recipient, reason) pair(s) until attr_scan_more()
|
||||||
|
* consumes a terminator. If the showq daemon messes up, don't try to
|
||||||
|
* resynchronize.
|
||||||
|
*/
|
||||||
|
vstream_printf("\"recipients\": [");
|
||||||
|
for (rcpt_count = 0; (showq_status = attr_scan_more(showq_stream)) > 0; rcpt_count++) {
|
||||||
|
if (rcpt_count > 0)
|
||||||
|
vstream_printf(",");
|
||||||
|
vstream_printf("{");
|
||||||
|
if (attr_scan(showq_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_RECIP, addr),
|
||||||
|
RECV_ATTR_STR(MAIL_ATTR_WHY, why),
|
||||||
|
ATTR_TYPE_END) != 2)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
vstream_printf("\"address\": \"%s\"",
|
||||||
|
json_quote(quote_buf, STR(addr)));
|
||||||
|
if (LEN(why) > 0)
|
||||||
|
vstream_printf(",\"delay_reason\": \"%s\",",
|
||||||
|
json_quote(quote_buf, STR(why)));
|
||||||
|
vstream_printf("}");
|
||||||
|
}
|
||||||
|
vstream_printf("]");
|
||||||
|
if (showq_status < 0)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
vstream_printf("}\n");
|
||||||
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* showq_json - streaming JSON-format output adapter */
|
||||||
|
|
||||||
|
void showq_json(VSTREAM *showq_stream)
|
||||||
|
{
|
||||||
|
int showq_status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit zero or more queue file objects until attr_scan_more()
|
||||||
|
* consumes a terminator.
|
||||||
|
*/
|
||||||
|
while ((showq_status = attr_scan_more(showq_stream)) > 0) {
|
||||||
|
format_json(showq_stream);
|
||||||
|
}
|
||||||
|
if (showq_status < 0)
|
||||||
|
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
|
||||||
|
}
|
@ -7,7 +7,8 @@
|
|||||||
/* \fBshowq\fR [generic Postfix daemon options]
|
/* \fBshowq\fR [generic Postfix daemon options]
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* The \fBshowq\fR(8) daemon reports the Postfix mail queue status.
|
/* The \fBshowq\fR(8) daemon reports the Postfix mail queue status.
|
||||||
/* It is the program that emulates the sendmail `mailq' command.
|
/* The output is meant to be formatted by the postqueue(1) command,
|
||||||
|
/* as it emulates the Sendmail `mailq' command.
|
||||||
/*
|
/*
|
||||||
/* The \fBshowq\fR(8) daemon can also be run in stand-alone mode
|
/* The \fBshowq\fR(8) daemon can also be run in stand-alone mode
|
||||||
/* by the superuser. This mode of operation is used to emulate
|
/* by the superuser. This mode of operation is used to emulate
|
||||||
@ -89,6 +90,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -140,18 +146,6 @@
|
|||||||
int var_dup_filter_limit;
|
int var_dup_filter_limit;
|
||||||
char *var_empty_addr;
|
char *var_empty_addr;
|
||||||
|
|
||||||
#define S_STRING_FORMAT "%-10s %8s %-20s %s\n"
|
|
||||||
#define S_SENDER_FORMAT "%-11s %7ld %20.20s %s\n"
|
|
||||||
#define S_DROP_FORMAT "%-10s%c %7ld %20.20s (maildrop queue, sender UID %u)\n"
|
|
||||||
#define S_HEADINGS "-Queue ID-", "--Size--", \
|
|
||||||
"----Arrival Time----", "-Sender/Recipient-------"
|
|
||||||
|
|
||||||
#define L_STRING_FORMAT "%-17s %8s %-19s %s\n"
|
|
||||||
#define L_SENDER_FORMAT "%-17s %8ld %19.19s %s\n"
|
|
||||||
#define L_DROP_FORMAT "%-16s%c %8ld %19.19s (maildrop queue, sender UID %u)\n"
|
|
||||||
#define L_HEADINGS "----Queue ID-----", "--Size--", \
|
|
||||||
"---Arrival Time----", "--Sender/Recipient------"
|
|
||||||
|
|
||||||
static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *,
|
static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *,
|
||||||
HTABLE *);
|
HTABLE *);
|
||||||
|
|
||||||
@ -167,15 +161,30 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||||||
int rec_type;
|
int rec_type;
|
||||||
time_t arrival_time = 0;
|
time_t arrival_time = 0;
|
||||||
char *start;
|
char *start;
|
||||||
long msg_size = 0;
|
long msg_size = size;
|
||||||
BOUNCE_LOG *logfile;
|
BOUNCE_LOG *logfile;
|
||||||
HTABLE *dup_filter = 0;
|
HTABLE *dup_filter = 0;
|
||||||
RCPT_BUF *rcpt_buf = 0;
|
RCPT_BUF *rcpt_buf = 0;
|
||||||
DSN_BUF *dsn_buf = 0;
|
DSN_BUF *dsn_buf = 0;
|
||||||
char status = (strcmp(queue, MAIL_QUEUE_ACTIVE) == 0 ? '*' :
|
int sender_seen = 0;
|
||||||
strcmp(queue, MAIL_QUEUE_HOLD) == 0 ? '!' : ' ');
|
|
||||||
int msg_size_ok = 0;
|
int msg_size_ok = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let the optimizer worry about eliminating duplicate code.
|
||||||
|
*/
|
||||||
|
#define SHOWQ_CLEANUP_AND_RETURN { \
|
||||||
|
if (sender_seen > 0) \
|
||||||
|
attr_print(client, ATTR_FLAG_NONE, ATTR_TYPE_END); \
|
||||||
|
vstring_free(buf); \
|
||||||
|
vstring_free(printable_quoted_addr); \
|
||||||
|
if (rcpt_buf) \
|
||||||
|
rcpb_free(rcpt_buf); \
|
||||||
|
if (dsn_buf) \
|
||||||
|
dsb_free(dsn_buf); \
|
||||||
|
if (dup_filter) \
|
||||||
|
htable_free(dup_filter, (void (*) (void *)) 0); \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX addresses in defer logfiles are in printable quoted form, while
|
* XXX addresses in defer logfiles are in printable quoted form, while
|
||||||
* addresses in message envelope records are in raw unquoted form. This
|
* addresses in message envelope records are in raw unquoted form. This
|
||||||
@ -192,12 +201,16 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||||||
msg_info("record %c %s", rec_type, printable(start, '?'));
|
msg_info("record %c %s", rec_type, printable(start, '?'));
|
||||||
switch (rec_type) {
|
switch (rec_type) {
|
||||||
case REC_TYPE_TIME:
|
case REC_TYPE_TIME:
|
||||||
arrival_time = atol(start);
|
/* TODO: parse seconds and microseconds. */
|
||||||
|
if (arrival_time == 0)
|
||||||
|
arrival_time = atol(start);
|
||||||
break;
|
break;
|
||||||
case REC_TYPE_SIZE:
|
case REC_TYPE_SIZE:
|
||||||
if (msg_size == 0) {
|
if (msg_size_ok == 0) {
|
||||||
if ((msg_size_ok = ((msg_size = atol(start)) > 0)) == 0) {
|
msg_size_ok = (alldig(start) && (msg_size = atol(start)) >= 0);
|
||||||
msg_warn("%s: malformed size record: %.100s",
|
if (msg_size_ok == 0) {
|
||||||
|
msg_warn("%s: malformed size record: %.100s "
|
||||||
|
"-- using file size instead",
|
||||||
id, printable(start, '?'));
|
id, printable(start, '?'));
|
||||||
msg_size = size;
|
msg_size = size;
|
||||||
}
|
}
|
||||||
@ -208,25 +221,40 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||||||
start = var_empty_addr;
|
start = var_empty_addr;
|
||||||
quote_822_local(printable_quoted_addr, start);
|
quote_822_local(printable_quoted_addr, start);
|
||||||
printable(STR(printable_quoted_addr), '?');
|
printable(STR(printable_quoted_addr), '?');
|
||||||
/* quote_822_local() saves buf, so we can reuse its space. */
|
if (sender_seen++ > 0) {
|
||||||
vstring_sprintf(buf, "%s%c", id, status);
|
msg_warn("%s: duplicate sender address: %s "
|
||||||
vstream_fprintf(client, var_long_queue_ids ?
|
"-- skipping remainder of this file",
|
||||||
L_SENDER_FORMAT : S_SENDER_FORMAT, STR(buf),
|
id, STR(printable_quoted_addr));
|
||||||
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
|
SHOWQ_CLEANUP_AND_RETURN;
|
||||||
asctime(localtime(&arrival_time)) :
|
}
|
||||||
asctime(localtime(&mtime)),
|
attr_print(client, ATTR_FLAG_MORE,
|
||||||
STR(printable_quoted_addr));
|
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
|
||||||
|
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
|
||||||
|
SEND_ATTR_LONG(MAIL_ATTR_TIME, arrival_time > 0 ?
|
||||||
|
arrival_time : mtime),
|
||||||
|
SEND_ATTR_LONG(MAIL_ATTR_SIZE, msg_size),
|
||||||
|
SEND_ATTR_STR(MAIL_ATTR_SENDER,
|
||||||
|
STR(printable_quoted_addr)),
|
||||||
|
ATTR_TYPE_END);
|
||||||
break;
|
break;
|
||||||
case REC_TYPE_RCPT:
|
case REC_TYPE_RCPT:
|
||||||
|
if (sender_seen == 0) {
|
||||||
|
msg_warn("%s: missing sender address: %s "
|
||||||
|
"-- skipping remainder of this file",
|
||||||
|
id, STR(printable_quoted_addr));
|
||||||
|
SHOWQ_CLEANUP_AND_RETURN;
|
||||||
|
}
|
||||||
if (*start == 0) /* can't happen? */
|
if (*start == 0) /* can't happen? */
|
||||||
start = var_empty_addr;
|
start = var_empty_addr;
|
||||||
quote_822_local(printable_quoted_addr, start);
|
quote_822_local(printable_quoted_addr, start);
|
||||||
printable(STR(printable_quoted_addr), '?');
|
printable(STR(printable_quoted_addr), '?');
|
||||||
if (dup_filter == 0
|
if (dup_filter == 0
|
||||||
|| htable_locate(dup_filter, STR(printable_quoted_addr)) == 0)
|
|| htable_locate(dup_filter, STR(printable_quoted_addr)) == 0)
|
||||||
vstream_fprintf(client, var_long_queue_ids ?
|
attr_print(client, ATTR_FLAG_MORE,
|
||||||
L_STRING_FORMAT : S_STRING_FORMAT,
|
SEND_ATTR_STR(MAIL_ATTR_RECIP,
|
||||||
"", "", "", STR(printable_quoted_addr));
|
STR(printable_quoted_addr)),
|
||||||
|
SEND_ATTR_STR(MAIL_ATTR_WHY, ""),
|
||||||
|
ATTR_TYPE_END);
|
||||||
break;
|
break;
|
||||||
case REC_TYPE_MESG:
|
case REC_TYPE_MESG:
|
||||||
if (msg_size_ok && vstream_fseek(qfile, msg_size, SEEK_CUR) < 0)
|
if (msg_size_ok && vstream_fseek(qfile, msg_size, SEEK_CUR) < 0)
|
||||||
@ -237,18 +265,22 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* With the heading printed, see if there is a defer logfile. The
|
* Before listing any recipients from the queue file, try to list
|
||||||
* defer logfile is not necessarily complete: delivery may be
|
* recipients from the corresponding defer logfile with per-recipient
|
||||||
|
* descriptions why delivery was deferred.
|
||||||
|
*
|
||||||
|
* The defer logfile is not necessarily complete: delivery may be
|
||||||
* interrupted (postfix stop or reload) before all recipients have
|
* interrupted (postfix stop or reload) before all recipients have
|
||||||
* been tried.
|
* been tried.
|
||||||
*
|
*
|
||||||
* Therefore we keep a record of recipients found in the defer logfile,
|
* Therefore we keep a record of recipients found in the defer logfile,
|
||||||
* and try to avoid listing those recipients again when processing
|
* and try to avoid listing those recipients again when processing
|
||||||
* the remainder of the queue file.
|
* recipients from the queue file.
|
||||||
*/
|
*/
|
||||||
if (rec_type == REC_TYPE_FROM
|
if (rec_type == REC_TYPE_FROM
|
||||||
&& dup_filter == 0
|
|
||||||
&& (logfile = bounce_log_open(MAIL_QUEUE_DEFER, id, O_RDONLY, 0)) != 0) {
|
&& (logfile = bounce_log_open(MAIL_QUEUE_DEFER, id, O_RDONLY, 0)) != 0) {
|
||||||
|
if (dup_filter != 0)
|
||||||
|
msg_panic("showq_report: attempt to reuse duplicate filter");
|
||||||
dup_filter = htable_create(var_dup_filter_limit);
|
dup_filter = htable_create(var_dup_filter_limit);
|
||||||
if (rcpt_buf == 0)
|
if (rcpt_buf == 0)
|
||||||
rcpt_buf = rcpb_create();
|
rcpt_buf = rcpb_create();
|
||||||
@ -259,14 +291,7 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||||||
msg_warn("close %s %s: %m", MAIL_QUEUE_DEFER, id);
|
msg_warn("close %s %s: %m", MAIL_QUEUE_DEFER, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vstring_free(buf);
|
SHOWQ_CLEANUP_AND_RETURN;
|
||||||
vstring_free(printable_quoted_addr);
|
|
||||||
if (rcpt_buf)
|
|
||||||
rcpb_free(rcpt_buf);
|
|
||||||
if (dsn_buf)
|
|
||||||
dsb_free(dsn_buf);
|
|
||||||
if (dup_filter)
|
|
||||||
htable_free(dup_filter, (void (*) (void *)) 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* showq_reasons - show deferral reasons */
|
/* showq_reasons - show deferral reasons */
|
||||||
@ -274,8 +299,6 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||||||
static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
|
static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
|
||||||
DSN_BUF *dsn_buf, HTABLE *dup_filter)
|
DSN_BUF *dsn_buf, HTABLE *dup_filter)
|
||||||
{
|
{
|
||||||
char *saved_reason = 0;
|
|
||||||
int padding;
|
|
||||||
RECIPIENT *rcpt = &rcpt_buf->rcpt;
|
RECIPIENT *rcpt = &rcpt_buf->rcpt;
|
||||||
DSN *dsn = &dsn_buf->dsn;
|
DSN *dsn = &dsn_buf->dsn;
|
||||||
|
|
||||||
@ -289,23 +312,11 @@ static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
|
|||||||
if (htable_locate(dup_filter, rcpt->address) == 0)
|
if (htable_locate(dup_filter, rcpt->address) == 0)
|
||||||
htable_enter(dup_filter, rcpt->address, (void *) 0);
|
htable_enter(dup_filter, rcpt->address, (void *) 0);
|
||||||
|
|
||||||
/*
|
attr_print(client, ATTR_FLAG_MORE,
|
||||||
* Don't print the reason when the previous recipient had the same
|
SEND_ATTR_STR(MAIL_ATTR_RECIP, rcpt->address),
|
||||||
* problem.
|
SEND_ATTR_STR(MAIL_ATTR_WHY, dsn->reason),
|
||||||
*/
|
ATTR_TYPE_END);
|
||||||
if (saved_reason == 0 || strcmp(saved_reason, dsn->reason) != 0) {
|
|
||||||
if (saved_reason)
|
|
||||||
myfree(saved_reason);
|
|
||||||
saved_reason = mystrdup(dsn->reason);
|
|
||||||
if ((padding = 76 - strlen(saved_reason)) < 0)
|
|
||||||
padding = 0;
|
|
||||||
vstream_fprintf(client, "%*s(%s)\n", padding, "", saved_reason);
|
|
||||||
}
|
|
||||||
vstream_fprintf(client, var_long_queue_ids ? L_STRING_FORMAT :
|
|
||||||
S_STRING_FORMAT, "", "", "", rcpt->address);
|
|
||||||
}
|
}
|
||||||
if (saved_reason)
|
|
||||||
myfree(saved_reason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -318,7 +329,6 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
|
|||||||
int status;
|
int status;
|
||||||
char *id;
|
char *id;
|
||||||
int file_count;
|
int file_count;
|
||||||
unsigned long queue_size = 0;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct queue_info {
|
struct queue_info {
|
||||||
char *name; /* queue name */
|
char *name; /* queue name */
|
||||||
@ -368,30 +378,14 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
|
|||||||
saved_id = mystrdup(id);
|
saved_id = mystrdup(id);
|
||||||
status = mail_open_ok(qp->name, id, &st, &path);
|
status = mail_open_ok(qp->name, id, &st, &path);
|
||||||
if (status == MAIL_OPEN_YES) {
|
if (status == MAIL_OPEN_YES) {
|
||||||
if (file_count == 0) {
|
|
||||||
if (var_long_queue_ids)
|
|
||||||
vstream_fprintf(client, L_STRING_FORMAT, L_HEADINGS);
|
|
||||||
else
|
|
||||||
vstream_fprintf(client, S_STRING_FORMAT, S_HEADINGS);
|
|
||||||
} else
|
|
||||||
vstream_fprintf(client, "\n");
|
|
||||||
if ((qfile = mail_queue_open(qp->name, id, O_RDONLY, 0)) != 0) {
|
if ((qfile = mail_queue_open(qp->name, id, O_RDONLY, 0)) != 0) {
|
||||||
queue_size += st.st_size;
|
|
||||||
showq_report(client, qp->name, id, qfile, (long) st.st_size,
|
showq_report(client, qp->name, id, qfile, (long) st.st_size,
|
||||||
st.st_mtime);
|
st.st_mtime);
|
||||||
if (vstream_fclose(qfile))
|
if (vstream_fclose(qfile))
|
||||||
msg_warn("close file %s %s: %m", qp->name, id);
|
msg_warn("close file %s %s: %m", qp->name, id);
|
||||||
} else if (strcmp(qp->name, MAIL_QUEUE_MAILDROP) == 0) {
|
} else if (errno != ENOENT) {
|
||||||
queue_size += st.st_size;
|
msg_warn("open %s %s: %m", qp->name, id);
|
||||||
vstream_fprintf(client, var_long_queue_ids ?
|
}
|
||||||
L_DROP_FORMAT : S_DROP_FORMAT, id, ' ',
|
|
||||||
(long) st.st_size,
|
|
||||||
asctime(localtime(&st.st_mtime)),
|
|
||||||
(unsigned) st.st_uid);
|
|
||||||
} else if (errno != ENOENT)
|
|
||||||
msg_fatal("open %s %s: %m", qp->name, id);
|
|
||||||
file_count++;
|
|
||||||
vstream_fflush(client);
|
|
||||||
}
|
}
|
||||||
vstream_fflush(client);
|
vstream_fflush(client);
|
||||||
}
|
}
|
||||||
@ -399,13 +393,7 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
|
|||||||
myfree(saved_id);
|
myfree(saved_id);
|
||||||
scan_dir_close(scan);
|
scan_dir_close(scan);
|
||||||
}
|
}
|
||||||
if (file_count == 0)
|
attr_print(client, ATTR_FLAG_NONE, ATTR_TYPE_END);
|
||||||
vstream_fprintf(client, "Mail queue is empty\n");
|
|
||||||
else {
|
|
||||||
vstream_fprintf(client, "\n-- %lu Kbytes in %d Request%s.\n",
|
|
||||||
queue_size / 1024, file_count,
|
|
||||||
file_count == 1 ? "" : "s");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MAIL_VERSION_STAMP_DECLARE;
|
MAIL_VERSION_STAMP_DECLARE;
|
||||||
|
@ -567,16 +567,21 @@ extern void smtp_rcpt_done(SMTP_STATE *, SMTP_RESP *, RECIPIENT *);
|
|||||||
/*
|
/*
|
||||||
* smtp_trouble.c
|
* smtp_trouble.c
|
||||||
*/
|
*/
|
||||||
|
#define SMTP_THROTTLE 1
|
||||||
|
#define SMTP_NOTHROTTLE 0
|
||||||
extern int smtp_sess_fail(SMTP_STATE *);
|
extern int smtp_sess_fail(SMTP_STATE *);
|
||||||
extern int PRINTFLIKE(4, 5) smtp_site_fail(SMTP_STATE *, const char *,
|
extern int PRINTFLIKE(5, 6) smtp_misc_fail(SMTP_STATE *, int, const char *,
|
||||||
SMTP_RESP *, const char *,...);
|
|
||||||
extern int PRINTFLIKE(4, 5) smtp_mesg_fail(SMTP_STATE *, const char *,
|
|
||||||
SMTP_RESP *, const char *,...);
|
SMTP_RESP *, const char *,...);
|
||||||
extern void PRINTFLIKE(5, 6) smtp_rcpt_fail(SMTP_STATE *, RECIPIENT *,
|
extern void PRINTFLIKE(5, 6) smtp_rcpt_fail(SMTP_STATE *, RECIPIENT *,
|
||||||
const char *, SMTP_RESP *,
|
const char *, SMTP_RESP *,
|
||||||
const char *,...);
|
const char *,...);
|
||||||
extern int smtp_stream_except(SMTP_STATE *, int, const char *);
|
extern int smtp_stream_except(SMTP_STATE *, int, const char *);
|
||||||
|
|
||||||
|
#define smtp_site_fail(state, mta, resp, ...) \
|
||||||
|
smtp_misc_fail((state), SMTP_THROTTLE, (mta), (resp), __VA_ARGS__)
|
||||||
|
#define smtp_mesg_fail(state, mta, resp, ...) \
|
||||||
|
smtp_misc_fail((state), SMTP_NOTHROTTLE, (mta), (resp), __VA_ARGS__)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* smtp_unalias.c
|
* smtp_unalias.c
|
||||||
*/
|
*/
|
||||||
|
@ -935,10 +935,17 @@ static int smtp_start_tls(SMTP_STATE *state)
|
|||||||
* authentication. If the server doesn't announce SASL support over
|
* authentication. If the server doesn't announce SASL support over
|
||||||
* plaintext connections, then we don't want delivery to fail with
|
* plaintext connections, then we don't want delivery to fail with
|
||||||
* "relay access denied".
|
* "relay access denied".
|
||||||
|
*
|
||||||
|
* If TLS is opportunistic, don't throttle the destination, otherwise if
|
||||||
|
* the mail is volume is high enough we may have difficulty ever
|
||||||
|
* draining even the deferred mail, as new mail provides a constant
|
||||||
|
* stream of negative feedback.
|
||||||
*/
|
*/
|
||||||
if (PLAINTEXT_FALLBACK_OK_AFTER_STARTTLS_FAILURE)
|
if (PLAINTEXT_FALLBACK_OK_AFTER_STARTTLS_FAILURE)
|
||||||
RETRY_AS_PLAINTEXT;
|
RETRY_AS_PLAINTEXT;
|
||||||
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
|
return (smtp_misc_fail(state, state->tls->level == TLS_LEV_MAY ?
|
||||||
|
SMTP_NOTHROTTLE : SMTP_THROTTLE,
|
||||||
|
DSN_BY_LOCAL_MTA,
|
||||||
SMTP_RESP_FAKE(&fake, "4.7.5"),
|
SMTP_RESP_FAKE(&fake, "4.7.5"),
|
||||||
"Cannot start TLS: handshake failure"));
|
"Cannot start TLS: handshake failure"));
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,13 @@
|
|||||||
/* SMTP_STATE *state;
|
/* SMTP_STATE *state;
|
||||||
/* int exception;
|
/* int exception;
|
||||||
/* const char *description;
|
/* const char *description;
|
||||||
|
/* AUXILIARY FUNCTIONS
|
||||||
|
/* int smtp_misc_fail(state, throttle, mta_name, resp, format, ...)
|
||||||
|
/* SMTP_STATE *state;
|
||||||
|
/* int throttle;
|
||||||
|
/* const char *mta_name;
|
||||||
|
/* SMTP_RESP *resp;
|
||||||
|
/* const char *format;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module handles all non-fatal errors that can happen while
|
/* This module handles all non-fatal errors that can happen while
|
||||||
/* attempting to deliver mail via SMTP, and implements the policy
|
/* attempting to deliver mail via SMTP, and implements the policy
|
||||||
@ -82,6 +89,13 @@
|
|||||||
/* remaining recipients.
|
/* remaining recipients.
|
||||||
/* The result is non-zero.
|
/* The result is non-zero.
|
||||||
/*
|
/*
|
||||||
|
/* smtp_misc_fail() provides a more detailed interface than
|
||||||
|
/* smtp_site_fail() and smtp_mesg_fail(), which are convenience
|
||||||
|
/* wrappers around smtp_misc_fail(). The throttle argument
|
||||||
|
/* is either SMTP_THROTTLE or SMTP_NOTHROTTLE; it is used only
|
||||||
|
/* in the "soft error, final server" policy, and determines
|
||||||
|
/* whether a destination will be marked as problematic.
|
||||||
|
/*
|
||||||
/* smtp_rcpt_fail() handles the case where a recipient is not
|
/* smtp_rcpt_fail() handles the case where a recipient is not
|
||||||
/* accepted by the server for reasons other than that the server
|
/* accepted by the server for reasons other than that the server
|
||||||
/* recipient limit is reached.
|
/* recipient limit is reached.
|
||||||
@ -162,9 +176,6 @@
|
|||||||
#include "smtp.h"
|
#include "smtp.h"
|
||||||
#include "smtp_sasl.h"
|
#include "smtp_sasl.h"
|
||||||
|
|
||||||
#define SMTP_THROTTLE 1
|
|
||||||
#define SMTP_NOTHROTTLE 0
|
|
||||||
|
|
||||||
/* smtp_check_code - check response code */
|
/* smtp_check_code - check response code */
|
||||||
|
|
||||||
static void smtp_check_code(SMTP_SESSION *session, int code)
|
static void smtp_check_code(SMTP_SESSION *session, int code)
|
||||||
@ -310,10 +321,10 @@ static void vsmtp_fill_dsn(SMTP_STATE *state, const char *mta_name,
|
|||||||
reply ? DSB_DTYPE_SMTP : DSB_DTYPE_NONE, reply);
|
reply ? DSB_DTYPE_SMTP : DSB_DTYPE_NONE, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* smtp_site_fail - throttle this queue; skip, defer or bounce all recipients */
|
/* smtp_misc_fail - maybe throttle queue; skip/defer/bounce all recipients */
|
||||||
|
|
||||||
int smtp_site_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
|
int smtp_misc_fail(SMTP_STATE *state, int throttle, const char *mta_name,
|
||||||
const char *format,...)
|
SMTP_RESP *resp, const char *format,...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@ -330,30 +341,7 @@ int smtp_site_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
|
|||||||
/*
|
/*
|
||||||
* Skip, defer or bounce recipients, and throttle this queue.
|
* Skip, defer or bounce recipients, and throttle this queue.
|
||||||
*/
|
*/
|
||||||
return (smtp_bulk_fail(state, SMTP_THROTTLE));
|
return (smtp_bulk_fail(state, throttle));
|
||||||
}
|
|
||||||
|
|
||||||
/* smtp_mesg_fail - skip, defer or bounce all recipients; no queue throttle */
|
|
||||||
|
|
||||||
int smtp_mesg_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
|
|
||||||
const char *format,...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize.
|
|
||||||
*/
|
|
||||||
va_start(ap, format);
|
|
||||||
vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (state->session && mta_name)
|
|
||||||
smtp_check_code(state->session, resp->code);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Skip, defer or bounce recipients, but don't throttle this queue.
|
|
||||||
*/
|
|
||||||
return (smtp_bulk_fail(state, SMTP_NOTHROTTLE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* smtp_rcpt_fail - skip, defer, or bounce recipient */
|
/* smtp_rcpt_fail - skip, defer, or bounce recipient */
|
||||||
|
@ -110,6 +110,7 @@ CHECK_VAL_HELPER_DCL(ATTR, ATTR_SCAN_SLAVE_FN);
|
|||||||
#define attr_vprint attr_vprint0
|
#define attr_vprint attr_vprint0
|
||||||
#define attr_scan attr_scan0
|
#define attr_scan attr_scan0
|
||||||
#define attr_vscan attr_vscan0
|
#define attr_vscan attr_vscan0
|
||||||
|
#define attr_scan_more attr_scan_more0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* attr_print64.c.
|
* attr_print64.c.
|
||||||
@ -122,6 +123,7 @@ extern int attr_vprint64(VSTREAM *, int, va_list);
|
|||||||
*/
|
*/
|
||||||
extern int WARN_UNUSED_RESULT attr_scan64(VSTREAM *, int,...);
|
extern int WARN_UNUSED_RESULT attr_scan64(VSTREAM *, int,...);
|
||||||
extern int WARN_UNUSED_RESULT attr_vscan64(VSTREAM *, int, va_list);
|
extern int WARN_UNUSED_RESULT attr_vscan64(VSTREAM *, int, va_list);
|
||||||
|
extern int WARN_UNUSED_RESULT attr_scan_more64(VSTREAM *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* attr_print0.c.
|
* attr_print0.c.
|
||||||
@ -134,12 +136,14 @@ extern int attr_vprint0(VSTREAM *, int, va_list);
|
|||||||
*/
|
*/
|
||||||
extern int WARN_UNUSED_RESULT attr_scan0(VSTREAM *, int,...);
|
extern int WARN_UNUSED_RESULT attr_scan0(VSTREAM *, int,...);
|
||||||
extern int WARN_UNUSED_RESULT attr_vscan0(VSTREAM *, int, va_list);
|
extern int WARN_UNUSED_RESULT attr_vscan0(VSTREAM *, int, va_list);
|
||||||
|
extern int WARN_UNUSED_RESULT attr_scan_more0(VSTREAM *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* attr_scan_plain.c.
|
* attr_scan_plain.c.
|
||||||
*/
|
*/
|
||||||
extern int attr_print_plain(VSTREAM *, int,...);
|
extern int attr_print_plain(VSTREAM *, int,...);
|
||||||
extern int attr_vprint_plain(VSTREAM *, int, va_list);
|
extern int attr_vprint_plain(VSTREAM *, int, va_list);
|
||||||
|
extern int attr_scan_more_plain(VSTREAM *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* attr_print_plain.c.
|
* attr_print_plain.c.
|
||||||
@ -147,7 +151,6 @@ extern int attr_vprint_plain(VSTREAM *, int, va_list);
|
|||||||
extern int WARN_UNUSED_RESULT attr_scan_plain(VSTREAM *, int,...);
|
extern int WARN_UNUSED_RESULT attr_scan_plain(VSTREAM *, int,...);
|
||||||
extern int WARN_UNUSED_RESULT attr_vscan_plain(VSTREAM *, int, va_list);
|
extern int WARN_UNUSED_RESULT attr_vscan_plain(VSTREAM *, int, va_list);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attribute names for testing the compatibility of the read and write
|
* Attribute names for testing the compatibility of the read and write
|
||||||
* routines.
|
* routines.
|
||||||
|
@ -7,15 +7,18 @@
|
|||||||
/* #include <attr.h>
|
/* #include <attr.h>
|
||||||
/*
|
/*
|
||||||
/* int attr_scan0(fp, flags, type, name, ..., ATTR_TYPE_END)
|
/* int attr_scan0(fp, flags, type, name, ..., ATTR_TYPE_END)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM *fp;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *name;
|
/* char *name;
|
||||||
/*
|
/*
|
||||||
/* int attr_vscan0(fp, flags, ap)
|
/* int attr_vscan0(fp, flags, ap)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM *fp;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* va_list ap;
|
/* va_list ap;
|
||||||
|
/*
|
||||||
|
/* int attr_scan_more0(fp)
|
||||||
|
/* VSTREAM *fp;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* attr_scan0() takes zero or more (name, value) request attributes
|
/* attr_scan0() takes zero or more (name, value) request attributes
|
||||||
/* and recovers the attribute values from the byte stream that was
|
/* and recovers the attribute values from the byte stream that was
|
||||||
@ -24,6 +27,11 @@
|
|||||||
/* attr_vscan0() provides an alternative interface that is convenient
|
/* attr_vscan0() provides an alternative interface that is convenient
|
||||||
/* for calling from within a variadic function.
|
/* for calling from within a variadic function.
|
||||||
/*
|
/*
|
||||||
|
/* attr_scan_more0() returns 0 when a terminator is found (and
|
||||||
|
/* consumes that terminator), returns 1 when more input is
|
||||||
|
/* expected (without consuming input), and returns -1 otherwise
|
||||||
|
/* (error).
|
||||||
|
/*
|
||||||
/* The input stream is formatted as follows, where (item)* stands
|
/* The input stream is formatted as follows, where (item)* stands
|
||||||
/* for zero or more instances of the specified item, and where
|
/* for zero or more instances of the specified item, and where
|
||||||
/* (item1 | item2) stands for choice:
|
/* (item1 | item2) stands for choice:
|
||||||
@ -144,6 +152,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -345,14 +358,14 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap)
|
|||||||
/*
|
/*
|
||||||
* See if the caller asks for this attribute.
|
* See if the caller asks for this attribute.
|
||||||
*/
|
*/
|
||||||
if (wanted_type == ATTR_TYPE_HASH
|
if (wanted_type == ATTR_TYPE_HASH
|
||||||
&& strcmp(ATTR_NAME_OPEN, STR(name_buf)) == 0) {
|
&& strcmp(ATTR_NAME_OPEN, STR(name_buf)) == 0) {
|
||||||
wanted_type = ATTR_TYPE_CLOSE;
|
wanted_type = ATTR_TYPE_CLOSE;
|
||||||
wanted_name = "(any attribute name or '}')";
|
wanted_name = "(any attribute name or '}')";
|
||||||
/* Advance in the input stream. */
|
/* Advance in the input stream. */
|
||||||
continue;
|
continue;
|
||||||
} else if (wanted_type == ATTR_TYPE_CLOSE
|
} else if (wanted_type == ATTR_TYPE_CLOSE
|
||||||
&& strcmp(ATTR_NAME_CLOSE, STR(name_buf)) == 0) {
|
&& strcmp(ATTR_NAME_CLOSE, STR(name_buf)) == 0) {
|
||||||
/* Advance in the argument list. */
|
/* Advance in the argument list. */
|
||||||
wanted_type = -1;
|
wanted_type = -1;
|
||||||
break;
|
break;
|
||||||
@ -450,6 +463,30 @@ int attr_scan0(VSTREAM *fp, int flags,...)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* attr_scan_more0 - look ahead for more */
|
||||||
|
|
||||||
|
int attr_scan_more0(VSTREAM *fp)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
switch (ch = VSTREAM_GETC(fp)) {
|
||||||
|
case 0:
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: terminator (consumed)", VSTREAM_PATH(fp));
|
||||||
|
return (0);
|
||||||
|
case VSTREAM_EOF:
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: EOF", VSTREAM_PATH(fp));
|
||||||
|
return (-1);
|
||||||
|
default:
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: non-terminator '%c' (lookahead)",
|
||||||
|
VSTREAM_PATH(fp), ch);
|
||||||
|
(void) vstream_ungetc(fp, ch);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,15 +7,18 @@
|
|||||||
/* #include <attr.h>
|
/* #include <attr.h>
|
||||||
/*
|
/*
|
||||||
/* int attr_scan64(fp, flags, type, name, ..., ATTR_TYPE_END)
|
/* int attr_scan64(fp, flags, type, name, ..., ATTR_TYPE_END)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM *fp;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *name;
|
/* char *name;
|
||||||
/*
|
/*
|
||||||
/* int attr_vscan64(fp, flags, ap)
|
/* int attr_vscan64(fp, flags, ap)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM *fp;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* va_list ap;
|
/* va_list ap;
|
||||||
|
/*
|
||||||
|
/* int attr_scan_more64(fp)
|
||||||
|
/* VSTREAM *fp;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* attr_scan64() takes zero or more (name, value) request attributes
|
/* attr_scan64() takes zero or more (name, value) request attributes
|
||||||
/* and recovers the attribute values from the byte stream that was
|
/* and recovers the attribute values from the byte stream that was
|
||||||
@ -24,6 +27,11 @@
|
|||||||
/* attr_vscan64() provides an alternative interface that is convenient
|
/* attr_vscan64() provides an alternative interface that is convenient
|
||||||
/* for calling from within a variadic function.
|
/* for calling from within a variadic function.
|
||||||
/*
|
/*
|
||||||
|
/* attr_scan_more64() returns 0 when a terminator is found
|
||||||
|
/* (and consumes that terminator), returns 1 when more input
|
||||||
|
/* is expected (without consuming input), and returns -1
|
||||||
|
/* otherwise (error).
|
||||||
|
/*
|
||||||
/* The input stream is formatted as follows, where (item)* stands
|
/* The input stream is formatted as follows, where (item)* stands
|
||||||
/* for zero or more instances of the specified item, and where
|
/* for zero or more instances of the specified item, and where
|
||||||
/* (item1 | item2) stands for choice:
|
/* (item1 | item2) stands for choice:
|
||||||
@ -146,6 +154,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -348,14 +361,14 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap)
|
|||||||
/*
|
/*
|
||||||
* See if the caller asks for this attribute.
|
* See if the caller asks for this attribute.
|
||||||
*/
|
*/
|
||||||
if (wanted_type == ATTR_TYPE_HASH
|
if (wanted_type == ATTR_TYPE_HASH
|
||||||
&& ch == '\n' && strcmp(ATTR_NAME_OPEN, STR(name_buf)) == 0) {
|
&& ch == '\n' && strcmp(ATTR_NAME_OPEN, STR(name_buf)) == 0) {
|
||||||
wanted_type = ATTR_TYPE_CLOSE;
|
wanted_type = ATTR_TYPE_CLOSE;
|
||||||
wanted_name = "(any attribute name or '}')";
|
wanted_name = "(any attribute name or '}')";
|
||||||
/* Advance in the input stream. */
|
/* Advance in the input stream. */
|
||||||
continue;
|
continue;
|
||||||
} else if (wanted_type == ATTR_TYPE_CLOSE
|
} else if (wanted_type == ATTR_TYPE_CLOSE
|
||||||
&& ch == '\n' && strcmp(ATTR_NAME_CLOSE, STR(name_buf)) == 0) {
|
&& ch == '\n' && strcmp(ATTR_NAME_CLOSE, STR(name_buf)) == 0) {
|
||||||
/* Advance in the argument list. */
|
/* Advance in the argument list. */
|
||||||
wanted_type = -1;
|
wanted_type = -1;
|
||||||
break;
|
break;
|
||||||
@ -509,6 +522,30 @@ int attr_scan64(VSTREAM *fp, int flags,...)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* attr_scan_more64 - look ahead for more */
|
||||||
|
|
||||||
|
int attr_scan_more64(VSTREAM *fp)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
switch (ch = VSTREAM_GETC(fp)) {
|
||||||
|
case '\n':
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: terminator (consumed)", VSTREAM_PATH(fp));
|
||||||
|
return (0);
|
||||||
|
case VSTREAM_EOF:
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: EOF", VSTREAM_PATH(fp));
|
||||||
|
return (-1);
|
||||||
|
default:
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: non-terminator '%c' (lookahead)",
|
||||||
|
VSTREAM_PATH(fp), ch);
|
||||||
|
(void) vstream_ungetc(fp, ch);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,15 +7,18 @@
|
|||||||
/* #include <attr.h>
|
/* #include <attr.h>
|
||||||
/*
|
/*
|
||||||
/* int attr_scan_plain(fp, flags, type, name, ..., ATTR_TYPE_END)
|
/* int attr_scan_plain(fp, flags, type, name, ..., ATTR_TYPE_END)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM *fp;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *name;
|
/* char *name;
|
||||||
/*
|
/*
|
||||||
/* int attr_vscan_plain(fp, flags, ap)
|
/* int attr_vscan_plain(fp, flags, ap)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM *fp;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* va_list ap;
|
/* va_list ap;
|
||||||
|
/*
|
||||||
|
/* int attr_scan_more_plain(fp)
|
||||||
|
/* VSTREAM *fp;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* attr_scan_plain() takes zero or more (name, value) request attributes
|
/* attr_scan_plain() takes zero or more (name, value) request attributes
|
||||||
/* and recovers the attribute values from the byte stream that was
|
/* and recovers the attribute values from the byte stream that was
|
||||||
@ -24,6 +27,11 @@
|
|||||||
/* attr_vscan_plain() provides an alternative interface that is convenient
|
/* attr_vscan_plain() provides an alternative interface that is convenient
|
||||||
/* for calling from within a variadic function.
|
/* for calling from within a variadic function.
|
||||||
/*
|
/*
|
||||||
|
/* attr_scan_more_plain() returns 0 when a terminator is found
|
||||||
|
/* (and consumes that terminator), returns 1 when more input
|
||||||
|
/* is expected (without consuming input), and returns -1
|
||||||
|
/* otherwise (error).
|
||||||
|
/*
|
||||||
/* The input stream is formatted as follows, where (item)* stands
|
/* The input stream is formatted as follows, where (item)* stands
|
||||||
/* for zero or more instances of the specified item, and where
|
/* for zero or more instances of the specified item, and where
|
||||||
/* (item1 | item2) stands for choice:
|
/* (item1 | item2) stands for choice:
|
||||||
@ -144,6 +152,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -361,14 +374,14 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
|
|||||||
/*
|
/*
|
||||||
* See if the caller asks for this attribute.
|
* See if the caller asks for this attribute.
|
||||||
*/
|
*/
|
||||||
if (wanted_type == ATTR_TYPE_HASH
|
if (wanted_type == ATTR_TYPE_HASH
|
||||||
&& ch == '\n' && strcmp(ATTR_NAME_OPEN, STR(name_buf)) == 0) {
|
&& ch == '\n' && strcmp(ATTR_NAME_OPEN, STR(name_buf)) == 0) {
|
||||||
wanted_type = ATTR_TYPE_CLOSE;
|
wanted_type = ATTR_TYPE_CLOSE;
|
||||||
wanted_name = "(any attribute name or '}')";
|
wanted_name = "(any attribute name or '}')";
|
||||||
/* Advance in the input stream. */
|
/* Advance in the input stream. */
|
||||||
continue;
|
continue;
|
||||||
} else if (wanted_type == ATTR_TYPE_CLOSE
|
} else if (wanted_type == ATTR_TYPE_CLOSE
|
||||||
&& ch == '\n' && strcmp(ATTR_NAME_CLOSE, STR(name_buf)) == 0) {
|
&& ch == '\n' && strcmp(ATTR_NAME_CLOSE, STR(name_buf)) == 0) {
|
||||||
/* Advance in the argument list. */
|
/* Advance in the argument list. */
|
||||||
wanted_type = -1;
|
wanted_type = -1;
|
||||||
break;
|
break;
|
||||||
@ -492,6 +505,30 @@ int attr_scan_plain(VSTREAM *fp, int flags,...)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* attr_scan_more_plain - look ahead for more */
|
||||||
|
|
||||||
|
int attr_scan_more_plain(VSTREAM *fp)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
switch (ch = VSTREAM_GETC(fp)) {
|
||||||
|
case '\n':
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: terminator (consumed)", VSTREAM_PATH(fp));
|
||||||
|
return (0);
|
||||||
|
case VSTREAM_EOF:
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: EOF", VSTREAM_PATH(fp));
|
||||||
|
return (-1);
|
||||||
|
default:
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: non-terminator '%c' (lookahead)",
|
||||||
|
VSTREAM_PATH(fp), ch);
|
||||||
|
(void) vstream_ungetc(fp, ch);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -399,7 +399,8 @@
|
|||||||
/* This is an alias for vstream_bufstat(stream, VSTREAM_BST_IN_PEND).
|
/* This is an alias for vstream_bufstat(stream, VSTREAM_BST_IN_PEND).
|
||||||
/*
|
/*
|
||||||
/* vstream_peek_data() returns a pointer to the unread bytes
|
/* vstream_peek_data() returns a pointer to the unread bytes
|
||||||
/* that exist according to vstream_peek().
|
/* that exist according to vstream_peek(), or null if no unread
|
||||||
|
/* bytes are available.
|
||||||
/*
|
/*
|
||||||
/* vstream_setjmp() saves processing context and makes that context
|
/* vstream_setjmp() saves processing context and makes that context
|
||||||
/* available for use with vstream_longjmp(). Normally, vstream_setjmp()
|
/* available for use with vstream_longjmp(). Normally, vstream_setjmp()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user