mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
snapshot-20010524
This commit is contained in:
committed by
Viktor Dukhovni
parent
92370560ec
commit
ca0dd40ea2
@@ -5187,13 +5187,18 @@ Apologies for any names omitted.
|
||||
|
||||
20010522
|
||||
|
||||
Feature: "postsuper -r queueID" re-queues a message. The
|
||||
message is moved to the maildrop queue so that the pickup
|
||||
daemon will copy it to a new file with the "right" name
|
||||
that matches the queue file inode number, and so that
|
||||
address rewriting will be done again. This is useful after
|
||||
changes of address rewriting or virtual mappings.
|
||||
Feature: "postsuper -r queueID" re-queues a message, and
|
||||
"postsuper -R" re-queues all mail. The message is moved to
|
||||
the maildrop queue so that the pickup daemon will copy it
|
||||
to a new queue file, and so that address rewriting will be
|
||||
done again. This is useful after changes of address rewriting
|
||||
or virtual mappings.
|
||||
|
||||
Feature: "postsuper -R" re-queues all mail. This is useful
|
||||
after restoring a Postfix queue from another machine, or
|
||||
from backup.
|
||||
20010523
|
||||
|
||||
Feature: "postsuper -s" (which is done by default) renames
|
||||
queue files whose queue ID does not match the message file
|
||||
inode number.
|
||||
|
||||
Bugfix: memory leak in the LDAP client module. Alain
|
||||
Thivillon,France Teaser - Groupe Firstream.
|
||||
|
@@ -12,20 +12,22 @@ server state just like RSET. This behavior cannot be disabled.
|
||||
Major changes with snapshot-20010522
|
||||
====================================
|
||||
|
||||
Revision of some fine details in the light of the new RFC 2821 and
|
||||
RFC 2822 standards. Changes that may affect interoperability are
|
||||
listed above under "incompatible changes".
|
||||
This release contains revisions of some fine details in the light
|
||||
of the new RFC 2821 and RFC 2822 standards. Changes that may affect
|
||||
interoperability are listed above under "incompatible changes".
|
||||
|
||||
The postsuper tool can rename files whose queue ID does not match
|
||||
the queue file inode number. This is necessary when a Postfix mail
|
||||
queue is restored from another machine or from backups. The feature
|
||||
is selected with the -s option, which is the default.
|
||||
|
||||
The postsuper queue maintenance tool was extended with options to
|
||||
read queue IDs from standard input (which makes it easier to drive
|
||||
the tool from scripts).
|
||||
read queue IDs from standard input. This makes the tool easier to
|
||||
drive from scripts.
|
||||
|
||||
The postsuper queue maintenance tool has a new -r (requeue) option
|
||||
for subjecting queue files to another iteration of address rewriting.
|
||||
|
||||
The postsuper -R option requeues all mail. This is necessary after
|
||||
restoring Postfix queues from another machine or from backups.
|
||||
|
||||
Major changes with snapshot-20010502
|
||||
====================================
|
||||
|
||||
|
@@ -174,9 +174,6 @@ check)
|
||||
\( -perm -020 -o -perm -002 \) \
|
||||
-exec $WARN group or other writable: {} \;
|
||||
|
||||
find $queue_directory/* $config_directory/* -name '*core' \
|
||||
-exec $WARN core file: {} \; 2>/dev/null
|
||||
|
||||
test -d maildrop || {
|
||||
$WARN creating missing Postfix maildrop directory
|
||||
mkdir maildrop || exit 1
|
||||
@@ -254,10 +251,11 @@ EOF
|
||||
$command_directory/postconf -e hash_queue_names="$found$missing"
|
||||
}
|
||||
|
||||
# See if all queue files are in the right place.
|
||||
# See if all queue files are in the right place. This is slow.
|
||||
# We must scan all queues for mis-named queue files before the
|
||||
# mail system can run.
|
||||
|
||||
$command_directory/postsuper active
|
||||
$command_directory/postsuper &
|
||||
$command_directory/postsuper || exit 1
|
||||
|
||||
find corrupt -type f -exec $WARN damaged message: {} \;
|
||||
|
||||
|
@@ -174,9 +174,6 @@ check)
|
||||
\( -perm -020 -o -perm -002 \) \
|
||||
-exec $WARN group or other writable: {} \;
|
||||
|
||||
find $queue_directory/* $config_directory/* -name '*core' \
|
||||
-exec $WARN core file: {} \; 2>/dev/null
|
||||
|
||||
test -d maildrop || {
|
||||
$WARN creating missing Postfix maildrop directory
|
||||
mkdir maildrop || exit 1
|
||||
@@ -255,10 +252,11 @@ EOF
|
||||
$command_directory/postconf -e hash_queue_names="$found$missing"
|
||||
}
|
||||
|
||||
# See if all queue files are in the right place.
|
||||
# See if all queue files are in the right place. This is slow.
|
||||
# We must scan all queues for mis-named queue files before the
|
||||
# mail system can run.
|
||||
|
||||
$command_directory/postsuper active
|
||||
$command_directory/postsuper &
|
||||
$command_directory/postsuper || exit 1
|
||||
|
||||
find corrupt -type f -exec $WARN damaged message: {} \;
|
||||
|
||||
|
@@ -3063,13 +3063,61 @@ that the file name will collide with another queue file.
|
||||
|
||||
<p>
|
||||
|
||||
To avoid queue file name collisions when copying queue files,
|
||||
restore the incoming, active and deferred queue files under the
|
||||
maildrop directory instead.
|
||||
<ul>
|
||||
|
||||
<li>If your Postfix queue is empty, and if you run a Postfix release
|
||||
after 20010524, you can use this procedure to copy a Postfix
|
||||
queue from another machine or to restore it from backup.
|
||||
|
||||
<p>
|
||||
|
||||
As of late 2000, Postfix queues are all hashed (for example, file
|
||||
<ul>
|
||||
|
||||
<li> Stop Postfix, if it was running.
|
||||
|
||||
<p>
|
||||
|
||||
<li> Execute the <b>mailq</b> command. If there is any output, do
|
||||
not complete this procedure, but use the second procedure instead.
|
||||
|
||||
<p>
|
||||
|
||||
<li> Copy or restore the queue to the usual place.
|
||||
|
||||
<p>
|
||||
|
||||
<li> Run the <b>postsuper</b> command. This command will rename
|
||||
queue files so that the name matches the message file inode number.
|
||||
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
||||
<li> If your Postfix queue is not empty, or if you are running a
|
||||
Postfix release prior to 20010524, use the following procedure
|
||||
instead.
|
||||
|
||||
<p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Stop Postfix, if it was running.
|
||||
|
||||
<p>
|
||||
|
||||
<li> To avoid queue file name collisions when restoring queue files,
|
||||
copy or restore the incoming, active and deferred queue files under
|
||||
the maildrop directory instead.
|
||||
|
||||
<p>
|
||||
|
||||
<li>While the next step is going on, don't submit new mail locally,
|
||||
because that could collide with the files you are restoring under
|
||||
the maildrop directory.
|
||||
|
||||
<p>
|
||||
|
||||
<li>As of late 2000, Postfix queues are all hashed (for example, file
|
||||
ABCDEF is stored as A/B/ABCDEF), so you need an additional step to
|
||||
move files down from their subdirectories.
|
||||
|
||||
@@ -3083,15 +3131,15 @@ move files down from their subdirectories.
|
||||
# postfix start
|
||||
</pre>
|
||||
|
||||
While all this is going on, don't submit new mail locally, because
|
||||
that could collide with the files you are restoring under the
|
||||
maildrop directory.
|
||||
|
||||
<p>
|
||||
|
||||
When Postfix is started, it will pick up queue files from the
|
||||
<li>When Postfix is started, it will pick up queue files from the
|
||||
maildrop directory and will give them proper queue file names.
|
||||
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<a name="bind"><h3>Undefined symbols: ___dn_expand, ___res_init etc.</h3></a>
|
||||
|
@@ -13,52 +13,52 @@ POSTSUPER(1) POSTSUPER(1)
|
||||
<i>...</i>]
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
The <b>postsuper</b> command does small maintenance jobs. Use of
|
||||
the command is restricted to the super-user.
|
||||
The <b>postsuper</b> command does maintenance jobs on the Postfix
|
||||
queue. Use of the command is restricted to the super-user.
|
||||
|
||||
By default, <b>postsuper</b> performs the operations requested
|
||||
with the <b>-s</b> and <b>-p</b> command-line options on the named Post-
|
||||
fix queue directories (default: all). Directory names are
|
||||
relative to the Postfix top-level queue directory.
|
||||
with the <b>-s</b> and <b>-p</b> command-line options on all Postfix
|
||||
queue directories - this includes the <b>incoming</b>, <b>active</b> and
|
||||
<b>deferred</b> directories with mail files and the <b>bounce</b>, <b>defer</b>
|
||||
and <b>flush</b> directories with log files.
|
||||
|
||||
Options:
|
||||
|
||||
<b>-d</b> This option ignores any <i>directory</i> argument(s).
|
||||
Delete one message queue file with the named queue
|
||||
ID. Specify multiple <b>-d</b> options to delete multiple
|
||||
queue files by name.
|
||||
|
||||
Alternatively, if a <i>queue_id</i> of <b>-</b> is specified, the
|
||||
<b>-d</b> <i>queue_id</i>
|
||||
Delete one message with the named queue ID from the
|
||||
named mail queue(s) (default: <b>incoming</b>, <b>active</b> and
|
||||
<b>deferred</b>). If a <i>queue_id</i> of <b>-</b> is specified, the
|
||||
program reads queue IDs from standard input.
|
||||
|
||||
The <b>postsuper</b> exit status is non-zero when no mes-
|
||||
sage queue file was deleted.
|
||||
Specify <b>-d</b> <b>ALL</b> to remove all messages; for example,
|
||||
specify <b>-d</b> <b>ALL</b> <b>deferred</b> to delete mail in the
|
||||
<b>deferred</b> queue. As a safety measure, the word <b>ALL</b>
|
||||
must be specified in upper case.
|
||||
|
||||
<b>There</b> <b>is</b> <b>a</b> <b>very</b> <b>small</b> <b>possibility</b> <b>that</b> <b>postsuper</b>
|
||||
<b>deletes</b> <b>the</b> <b>wrong</b> <b>message</b> <b>file</b> <b>when</b> <b>it</b> <b>is</b> <b>executed</b>
|
||||
<b>while</b> <b>the</b> <b>Postfix</b> <b>mail</b> <b>system</b> <b>is</b> <b>running.</b>
|
||||
<b>Postfix</b> <b>queue</b> <b>IDs</b> <b>are</b> <b>reused.</b> <b>There</b> <b>is</b> <b>a</b> <b>very</b>
|
||||
<b>small</b> <b>possibility</b> <b>that</b> <b>postsuper</b> <b>deletes</b> <b>the</b> <b>wrong</b>
|
||||
<b>message</b> <b>file</b> <b>when</b> <b>it</b> <b>is</b> <b>executed</b> <b>while</b> <b>the</b> <b>Postfix</b>
|
||||
<b>mail</b> <b>system</b> <b>is</b> <b>running.</b>
|
||||
|
||||
The scenario is as follows:
|
||||
|
||||
<b>o</b> The Postfix queue manager deletes the file
|
||||
that <b>postsuper</b> was supposed to delete,
|
||||
because Postfix was finished with the mes-
|
||||
1) The Postfix queue manager deletes the mes-
|
||||
sage that <b>postsuper</b> is supposed to delete,
|
||||
because Postfix is finished with the mes-
|
||||
sage.
|
||||
|
||||
<b>o</b> New mail arrives, and the new message is
|
||||
2) New mail arrives, and the new message is
|
||||
given the same queue ID as the message that
|
||||
<b>postsuper</b> was supposed to delete. The prob-
|
||||
ability for reusing a deleted queue ID is
|
||||
<b>postsuper</b> is supposed to delete. The proba-
|
||||
bility for reusing a deleted queue ID is
|
||||
about 1 in 2**15 (the number of different
|
||||
microsecond values that the system clock can
|
||||
distinguish within a second).
|
||||
|
||||
<b>o</b> <b>postsuper</b> deletes the new message file,
|
||||
instead of the old file that should have
|
||||
been deleted.
|
||||
3) <b>postsuper</b> deletes the new message, instead
|
||||
of the old message that it should have
|
||||
deleted.
|
||||
|
||||
<b>-r</b> This option ignores any <i>directory</i> argument(s).
|
||||
Requeue one message queue file with the named queue
|
||||
|
||||
|
||||
|
||||
@@ -71,33 +71,49 @@ POSTSUPER(1) POSTSUPER(1)
|
||||
POSTSUPER(1) POSTSUPER(1)
|
||||
|
||||
|
||||
ID. Specify multiple <b>-r</b> options to requeue multi-
|
||||
ple queue files by name.
|
||||
<b>-p</b> Purge old temporary files that are left over after
|
||||
system or software crashes.
|
||||
|
||||
Alternatively, if a <i>queue_id</i> of <b>-</b> is specified, the
|
||||
program reads queue IDs from standard input.
|
||||
<b>-r</b> <i>queue_id</i>
|
||||
Requeue the message with the named queue ID from
|
||||
the named mail queue(s) (default: <b>incoming</b>, <b>active</b>
|
||||
and <b>deferred</b>). To requeue multiple messages, spec-
|
||||
ify multiple <b>-r</b> command-line options. Alterna-
|
||||
tively, if a <i>queue_id</i> of <b>-</b> is specified, the pro-
|
||||
gram reads queue IDs from standard input.
|
||||
|
||||
The queue file is moved to the maildrop queue, from
|
||||
where it is copied by the pickup daemon to a new
|
||||
file whose name is guaranteed to match the queue
|
||||
file inode number. This feature is useful for queue
|
||||
files from another machine or for files restored
|
||||
from backup. The new queue file is subjected again
|
||||
to address rewriting and substitution.
|
||||
Specify <b>-r</b> <b>ALL</b> to requeue all messages. As a safety
|
||||
measure, the word <b>ALL</b> must be specified in upper
|
||||
case.
|
||||
|
||||
The <b>postsuper</b> exit status is non-zero when no mes-
|
||||
sage queue file was requeued.
|
||||
A requeued message is moved to the <b>maildrop</b> queue,
|
||||
from where it is copied by the pickup daemon to a
|
||||
new file whose name is guaranteed to match the new
|
||||
queue file inode number. The new queue file is sub-
|
||||
jected again to mail address rewriting and substi-
|
||||
tution. This is useful when rewriting rules or vir-
|
||||
tual mappings have changed.
|
||||
|
||||
<b>-s</b> Structure check. Move queue files that are in the
|
||||
wrong place in the file system hierarchy and remove
|
||||
subdirectories that are no longer needed. File
|
||||
rearrangements are necessary after a change in the
|
||||
<b>hash</b><i>_</i><b>queue</b><i>_</i><b>names</b> and/or <b>hash</b><i>_</i><b>queue</b><i>_</i><b>depth</b> configura-
|
||||
tion parameters. It is highly recommended to run
|
||||
this check once before Postfix startup.
|
||||
Postfix queue IDs are reused. There is a very
|
||||
small possibility that <b>postsuper</b> requeues the wrong
|
||||
message file when it is executed while the Postfix
|
||||
mail system is running, but no harm should be done.
|
||||
|
||||
<b>-p</b> Purge stale files (files that are left over after
|
||||
system or software crashes).
|
||||
<b>-s</b> Structure check and structure repair. It is highly
|
||||
recommended to perform this operation once before
|
||||
Postfix startup.
|
||||
|
||||
<b>o</b> Rename files whose name does not match the
|
||||
message file inode number. This operation is
|
||||
necessary after restoring a mail queue from
|
||||
a different machine, or from backup media.
|
||||
|
||||
<b>o</b> Move queue files that are in the wrong place
|
||||
in the file system hierarchy and remove sub-
|
||||
directories that are no longer needed. File
|
||||
position rearrangements are necessary after
|
||||
a change in the <b>hash</b><i>_</i><b>queue</b><i>_</i><b>names</b> and/or
|
||||
<b>hash</b><i>_</i><b>queue</b><i>_</i><b>depth</b> configuration parameters.
|
||||
|
||||
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
|
||||
tiple <b>-v</b> options make the software increasingly
|
||||
@@ -107,6 +123,24 @@ POSTSUPER(1) POSTSUPER(1)
|
||||
Problems are reported to the standard error stream and to
|
||||
<b>syslogd</b>.
|
||||
|
||||
<b>postsuper</b> reports the number of messages deleted with <b>-d</b>,
|
||||
the number of messages requeued with <b>-r</b>, and the number of
|
||||
|
||||
|
||||
|
||||
2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
POSTSUPER(1) POSTSUPER(1)
|
||||
|
||||
|
||||
messages whose queue file name was fixed with <b>-s</b>. The
|
||||
report is written to the standard error stream and to <b>sys-</b>
|
||||
<b>logd</b>.
|
||||
|
||||
<b>CONFIGURATION</b> <b>PARAMETERS</b>
|
||||
See the Postfix <b>main.cf</b> file for syntax details and for
|
||||
default values.
|
||||
@@ -125,18 +159,6 @@ POSTSUPER(1) POSTSUPER(1)
|
||||
<b>AUTHOR(S)</b>
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
|
||||
|
||||
|
||||
2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
POSTSUPER(1) POSTSUPER(1)
|
||||
|
||||
|
||||
P.O. Box 704
|
||||
Yorktown Heights, NY 10598, USA
|
||||
|
||||
@@ -151,28 +173,6 @@ POSTSUPER(1) POSTSUPER(1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -14,27 +14,30 @@ Postfix super intendent
|
||||
.SH DESCRIPTION
|
||||
.ad
|
||||
.fi
|
||||
The \fBpostsuper\fR command does small maintenance jobs. Use of
|
||||
the command is restricted to the super-user.
|
||||
The \fBpostsuper\fR command does maintenance jobs on the Postfix
|
||||
queue. Use of the command is restricted to the super-user.
|
||||
|
||||
By default, \fBpostsuper\fR performs the operations requested with the
|
||||
\fB-s\fR and \fB-p\fR command-line options on the named Postfix queue
|
||||
directories (default: all).
|
||||
Directory names are relative to the Postfix top-level queue directory.
|
||||
\fB-s\fR and \fB-p\fR command-line options on all Postfix queue
|
||||
directories - this includes the \fBincoming\fR, \fBactive\fR and
|
||||
\fBdeferred\fR directories with mail files and the \fBbounce\fR,
|
||||
\fBdefer\fR and \fBflush\fR directories with log files.
|
||||
|
||||
Options:
|
||||
.IP \fB-d \fIqueue_id\fR
|
||||
This option ignores any \fIdirectory\fR argument(s).
|
||||
Delete one message queue file with the named queue ID. Specify
|
||||
multiple \fB-d\fR options to delete multiple queue files by name.
|
||||
.IP "\fB-d \fIqueue_id\fR"
|
||||
Delete one message with the named queue ID from the named
|
||||
mail queue(s) (default: \fBincoming\fR, \fBactive\fR and
|
||||
\fBdeferred\fR).
|
||||
If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
|
||||
queue IDs from standard input.
|
||||
.sp
|
||||
Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, the
|
||||
program reads queue IDs from standard input.
|
||||
.sp
|
||||
The \fBpostsuper\fR exit status is non-zero when no message queue
|
||||
file was deleted.
|
||||
Specify \fB-d ALL\fR to remove all messages; for example, specify
|
||||
\fB-d ALL deferred\fR to delete mail in the \fBdeferred\fR queue.
|
||||
As a safety measure, the word \fBALL\fR must be specified in upper
|
||||
case.
|
||||
.sp
|
||||
.ft B
|
||||
Postfix queue IDs are reused.
|
||||
There is a very small possibility that postsuper deletes the
|
||||
wrong message file when it is executed while the Postfix mail
|
||||
system is running.
|
||||
@@ -42,47 +45,61 @@ system is running.
|
||||
.sp
|
||||
The scenario is as follows:
|
||||
.RS
|
||||
.IP \(bu
|
||||
The Postfix queue manager deletes the file that \fBpostsuper\fR
|
||||
was supposed to delete, because Postfix was finished with the
|
||||
.IP 1)
|
||||
The Postfix queue manager deletes the message that \fBpostsuper\fR
|
||||
is supposed to delete, because Postfix is finished with the
|
||||
message.
|
||||
.IP \(bu
|
||||
.IP 2)
|
||||
New mail arrives, and the new message is given the same queue ID
|
||||
as the message that \fBpostsuper\fR was supposed to delete.
|
||||
as the message that \fBpostsuper\fR is supposed to delete.
|
||||
The probability for reusing a deleted queue ID is about 1 in 2**15
|
||||
(the number of different microsecond values that the system clock
|
||||
can distinguish within a second).
|
||||
.IP \(bu
|
||||
\fBpostsuper\fR deletes the new message file, instead of the
|
||||
old file that should have been deleted.
|
||||
.IP 3)
|
||||
\fBpostsuper\fR deletes the new message, instead of the old
|
||||
message that it should have deleted.
|
||||
.RE
|
||||
.IP \fB-r \fIqueue_id\fR
|
||||
This option ignores any \fIdirectory\fR argument(s).
|
||||
Requeue one message queue file with the named queue ID. Specify
|
||||
multiple \fB-r\fR options to requeue multiple queue files by name.
|
||||
.sp
|
||||
Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, the
|
||||
program reads queue IDs from standard input.
|
||||
.sp
|
||||
The queue file is moved to the maildrop queue, from where
|
||||
it is copied by the pickup daemon to a new file whose name
|
||||
is guaranteed to match the queue file inode number. This
|
||||
feature is useful for queue files from another machine or
|
||||
for files restored from backup. The new queue file is
|
||||
subjected again to address rewriting and substitution.
|
||||
.sp
|
||||
The \fBpostsuper\fR exit status is non-zero when no message queue
|
||||
file was requeued.
|
||||
.IP \fB-s\fR
|
||||
Structure check. Move queue files that are in the wrong place
|
||||
in the file system hierarchy and remove subdirectories that are
|
||||
no longer needed. File rearrangements are necessary after a change
|
||||
in the \fBhash_queue_names\fR and/or \fBhash_queue_depth\fR
|
||||
configuration parameters. It is highly recommended to run this
|
||||
check once before Postfix startup.
|
||||
.IP \fB-p\fR
|
||||
Purge stale files (files that are left over after system or
|
||||
software crashes).
|
||||
Purge old temporary files that are left over after system or
|
||||
software crashes.
|
||||
.IP "\fB-r \fIqueue_id\fR"
|
||||
Requeue the message with the named queue ID from the named
|
||||
mail queue(s) (default: \fBincoming\fR, \fBactive\fR and
|
||||
\fBdeferred\fR).
|
||||
To requeue multiple messages, specify multiple \fB-r\fR
|
||||
command-line options.
|
||||
Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified,
|
||||
the program reads queue IDs from standard input.
|
||||
.sp
|
||||
Specify \fB-r ALL\fR to requeue all messages. As a safety
|
||||
measure, the word \fBALL\fR must be specified in upper case.
|
||||
.sp
|
||||
A requeued message is moved to the \fBmaildrop\fR queue, from
|
||||
where it is copied by the pickup daemon to a new file whose name
|
||||
is guaranteed to match the new queue file inode number. The
|
||||
new queue file is subjected again to mail address rewriting and
|
||||
substitution. This is useful when rewriting rules or virtual
|
||||
mappings have changed.
|
||||
.sp
|
||||
Postfix queue IDs are reused.
|
||||
There is a very small possibility that \fBpostsuper\fR requeues
|
||||
the wrong message file when it is executed while the Postfix mail
|
||||
system is running, but no harm should be done.
|
||||
.IP \fB-s\fR
|
||||
Structure check and structure repair. It is highly recommended
|
||||
to perform this operation once before Postfix startup.
|
||||
.RS
|
||||
.IP \(bu
|
||||
Rename files whose name does not match the message file inode
|
||||
number. This operation is necessary after restoring a mail queue
|
||||
from a different machine, or from backup media.
|
||||
.IP \(bu
|
||||
Move queue files that are in the wrong place in the file system
|
||||
hierarchy and remove subdirectories that are no longer needed.
|
||||
File position rearrangements are necessary after a change in the
|
||||
\fBhash_queue_names\fR and/or \fBhash_queue_depth\fR
|
||||
configuration parameters.
|
||||
.RE
|
||||
.IP \fB-v\fR
|
||||
Enable verbose logging for debugging purposes. Multiple \fB-v\fR
|
||||
options make the software increasingly verbose.
|
||||
@@ -91,6 +108,11 @@ options make the software increasingly verbose.
|
||||
.fi
|
||||
Problems are reported to the standard error stream and to
|
||||
\fBsyslogd\fR.
|
||||
|
||||
\fBpostsuper\fR reports the number of messages deleted with \fB-d\fR,
|
||||
the number of messages requeued with \fB-r\fR, and the number of
|
||||
messages whose queue file name was fixed with \fB-s\fR. The report
|
||||
is written to the standard error stream and to \fBsyslogd\fR.
|
||||
.SH CONFIGURATION PARAMETERS
|
||||
.na
|
||||
.nf
|
||||
|
@@ -65,7 +65,7 @@ const char *get_file_id(int fd)
|
||||
result = vstring_alloc(1);
|
||||
if (fstat(fd, &st) < 0)
|
||||
msg_fatal("fstat: %m");
|
||||
vstring_sprintf(result, "%X", (int) st.st_ino);
|
||||
vstring_sprintf(result, "%lX", (long) st.st_ino);
|
||||
return (vstring_str(result));
|
||||
}
|
||||
|
||||
|
@@ -388,11 +388,13 @@ VSTREAM *mail_queue_enter(const char *queue_name, int mode)
|
||||
for (count = 0;; count++) {
|
||||
vstring_sprintf(id_buf, "%05X%s", (int) tv.tv_usec, file_id);
|
||||
mail_queue_path(path_buf, queue_name, STR(id_buf));
|
||||
#if 0
|
||||
if (access(STR(path_buf), X_OK) == 0) { /* collision. */
|
||||
if ((int) ++tv.tv_usec < 0)
|
||||
tv.tv_usec = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (sane_rename(STR(temp_path), STR(path_buf)) == 0) /* success */
|
||||
break;
|
||||
if (errno == EPERM || errno == EISDIR) {/* collision. weird. */
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* Version of this program.
|
||||
*/
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20010522"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20010524"
|
||||
extern char *var_mail_version;
|
||||
|
||||
/* LICENSE
|
||||
|
@@ -5,30 +5,33 @@
|
||||
/* Postfix superintendent
|
||||
/* SYNOPSIS
|
||||
/* .fi
|
||||
/* \fBpostsuper\fR [\fB-Rpsv\fR] [\fB-d \fIqueue_id\fR]
|
||||
/* \fBpostsuper\fR [\fB-psv\fR] [\fB-d \fIqueue_id\fR]
|
||||
/* [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR]
|
||||
/* DESCRIPTION
|
||||
/* The \fBpostsuper\fR command does small maintenance jobs. Use of
|
||||
/* the command is restricted to the super-user.
|
||||
/* The \fBpostsuper\fR command does maintenance jobs on the Postfix
|
||||
/* queue. Use of the command is restricted to the super-user.
|
||||
/*
|
||||
/* By default, \fBpostsuper\fR performs the operations requested with the
|
||||
/* \fB-s\fR and \fB-p\fR command-line options on the named Postfix queue
|
||||
/* directories (default: all).
|
||||
/* Directory names are relative to the Postfix top-level queue directory.
|
||||
/* \fB-s\fR and \fB-p\fR command-line options on all Postfix queue
|
||||
/* directories - this includes the \fBincoming\fR, \fBactive\fR and
|
||||
/* \fBdeferred\fR directories with mail files and the \fBbounce\fR,
|
||||
/* \fBdefer\fR and \fBflush\fR directories with log files.
|
||||
/*
|
||||
/* Options:
|
||||
/* .IP \fB-d \fIqueue_id\fR
|
||||
/* This option ignores any \fIdirectory\fR argument(s).
|
||||
/* Delete one message queue file with the named queue ID. Specify
|
||||
/* multiple \fB-d\fR options to delete multiple queue files by name.
|
||||
/* .IP "\fB-d \fIqueue_id\fR"
|
||||
/* Delete one message with the named queue ID from the named
|
||||
/* mail queue(s) (default: \fBincoming\fR, \fBactive\fR and
|
||||
/* \fBdeferred\fR).
|
||||
/* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
|
||||
/* queue IDs from standard input.
|
||||
/* .sp
|
||||
/* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, the
|
||||
/* program reads queue IDs from standard input.
|
||||
/* .sp
|
||||
/* The \fBpostsuper\fR exit status is non-zero when no message queue
|
||||
/* file was deleted.
|
||||
/* Specify \fB-d ALL\fR to remove all messages; for example, specify
|
||||
/* \fB-d ALL deferred\fR to delete mail in the \fBdeferred\fR queue.
|
||||
/* As a safety measure, the word \fBALL\fR must be specified in upper
|
||||
/* case.
|
||||
/* .sp
|
||||
/* .ft B
|
||||
/* Postfix queue IDs are reused.
|
||||
/* There is a very small possibility that postsuper deletes the
|
||||
/* wrong message file when it is executed while the Postfix mail
|
||||
/* system is running.
|
||||
@@ -36,64 +39,72 @@
|
||||
/* .sp
|
||||
/* The scenario is as follows:
|
||||
/* .RS
|
||||
/* .IP \(bu
|
||||
/* The Postfix queue manager deletes the file that \fBpostsuper\fR
|
||||
/* was supposed to delete, because Postfix was finished with the
|
||||
/* .IP 1)
|
||||
/* The Postfix queue manager deletes the message that \fBpostsuper\fR
|
||||
/* is supposed to delete, because Postfix is finished with the
|
||||
/* message.
|
||||
/* .IP \(bu
|
||||
/* .IP 2)
|
||||
/* New mail arrives, and the new message is given the same queue ID
|
||||
/* as the message that \fBpostsuper\fR was supposed to delete.
|
||||
/* as the message that \fBpostsuper\fR is supposed to delete.
|
||||
/* The probability for reusing a deleted queue ID is about 1 in 2**15
|
||||
/* (the number of different microsecond values that the system clock
|
||||
/* can distinguish within a second).
|
||||
/* .IP \(bu
|
||||
/* \fBpostsuper\fR deletes the new message file, instead of the
|
||||
/* old file that should have been deleted.
|
||||
/* .IP 3)
|
||||
/* \fBpostsuper\fR deletes the new message, instead of the old
|
||||
/* message that it should have deleted.
|
||||
/* .RE
|
||||
/* .IP \fB-R\fR
|
||||
/* This option ignores any \fIdirectory\fR argument(s).
|
||||
/* Requeue all message queue files. This option is useful for
|
||||
/* restoring a Postfix queue from another machine or from backup.
|
||||
/* .sp
|
||||
/* Each queue file is moved to the maildrop queue, from where
|
||||
/* it is copied by the pickup daemon to a new file whose name
|
||||
/* is guaranteed to match the queue file inode number. The
|
||||
/* new queue file is subjected again to address rewriting and
|
||||
/* substitution. This is useful when rewriting rules or virtual
|
||||
/* mappings have changed.
|
||||
/* .IP \fB-r \fIqueue_id\fR
|
||||
/* This option ignores any \fIdirectory\fR argument(s).
|
||||
/* Requeue one message queue file with the named queue ID. Specify
|
||||
/* multiple \fB-r\fR options to requeue multiple queue files by name.
|
||||
/* .sp
|
||||
/* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, the
|
||||
/* program reads queue IDs from standard input.
|
||||
/* .sp
|
||||
/* The queue file is moved to the maildrop queue, from where
|
||||
/* it is copied by the pickup daemon to a new file whose name
|
||||
/* is guaranteed to match the queue file inode number. The
|
||||
/* new queue file is subjected again to address rewriting and
|
||||
/* substitution. This is useful when rewriting rules or virtual
|
||||
/* mappings have changed.
|
||||
/* .sp
|
||||
/* The \fBpostsuper\fR exit status is non-zero when no message queue
|
||||
/* file was requeued.
|
||||
/* .IP \fB-s\fR
|
||||
/* Structure check. Move queue files that are in the wrong place
|
||||
/* in the file system hierarchy and remove subdirectories that are
|
||||
/* no longer needed. File rearrangements are necessary after a change
|
||||
/* in the \fBhash_queue_names\fR and/or \fBhash_queue_depth\fR
|
||||
/* configuration parameters. It is highly recommended to run this
|
||||
/* check once before Postfix startup.
|
||||
/* .IP \fB-p\fR
|
||||
/* Purge stale files (files that are left over after system or
|
||||
/* software crashes).
|
||||
/* Purge old temporary files that are left over after system or
|
||||
/* software crashes.
|
||||
/* .IP "\fB-r \fIqueue_id\fR"
|
||||
/* Requeue the message with the named queue ID from the named
|
||||
/* mail queue(s) (default: \fBincoming\fR, \fBactive\fR and
|
||||
/* \fBdeferred\fR).
|
||||
/* To requeue multiple messages, specify multiple \fB-r\fR
|
||||
/* command-line options.
|
||||
/* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified,
|
||||
/* the program reads queue IDs from standard input.
|
||||
/* .sp
|
||||
/* Specify \fB-r ALL\fR to requeue all messages. As a safety
|
||||
/* measure, the word \fBALL\fR must be specified in upper case.
|
||||
/* .sp
|
||||
/* A requeued message is moved to the \fBmaildrop\fR queue, from
|
||||
/* where it is copied by the pickup daemon to a new file whose name
|
||||
/* is guaranteed to match the new queue file inode number. The
|
||||
/* new queue file is subjected again to mail address rewriting and
|
||||
/* substitution. This is useful when rewriting rules or virtual
|
||||
/* mappings have changed.
|
||||
/* .sp
|
||||
/* Postfix queue IDs are reused.
|
||||
/* There is a very small possibility that \fBpostsuper\fR requeues
|
||||
/* the wrong message file when it is executed while the Postfix mail
|
||||
/* system is running, but no harm should be done.
|
||||
/* .IP \fB-s\fR
|
||||
/* Structure check and structure repair. It is highly recommended
|
||||
/* to perform this operation once before Postfix startup.
|
||||
/* .RS
|
||||
/* .IP \(bu
|
||||
/* Rename files whose name does not match the message file inode
|
||||
/* number. This operation is necessary after restoring a mail queue
|
||||
/* from a different machine, or from backup media.
|
||||
/* .IP \(bu
|
||||
/* Move queue files that are in the wrong place in the file system
|
||||
/* hierarchy and remove subdirectories that are no longer needed.
|
||||
/* File position rearrangements are necessary after a change in the
|
||||
/* \fBhash_queue_names\fR and/or \fBhash_queue_depth\fR
|
||||
/* configuration parameters.
|
||||
/* .RE
|
||||
/* .IP \fB-v\fR
|
||||
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
|
||||
/* options make the software increasingly verbose.
|
||||
/* DIAGNOSTICS
|
||||
/* Problems are reported to the standard error stream and to
|
||||
/* \fBsyslogd\fR.
|
||||
/*
|
||||
/* \fBpostsuper\fR reports the number of messages deleted with \fB-d\fR,
|
||||
/* the number of messages requeued with \fB-r\fR, and the number of
|
||||
/* messages whose queue file name was fixed with \fB-s\fR. The report
|
||||
/* is written to the standard error stream and to \fBsyslogd\fR.
|
||||
/* CONFIGURATION PARAMETERS
|
||||
/* .ad
|
||||
/* .fi
|
||||
@@ -123,6 +134,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h> /* remove() */
|
||||
|
||||
/* Utility library. */
|
||||
@@ -155,9 +167,10 @@
|
||||
|
||||
#define ACTION_STRUCT (1<<0) /* fix file organization */
|
||||
#define ACTION_PURGE (1<<1) /* purge old temp files */
|
||||
#define ACTION_DELETE (1<<2) /* delete named queue file(s) */
|
||||
#define ACTION_REQUEUE (1<<3) /* requeue named queue file(s) */
|
||||
#define ACTION_REQUEUE_ALL (1<<4) /* requeue all queue file(s) */
|
||||
#define ACTION_DELETE_ONE (1<<2) /* delete named queue file(s) */
|
||||
#define ACTION_DELETE_ALL (1<<3) /* delete all queue file(s) */
|
||||
#define ACTION_REQUEUE_ONE (1<<4) /* requeue named queue file(s) */
|
||||
#define ACTION_REQUEUE_ALL (1<<5) /* requeue all queue file(s) */
|
||||
|
||||
#define ACTION_DEFAULT (ACTION_STRUCT | ACTION_PURGE)
|
||||
|
||||
@@ -188,78 +201,144 @@ static struct queue_info queue_info[] = {
|
||||
0,
|
||||
};
|
||||
|
||||
/* postunlink - remove file with prejudice */
|
||||
/*
|
||||
* Directories with per-message meta files.
|
||||
*/
|
||||
const char *log_queue_names[] = {
|
||||
MAIL_QUEUE_BOUNCE,
|
||||
MAIL_QUEUE_DEFER,
|
||||
0,
|
||||
};
|
||||
|
||||
static int postunlink(const char *path)
|
||||
/*
|
||||
* Cruft that we append to a file name when a queue ID is named after the
|
||||
* message file inode number. This cruft must not pass mail_queue_id_ok() so
|
||||
* that the queue manager will ignore it, should people be so unwise as to
|
||||
* run this operation on a live mail system.
|
||||
*/
|
||||
#define SUFFIX "#FIX"
|
||||
#define SUFFIX_LEN 4
|
||||
|
||||
/*
|
||||
* Grr. These counters are global, because C only has clumsy ways to return
|
||||
* multiple results from a function.
|
||||
*/
|
||||
static int message_requeued = 0; /* requeued messages */
|
||||
static int message_deleted = 0; /* deleted messages */
|
||||
static int inode_fixed = 0; /* queue id matched to inode number */
|
||||
static int inode_mismatch = 0; /* queue id inode mismatch */
|
||||
static int position_mismatch = 0; /* file position mismatch */
|
||||
|
||||
/*
|
||||
* Silly little macros. These translate arcane expressions into something
|
||||
* more at a conceptual level.
|
||||
*/
|
||||
#define MESSAGE_QUEUE(qp) ((qp)->perms == MAIL_QUEUE_STAT_READY)
|
||||
#define READY_MESSAGE(st) (((st).st_mode & S_IRWXU) == MAIL_QUEUE_STAT_READY)
|
||||
|
||||
/* find_queue_info - look up expected permissions field by queue name */
|
||||
|
||||
static struct queue_info *find_queue_info(const char *queue_name)
|
||||
{
|
||||
struct queue_info *qp;
|
||||
|
||||
for (qp = queue_info; qp->name; qp++)
|
||||
if (strcmp(queue_name, qp->name) == 0)
|
||||
return (qp);
|
||||
msg_fatal("invalid directory name: %s", queue_name);
|
||||
}
|
||||
|
||||
/* postremove - remove file with extreme prejudice */
|
||||
|
||||
static int postremove(const char *path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = unlink(path)) == 0) {
|
||||
if ((ret = remove(path)) < 0) {
|
||||
if (errno != ENOENT)
|
||||
msg_fatal("remove file %s: %m", path);
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("removed file %s", path);
|
||||
} else if (errno != ENOENT) {
|
||||
msg_warn("remove file %s: %m", path);
|
||||
} else if (msg_verbose) {
|
||||
msg_info("remove file %s: %m", path);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* postrename - rename file with prejudice */
|
||||
/* postrename - rename file with extreme prejudice */
|
||||
|
||||
static int postrename(const char *old, const char *new)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = sane_rename(old, new)) == 0) {
|
||||
msg_info("requeued file %s as %s", old, new);
|
||||
} else if (errno != ENOENT) {
|
||||
msg_warn("requeue file %s as %s: %m", old, new);
|
||||
} else if (msg_verbose) {
|
||||
msg_info("requeue file %s as %s: %m", old, new);
|
||||
if ((ret = sane_rename(old, new)) < 0) {
|
||||
if (errno != ENOENT
|
||||
|| mail_queue_mkdirs(new) < 0
|
||||
|| sane_rename(old, new) < 0)
|
||||
if (errno != ENOENT)
|
||||
msg_fatal("rename file %s as %s: %m", old, new);
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("renamed file %s as %s", old, new);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* postrmdir - remove directory with extreme prejudice */
|
||||
|
||||
static int postrmdir(const char *path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = rmdir(path)) < 0) {
|
||||
if (errno != ENOENT)
|
||||
msg_fatal("remove directory %s: %m", path);
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("remove directory %s", path);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* delete_one - delete one message instance and all its associated files */
|
||||
|
||||
static int delete_one(const char *queue_id)
|
||||
static int delete_one(const char **queue_names, const char *queue_id)
|
||||
{
|
||||
const char *msg_queue_names[] = {
|
||||
MAIL_QUEUE_MAILDROP,
|
||||
MAIL_QUEUE_INCOMING, /* twice, to avoid */
|
||||
MAIL_QUEUE_ACTIVE, /* missing a file while */
|
||||
MAIL_QUEUE_DEFERRED, /* it is being renamed */
|
||||
MAIL_QUEUE_INCOMING, /* this is not 100% */
|
||||
MAIL_QUEUE_ACTIVE, /* foolproof but adequate */
|
||||
0,
|
||||
};
|
||||
const char *log_queue_names[] = {
|
||||
MAIL_QUEUE_BOUNCE,
|
||||
MAIL_QUEUE_DEFER,
|
||||
0,
|
||||
};
|
||||
struct stat st;
|
||||
const char **msg_qpp;
|
||||
const char **log_qpp;
|
||||
const char *msg_path;
|
||||
VSTRING *log_path_buf = vstring_alloc(100);
|
||||
int found = 0;
|
||||
VSTRING *log_path_buf;
|
||||
int found;
|
||||
int tries;
|
||||
|
||||
/*
|
||||
* Delete defer or bounce logfiles before deleting the corresponding
|
||||
* message file, and only if the message file exists. This minimizes but
|
||||
* does not eliminate a race condition with queue ID reuse which results
|
||||
* in deleting the wrong files.
|
||||
* Sanity check. No early returns beyond this point.
|
||||
*/
|
||||
for (msg_qpp = msg_queue_names; *msg_qpp != 0; msg_qpp++) {
|
||||
if (!mail_queue_id_ok(queue_id)) {
|
||||
msg_warn("invalid mail queue id: %s", queue_id);
|
||||
return (0);
|
||||
}
|
||||
log_path_buf = vstring_alloc(100);
|
||||
|
||||
/*
|
||||
* Skip meta file directories. Delete defer or bounce logfiles before
|
||||
* deleting the corresponding message file, and only if the message file
|
||||
* exists. This minimizes but does not eliminate a race condition with
|
||||
* queue ID reuse which results in deleting the wrong files.
|
||||
*/
|
||||
for (found = 0, tries = 0; found == 0 && tries < 2; tries++) {
|
||||
for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) {
|
||||
if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp)))
|
||||
continue;
|
||||
if (mail_open_ok(*msg_qpp, queue_id, &st, &msg_path) != MAIL_OPEN_YES)
|
||||
continue;
|
||||
for (log_qpp = log_queue_names; *log_qpp != 0; log_qpp++)
|
||||
postunlink(mail_queue_path(log_path_buf, *log_qpp, queue_id));
|
||||
if (postunlink(msg_path) == 0) {
|
||||
postremove(mail_queue_path(log_path_buf, *log_qpp, queue_id));
|
||||
if (postremove(msg_path) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
} /* else: lost a race */
|
||||
} /* else: maybe lost a race */
|
||||
}
|
||||
}
|
||||
vstring_free(log_path_buf);
|
||||
return (found);
|
||||
@@ -267,35 +346,44 @@ static int delete_one(const char *queue_id)
|
||||
|
||||
/* requeue_one - requeue one message instance and delete its logfiles */
|
||||
|
||||
static int requeue_one(const char *queue_id)
|
||||
static int requeue_one(const char **queue_names, const char *queue_id)
|
||||
{
|
||||
const char *msg_queue_names[] = {
|
||||
MAIL_QUEUE_INCOMING, /* twice, to avoid */
|
||||
MAIL_QUEUE_ACTIVE, /* missing a file while */
|
||||
MAIL_QUEUE_DEFERRED, /* it is being renamed */
|
||||
MAIL_QUEUE_INCOMING, /* this is not 100% */
|
||||
MAIL_QUEUE_ACTIVE, /* foolproof but adequate */
|
||||
0,
|
||||
};
|
||||
struct stat st;
|
||||
const char **msg_qpp;
|
||||
const char *old_path;
|
||||
VSTRING *new_path_buf = vstring_alloc(100);
|
||||
int found = 0;
|
||||
VSTRING *new_path_buf;
|
||||
int found;
|
||||
int tries;
|
||||
|
||||
/*
|
||||
* Do not delete defer or bounce logfiles, to avoid losing a race where
|
||||
* the queue manager decides to bounce mail after all recipients have
|
||||
* been tried.
|
||||
* Sanity check. No early returns beyond this point.
|
||||
*/
|
||||
for (msg_qpp = msg_queue_names; *msg_qpp != 0; msg_qpp++) {
|
||||
if (!mail_queue_id_ok(queue_id)) {
|
||||
msg_warn("invalid mail queue id: %s", queue_id);
|
||||
return (0);
|
||||
}
|
||||
new_path_buf = vstring_alloc(100);
|
||||
|
||||
/*
|
||||
* Skip meta file directories. Like the mass requeue operation, we not
|
||||
* delete defer or bounce logfiles, to avoid losing a race where the
|
||||
* queue manager decides to bounce mail after all recipients have been
|
||||
* tried.
|
||||
*/
|
||||
for (found = 0, tries = 0; found == 0 && tries < 2; tries++) {
|
||||
for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) {
|
||||
if (strcmp(*msg_qpp, MAIL_QUEUE_MAILDROP) == 0)
|
||||
continue;
|
||||
if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp)))
|
||||
continue;
|
||||
if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES)
|
||||
continue;
|
||||
(void) mail_queue_path(new_path_buf, MAIL_QUEUE_MAILDROP, queue_id);
|
||||
if (postrename(old_path, STR(new_path_buf)) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
} /* else: lost a race */
|
||||
} /* else: maybe lost a race */
|
||||
}
|
||||
}
|
||||
vstring_free(new_path_buf);
|
||||
return (found);
|
||||
@@ -303,33 +391,84 @@ static int requeue_one(const char *queue_id)
|
||||
|
||||
/* operate_stream - operate on queue IDs given on stream */
|
||||
|
||||
static int operate_stream(VSTREAM *fp, int (*operator) (const char *))
|
||||
static int operate_stream(VSTREAM *fp,
|
||||
int (*operator) (const char **, const char *),
|
||||
const char **queues)
|
||||
{
|
||||
VSTRING *buf = vstring_alloc(20);
|
||||
int found = 0;
|
||||
|
||||
while (vstring_get_nonl(buf, fp) != VSTREAM_EOF)
|
||||
found |= operator(STR(buf));
|
||||
found += operator(queues, STR(buf));
|
||||
|
||||
vstring_free(buf);
|
||||
return (found);
|
||||
}
|
||||
|
||||
/* super - check queue file location and clean up */
|
||||
/* fix_queue_id - make message queue ID match inode number */
|
||||
|
||||
static void super(char **queues, int action)
|
||||
static int fix_queue_id(const char *actual_path, const char *actual_queue,
|
||||
const char *actual_id, ino_t inum)
|
||||
{
|
||||
VSTRING *old_path = vstring_alloc(10);
|
||||
VSTRING *new_path = vstring_alloc(10);
|
||||
VSTRING *new_id = vstring_alloc(10);
|
||||
const char **log_qpp;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Create the new queue ID from the existing time digits and from the new
|
||||
* inode number. Since we are renaming multiple files, the new name must
|
||||
* be deterministic so that we can recover even when the renaming
|
||||
* operation is interrupted in the middle.
|
||||
*/
|
||||
vstring_sprintf(new_id, "%.5s%lX", actual_id, (unsigned long) inum);
|
||||
|
||||
/*
|
||||
* Rename logfiles before renaming the message file, so that we can
|
||||
* recover when a previous attempt was interrupted.
|
||||
*/
|
||||
for (log_qpp = log_queue_names; *log_qpp; log_qpp++) {
|
||||
mail_queue_path(old_path, *log_qpp, actual_id);
|
||||
mail_queue_path(new_path, *log_qpp, STR(new_id));
|
||||
vstring_strcat(new_path, SUFFIX);
|
||||
postrename(STR(old_path), STR(new_path));
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename the message file last, so that we know that we are done with
|
||||
* this message and with all its logfiles.
|
||||
*/
|
||||
mail_queue_path(new_path, actual_queue, STR(new_id));
|
||||
vstring_strcat(new_path, SUFFIX);
|
||||
ret = postrename(actual_path, STR(new_path));
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
*/
|
||||
vstring_free(old_path);
|
||||
vstring_free(new_path);
|
||||
vstring_free(new_id);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* super - check queue structure, clean up, do wild-card operations */
|
||||
|
||||
static void super(const char **queues, int action)
|
||||
{
|
||||
ARGV *hash_queue_names = argv_split(var_hash_queue_names, " \t\r\n,");
|
||||
VSTRING *actual_path = vstring_alloc(10);
|
||||
VSTRING *wanted_path = vstring_alloc(10);
|
||||
struct stat st;
|
||||
char *queue_name;
|
||||
const char *queue_name;
|
||||
SCAN_DIR *info;
|
||||
char *path;
|
||||
int actual_depth;
|
||||
int wanted_depth;
|
||||
char **cpp;
|
||||
struct queue_info *qp;
|
||||
unsigned long inum;
|
||||
|
||||
/*
|
||||
* Make sure every file is in the right place, clean out stale files, and
|
||||
@@ -345,12 +484,7 @@ static void super(char **queues, int action)
|
||||
* file permissions to look for, and whether or not it is desirable
|
||||
* to step into subdirectories.
|
||||
*/
|
||||
for (qp = queue_info; /* void */ ; qp++) {
|
||||
if (qp->name == 0)
|
||||
msg_fatal("unknown queue name: %s", queue_name);
|
||||
if (strcmp(qp->name, queue_name) == 0)
|
||||
break;
|
||||
}
|
||||
qp = find_queue_info(queue_name);
|
||||
for (cpp = hash_queue_names->argv; /* void */ ; cpp++) {
|
||||
if (*cpp == 0) {
|
||||
wanted_depth = 0;
|
||||
@@ -383,12 +517,8 @@ static void super(char **queues, int action)
|
||||
if ((path = scan_dir_next(info)) == 0) {
|
||||
if (actual_depth == 0)
|
||||
break;
|
||||
if (actual_depth > wanted_depth) {
|
||||
if (rmdir(scan_dir_path(info)) < 0 && errno != ENOENT)
|
||||
msg_warn("remove %s: %m", scan_dir_path(info));
|
||||
else if (msg_verbose)
|
||||
msg_info("remove %s", scan_dir_path(info));
|
||||
}
|
||||
if (actual_depth > wanted_depth)
|
||||
postrmdir(scan_dir_path(info));
|
||||
scan_dir_pop(info);
|
||||
actual_depth--;
|
||||
continue;
|
||||
@@ -406,83 +536,174 @@ static void super(char **queues, int action)
|
||||
}
|
||||
|
||||
/*
|
||||
* See if this is a stale file or some non-file object. Be
|
||||
* careful not to delete bounce or defer logs just because they
|
||||
* are more than a couple days old.
|
||||
* From here on we need to keep track of operations that
|
||||
* invalidate or revalidate the actual_path and path variables,
|
||||
* otherwise we can hit the wrong files.
|
||||
*/
|
||||
vstring_sprintf(actual_path, "%s/%s", scan_dir_path(info), path);
|
||||
if (stat(STR(actual_path), &st) < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Remove alien directories. If maildrop is world writable, then
|
||||
* we cannot abort just because we cannot remove someone's
|
||||
* directory.
|
||||
*/
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (rmdir(STR(actual_path)) < 0 && errno != ENOENT)
|
||||
msg_warn("remove subdirectory %s: %m", STR(actual_path));
|
||||
else if (msg_verbose)
|
||||
msg_info("remove subdirectory %s", STR(actual_path));
|
||||
continue;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)
|
||||
|| ((action & ACTION_PURGE) != 0 &&
|
||||
(st.st_mode & S_IRWXU) != qp->perms
|
||||
&& time((time_t *) 0) > st.st_mtime + MAX_TEMP_AGE)) {
|
||||
if (remove(STR(actual_path)) < 0 && errno != ENOENT)
|
||||
msg_warn("remove %s: %m", STR(actual_path));
|
||||
else if (msg_verbose)
|
||||
msg_info("remove %s", STR(actual_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip temporary files that aren't old enough.
|
||||
*/
|
||||
if (mail_queue_id_ok(path) == 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Requeue this message. This means the pickup daemon will copy
|
||||
* it to a new queue file, and that address rewriting is applied
|
||||
* again. XXX Share more code with requeue_one(). Note, that this
|
||||
* option is intended for large-scale mail queue restore
|
||||
* operations so that at this stage, the queue file may not even
|
||||
* be in the "right" place for the current machine. We therefore
|
||||
* cannot rely on the mail_queue(3) API.()
|
||||
*/
|
||||
if ((action & ACTION_REQUEUE_ALL)
|
||||
&& strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0) {
|
||||
(void) mail_queue_path(wanted_path, MAIL_QUEUE_MAILDROP, path);
|
||||
if (rename(STR(actual_path), STR(wanted_path)) < 0) {
|
||||
if (rmdir(STR(actual_path)) < 0) {
|
||||
if (errno != ENOENT)
|
||||
msg_fatal("rename %s to %s: %m", STR(actual_path),
|
||||
STR(wanted_path));
|
||||
msg_warn("remove subdirectory %s: %m", STR(actual_path));
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("rename %s to %s", STR(actual_path),
|
||||
STR(wanted_path));
|
||||
msg_info("remove subdirectory %s", STR(actual_path));
|
||||
}
|
||||
/* No further work on this object is possible. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mass deletion. We count the deletion of mail that this system
|
||||
* has taken responsibility for. XXX This option does not use the
|
||||
* mail_queue(3) API, so that it can be run on a queue that does
|
||||
* not have files in the "right" place. It would be terribly
|
||||
* inefficient to first have to rename files into place before
|
||||
* deleting them.
|
||||
*/
|
||||
if (action & ACTION_DELETE_ALL) {
|
||||
if (postremove(STR(actual_path)) == 0)
|
||||
if (MESSAGE_QUEUE(qp) && READY_MESSAGE(st))
|
||||
message_deleted++;
|
||||
/* No further work on this object is possible. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove non-file objects and old temporary files. Be careful
|
||||
* not to delete bounce or defer logs just because they are more
|
||||
* than a couple days old.
|
||||
*/
|
||||
if (!S_ISREG(st.st_mode)
|
||||
|| ((action & ACTION_PURGE) != 0
|
||||
&& MESSAGE_QUEUE(qp)
|
||||
&& !READY_MESSAGE(st)
|
||||
&& time((time_t *) 0) > st.st_mtime + MAX_TEMP_AGE)) {
|
||||
(void) postremove(STR(actual_path));
|
||||
/* No further work on this object is possible. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip temporary message files that aren't old enough.
|
||||
*/
|
||||
if (MESSAGE_QUEUE(qp) && !READY_MESSAGE(st))
|
||||
/* No further work on this object is possible. */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Fix queueid#FIX names that were left from a previous pass over
|
||||
* the queue where message queue file names were matched to their
|
||||
* inode number. This requires that the file is already in the
|
||||
* proper directory so that we only have to strip the suffix.
|
||||
* Make sure that the name minus suffix is well formed and that
|
||||
* the name matches the file inode number.
|
||||
*/
|
||||
if (strcmp(path + (strlen(path) - SUFFIX_LEN), SUFFIX) == 0) {
|
||||
path[strlen(path) - SUFFIX_LEN] = 0; /* XXX */
|
||||
if (!mail_queue_id_ok(path)) {
|
||||
msg_warn("bogus file name: %s", STR(actual_path));
|
||||
continue;
|
||||
}
|
||||
if (MESSAGE_QUEUE(qp)) {
|
||||
if (sscanf(path + 5, "%lx", &inum) != 1) {
|
||||
msg_warn("bogus file name: %s", STR(actual_path));
|
||||
continue;
|
||||
}
|
||||
if (inum != (unsigned long) st.st_ino) {
|
||||
msg_warn("name/inode mismatch: %s", STR(actual_path));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
vstring_strncpy(wanted_path, STR(actual_path),
|
||||
strlen(STR(actual_path)) - SUFFIX_LEN);
|
||||
if (postrename(STR(actual_path), STR(wanted_path)) < 0) {
|
||||
/* No further work on this object is possible. */
|
||||
continue;
|
||||
} else {
|
||||
if (MESSAGE_QUEUE(qp))
|
||||
inode_fixed++;
|
||||
vstring_strcpy(actual_path, STR(wanted_path));
|
||||
/* At this point, path and actual_path are revalidated. */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over files with illegal names. The library routines
|
||||
* refuse to operate on them.
|
||||
*/
|
||||
if (!mail_queue_id_ok(path)) {
|
||||
msg_warn("bogus file name: %s", STR(actual_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mass requeuing. The pickup daemon will copy requeued mail to a
|
||||
* new queue file, so that address rewriting is applied again.
|
||||
* XXX This option does not use the mail_queue(3) API, so that it
|
||||
* can be run on a queue that does not have the files in the
|
||||
* "right" place. It would be terribly inefficient to first have
|
||||
* to rename files into place before requeuing them. Like the
|
||||
* requeue_one() routine, this code does not touch logfiles.
|
||||
*/
|
||||
if ((action & ACTION_REQUEUE_ALL)
|
||||
&& MESSAGE_QUEUE(qp)
|
||||
&& strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0) {
|
||||
(void) mail_queue_path(wanted_path, MAIL_QUEUE_MAILDROP, path);
|
||||
if (postrename(STR(actual_path), STR(wanted_path)) == 0)
|
||||
message_requeued++;
|
||||
/* At this point, path and actual_path are invalidated. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the file name matches the file inode number. Skip meta
|
||||
* file directories. This option requires that meta files be put
|
||||
* into their proper place before queue files, so that we can
|
||||
* rename queue files and meta files at the same time. Mis-named
|
||||
* files are renamed to newqueueid#FIX on the first pass, and
|
||||
* upon the second pass the #FIX is stripped off the name. Of
|
||||
* course we have to be prepared that the program is interrupted
|
||||
* before it completes, so any left-over newqueueid#FIX files
|
||||
* have to be handled properly. XXX This option does not use the
|
||||
* mail_queue(3) API for message queue files, so that it can be
|
||||
* run on a queue that does not have message queue files in the
|
||||
* "right" place. It would be terribly inefficient to first have
|
||||
* to rename files into place before fixing the file names.
|
||||
*/
|
||||
if ((action & ACTION_STRUCT) != 0 && MESSAGE_QUEUE(qp)) {
|
||||
if (sscanf(path + 5, "%lx", &inum) != 1) {
|
||||
msg_warn("bogus file name: %s", STR(actual_path));
|
||||
continue;
|
||||
}
|
||||
if (inum != (unsigned long) st.st_ino) {
|
||||
inode_mismatch++; /* before we fix */
|
||||
fix_queue_id(STR(actual_path), queue_name, path, st.st_ino);
|
||||
/* At this point, path and actual_path are invalidated. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See if this file sits in the right place in the file system
|
||||
* hierarchy. Its place may be wrong after a change to the
|
||||
* hash_queue_{names,depth} parameter settings. The implied
|
||||
* mkdir() operation is the main reason for this command to run
|
||||
* with postfix privilege. The mail_queue_mkdirs() routine could
|
||||
* be fixed to use the "right" privilege, but it is a good idea
|
||||
* to do everything with the postfix owner privileges regardless,
|
||||
* in order to limit the amount of damage that we can do.
|
||||
* hash_queue_{names,depth} parameter settings.
|
||||
*/
|
||||
if (action & ACTION_STRUCT) {
|
||||
(void) mail_queue_path(wanted_path, queue_name, path);
|
||||
if (strcmp(STR(actual_path), STR(wanted_path)) != 0) {
|
||||
if (rename(STR(actual_path), STR(wanted_path)) < 0)
|
||||
if (errno != ENOENT
|
||||
|| mail_queue_mkdirs(STR(wanted_path)) < 0
|
||||
|| rename(STR(actual_path), STR(wanted_path)) < 0)
|
||||
msg_fatal("rename %s to %s: %m", STR(actual_path),
|
||||
STR(wanted_path));
|
||||
if (msg_verbose)
|
||||
msg_info("rename %s to %s", STR(actual_path),
|
||||
STR(wanted_path));
|
||||
position_mismatch++; /* before we fix */
|
||||
(void) postrename(STR(actual_path), STR(wanted_path));
|
||||
/* At this point, path and actual_path are invalidated. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,27 +718,43 @@ static void super(char **queues, int action)
|
||||
argv_free(hash_queue_names);
|
||||
}
|
||||
|
||||
/* fatal_exit - print warning if queue fix is incomplete */
|
||||
|
||||
static void fatal_exit(void)
|
||||
{
|
||||
if (inode_mismatch > 0 || inode_fixed > 0 || position_mismatch > 0)
|
||||
msg_fatal("OPERATION INCOMPLETE -- RERUN COMMAND TO FIX THE QUEUE FIRST");
|
||||
}
|
||||
|
||||
/* interrupted - signal handler */
|
||||
|
||||
static void interrupted(int unused_sig)
|
||||
{
|
||||
fatal_exit();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
char *slash;
|
||||
int debug_me = 0;
|
||||
int action = 0;
|
||||
char **queues;
|
||||
const char **queues;
|
||||
int c;
|
||||
int found = 0;
|
||||
ARGV *requeue_names = 0;
|
||||
ARGV *delete_names = 0;
|
||||
char **cpp;
|
||||
|
||||
/*
|
||||
* Defaults.
|
||||
*/
|
||||
static char *default_queues[] = {
|
||||
MAIL_QUEUE_DEFER, /* before message directories */
|
||||
MAIL_QUEUE_BOUNCE, /* before message directories */
|
||||
MAIL_QUEUE_MAILDROP,
|
||||
MAIL_QUEUE_INCOMING,
|
||||
MAIL_QUEUE_ACTIVE,
|
||||
MAIL_QUEUE_DEFERRED,
|
||||
MAIL_QUEUE_DEFER,
|
||||
MAIL_QUEUE_BOUNCE,
|
||||
MAIL_QUEUE_FLUSH,
|
||||
0,
|
||||
};
|
||||
@@ -544,8 +781,6 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
if (safe_getenv(CONF_ENV_VERB))
|
||||
msg_verbose = 1;
|
||||
if (safe_getenv(CONF_ENV_DEBUG))
|
||||
debug_me = 1;
|
||||
|
||||
/*
|
||||
* Initialize. Set up logging, read the global configuration file and
|
||||
@@ -561,6 +796,17 @@ int main(int argc, char **argv)
|
||||
if (chdir(var_queue_dir))
|
||||
msg_fatal("chdir %s: %m", var_queue_dir);
|
||||
|
||||
/*
|
||||
* Be sure to log a warning if we do not finish structural repair. Maybe
|
||||
* we should have an fsck-style "clean" flag so Postfix will not start
|
||||
* with a broken queue.
|
||||
*/
|
||||
signal(SIGHUP, interrupted);
|
||||
signal(SIGINT, interrupted);
|
||||
signal(SIGQUIT, interrupted);
|
||||
signal(SIGTERM, interrupted);
|
||||
msg_cleanup(fatal_exit);
|
||||
|
||||
/*
|
||||
* All file/directory updates must be done as the mail system owner. This
|
||||
* is because Postfix daemons manipulate the queue with those same
|
||||
@@ -579,30 +825,27 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Parse JCL.
|
||||
*/
|
||||
while ((c = GETOPT(argc, argv, "d:spv")) > 0) {
|
||||
while ((c = GETOPT(argc, argv, "d:pr:sv")) > 0) {
|
||||
switch (c) {
|
||||
default:
|
||||
msg_fatal("usage: %s [-d queue_id (delete message)] [-p (purge stale files)] [-r queue_id (requeue message)] [-R (requeue all)] [-s (fix structure)]",
|
||||
msg_fatal("usage: %s [-d queue_id (delete)] [-p (purge temporary files)] [-r queue_id (requeue)] [-s (structure fix)]",
|
||||
argv[0]);
|
||||
case 'd':
|
||||
if (strcmp(optarg, "-") == 0)
|
||||
found |= operate_stream(VSTREAM_IN, delete_one);
|
||||
else
|
||||
found |= delete_one(optarg);
|
||||
action |= ACTION_DELETE;
|
||||
if (delete_names == 0)
|
||||
delete_names = argv_alloc(1);
|
||||
argv_add(delete_names, optarg, (char *) 0);
|
||||
action |= (strcmp(optarg, "ALL") == 0 ?
|
||||
ACTION_DELETE_ALL : ACTION_DELETE_ONE);
|
||||
break;
|
||||
case 'p':
|
||||
action |= ACTION_PURGE;
|
||||
break;
|
||||
case 'r':
|
||||
if (strcmp(optarg, "-") == 0)
|
||||
found |= operate_stream(VSTREAM_IN, requeue_one);
|
||||
else
|
||||
found |= requeue_one(optarg);
|
||||
action |= ACTION_REQUEUE;
|
||||
break;
|
||||
case 'R':
|
||||
action |= ACTION_REQUEUE_ALL;
|
||||
if (requeue_names == 0)
|
||||
requeue_names = argv_alloc(1);
|
||||
argv_add(requeue_names, optarg, (char *) 0);
|
||||
action |= (strcmp(optarg, "ALL") == 0 ?
|
||||
ACTION_REQUEUE_ALL : ACTION_REQUEUE_ONE);
|
||||
break;
|
||||
case 's':
|
||||
action |= ACTION_STRUCT;
|
||||
@@ -616,17 +859,94 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Execute the explicitly specified (or default) action, on the
|
||||
* explicitly specified (or default) queues.
|
||||
*
|
||||
* XXX Work around gcc const brain damage.
|
||||
*/
|
||||
if (action == 0)
|
||||
action = ACTION_DEFAULT;
|
||||
if (argv[optind] == 0)
|
||||
queues = default_queues;
|
||||
queues = (const char **) default_queues;
|
||||
else
|
||||
queues = argv + optind;
|
||||
queues = (const char **) argv + optind;
|
||||
|
||||
#define ACTIONS_ON_THE_FLY (ACTION_DELETE | ACTION_REQUEUE)
|
||||
#define ACTIONS_BY_QUEUE_ID (ACTION_DELETE_ONE | ACTION_REQUEUE_ONE)
|
||||
|
||||
if (action & ~ACTIONS_ON_THE_FLY)
|
||||
super(queues, action & ~ACTIONS_ON_THE_FLY);
|
||||
exit((action & ACTIONS_ON_THE_FLY) ? !found : 0);
|
||||
/*
|
||||
* Basic queue maintenance, as well as mass deletion, mass requeuing, and
|
||||
* mass name-to-inode fixing. This ensures that queue files are in the
|
||||
* right place before the queue file by name operations are done.
|
||||
*/
|
||||
if (action & ~ACTIONS_BY_QUEUE_ID)
|
||||
super(queues, action & ~ACTIONS_BY_QUEUE_ID);
|
||||
if (inode_mismatch > 0)
|
||||
super(queues, 0);
|
||||
|
||||
/*
|
||||
* Delete queue files by name. This must not be done when queue files
|
||||
* have changed names as a result of the structure check, because we
|
||||
* could be deleiting the wrong message.
|
||||
*/
|
||||
if (action & ACTION_DELETE_ONE) {
|
||||
if (inode_mismatch > 0 || inode_fixed > 0) {
|
||||
msg_error("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS");
|
||||
msg_fatal("CHECK YOUR QUEUE IDS AND RE-ISSUE THE COMMAND");
|
||||
}
|
||||
argv_terminate(delete_names);
|
||||
for (cpp = delete_names->argv; *cpp; cpp++) {
|
||||
if (strcmp(*cpp, "ALL") == 0)
|
||||
continue;
|
||||
if (strcmp(*cpp, "-") == 0)
|
||||
message_deleted +=
|
||||
operate_stream(VSTREAM_IN, delete_one, queues);
|
||||
else
|
||||
message_deleted += delete_one(queues, *cpp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Requeue queue files by name. This must not be done when queue files
|
||||
* have changed names as a result of the structure check, because we
|
||||
* could be requeuing the wrong message.
|
||||
*/
|
||||
if (action & ACTION_REQUEUE_ONE) {
|
||||
if (inode_mismatch > 0 || inode_fixed > 0) {
|
||||
msg_error("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS");
|
||||
msg_fatal("CHECK YOUR QUEUE IDS AND RE-ISSUE THE COMMAND");
|
||||
}
|
||||
argv_terminate(requeue_names);
|
||||
for (cpp = requeue_names->argv; *cpp; cpp++) {
|
||||
if (strcmp(*cpp, "ALL") == 0)
|
||||
continue;
|
||||
if (strcmp(*cpp, "-") == 0)
|
||||
message_requeued +=
|
||||
operate_stream(VSTREAM_IN, requeue_one, queues);
|
||||
else
|
||||
message_requeued += requeue_one(queues, *cpp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Report.
|
||||
*/
|
||||
if (message_requeued > 0)
|
||||
msg_info("Requeued: %d message%s", message_requeued,
|
||||
message_requeued > 1 ? "s" : "");
|
||||
if (message_deleted > 0)
|
||||
msg_info("Deleted: %d message%s", message_deleted,
|
||||
message_deleted > 1 ? "s" : "");
|
||||
if (inode_fixed > 0)
|
||||
msg_info("Renamed to match inode number: %d message%s", inode_fixed,
|
||||
inode_fixed > 1 ? "s" : "");
|
||||
if (inode_mismatch > 0 || inode_fixed > 0)
|
||||
msg_warn("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS");
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
*/
|
||||
if (requeue_names)
|
||||
argv_free(requeue_names);
|
||||
if (delete_names)
|
||||
argv_free(delete_names);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
@@ -584,6 +584,8 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
||||
ldap_msgfree(res);
|
||||
if (filter_buf != 0)
|
||||
vstring_free(filter_buf);
|
||||
if (escaped_name != 0)
|
||||
vstring_free(escaped_name);
|
||||
|
||||
/*
|
||||
* If we had an error, return nothing, Otherwise, return the result, if
|
||||
|
Reference in New Issue
Block a user