Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / postsuper / postsuper.c
blob6434323102077690fb6a757950ca89a081d37163
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* postsuper 1
6 /* SUMMARY
7 /* Postfix superintendent
8 /* SYNOPSIS
9 /* .fi
10 /* \fBpostsuper\fR [\fB-psv\fR]
11 /* [\fB-c \fIconfig_dir\fR] [\fB-d \fIqueue_id\fR]
12 /* [\fB-h \fIqueue_id\fR] [\fB-H \fIqueue_id\fR]
13 /* [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR]
14 /* DESCRIPTION
15 /* The \fBpostsuper\fR(1) command does maintenance jobs on the Postfix
16 /* queue. Use of the command is restricted to the superuser.
17 /* See the \fBpostqueue\fR(1) command for unprivileged queue operations
18 /* such as listing or flushing the mail queue.
20 /* By default, \fBpostsuper\fR(1) performs the operations
21 /* requested with the
22 /* \fB-s\fR and \fB-p\fR command-line options on all Postfix queue
23 /* directories - this includes the \fBincoming\fR, \fBactive\fR and
24 /* \fBdeferred\fR directories with mail files and the \fBbounce\fR,
25 /* \fBdefer\fR, \fBtrace\fR and \fBflush\fR directories with log files.
27 /* Options:
28 /* .IP "\fB-c \fIconfig_dir\fR"
29 /* The \fBmain.cf\fR configuration file is in the named directory
30 /* instead of the default configuration directory. See also the
31 /* MAIL_CONFIG environment setting below.
32 /* .IP "\fB-d \fIqueue_id\fR"
33 /* Delete one message with the named queue ID from the named
34 /* mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and
35 /* \fBdeferred\fR).
37 /* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
38 /* queue IDs from standard input. For example, to delete all mail
39 /* with exactly one recipient \fBuser@example.com\fR:
40 /* .sp
41 /* .nf
42 /* mailq | tail +2 | grep -v '^ *(' | awk \'BEGIN { RS = "" }
43 /* # $7=sender, $8=recipient1, $9=recipient2
44 /* { if ($8 == "user@example.com" && $9 == "")
45 /* print $1 }
46 /* \' | tr -d '*!' | postsuper -d -
47 /* .fi
48 /* .sp
49 /* Specify "\fB-d ALL\fR" to remove all messages; for example, specify
50 /* "\fB-d ALL deferred\fR" to delete all mail in the \fBdeferred\fR queue.
51 /* As a safety measure, the word \fBALL\fR must be specified in upper
52 /* case.
53 /* .sp
54 /* Warning: Postfix queue IDs are reused.
55 /* There is a very small possibility that postsuper deletes the
56 /* wrong message file when it is executed while the Postfix mail
57 /* system is delivering mail.
58 /* .sp
59 /* The scenario is as follows:
60 /* .RS
61 /* .IP 1)
62 /* The Postfix queue manager deletes the message that \fBpostsuper\fR(1)
63 /* is asked to delete, because Postfix is finished with the
64 /* message (it is delivered, or it is returned to the sender).
65 /* .IP 2)
66 /* New mail arrives, and the new message is given the same queue ID
67 /* as the message that \fBpostsuper\fR(1) is supposed to delete.
68 /* The probability for reusing a deleted queue ID is about 1 in 2**15
69 /* (the number of different microsecond values that the system clock
70 /* can distinguish within a second).
71 /* .IP 3)
72 /* \fBpostsuper\fR(1) deletes the new message, instead of the old
73 /* message that it should have deleted.
74 /* .RE
75 /* .IP "\fB-h \fIqueue_id\fR"
76 /* Put mail "on hold" so that no attempt is made to deliver it.
77 /* Move one message with the named queue ID from the named
78 /* mail queue(s) (default: \fBincoming\fR, \fBactive\fR and
79 /* \fBdeferred\fR) to the \fBhold\fR queue.
81 /* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
82 /* queue IDs from standard input.
83 /* .sp
84 /* Specify "\fB-h ALL\fR" to hold all messages; for example, specify
85 /* "\fB-h ALL deferred\fR" to hold all mail in the \fBdeferred\fR queue.
86 /* As a safety measure, the word \fBALL\fR must be specified in upper
87 /* case.
88 /* .sp
89 /* Note: while mail is "on hold" it will not expire when its
90 /* time in the queue exceeds the \fBmaximal_queue_lifetime\fR
91 /* or \fBbounce_queue_lifetime\fR setting. It becomes subject to
92 /* expiration after it is released from "hold".
93 /* .sp
94 /* This feature is available in Postfix 2.0 and later.
95 /* .IP "\fB-H \fIqueue_id\fR"
96 /* Release mail that was put "on hold".
97 /* Move one message with the named queue ID from the named
98 /* mail queue(s) (default: \fBhold\fR) to the \fBdeferred\fR queue.
100 /* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads
101 /* queue IDs from standard input.
102 /* .sp
103 /* Note: specify "\fBpostsuper -r\fR" to release mail that was kept on
104 /* hold for a significant fraction of \fB$maximal_queue_lifetime\fR
105 /* or \fB$bounce_queue_lifetime\fR, or longer.
106 /* .sp
107 /* Specify "\fB-H ALL\fR" to release all mail that is "on hold".
108 /* As a safety measure, the word \fBALL\fR must be specified in upper
109 /* case.
110 /* .sp
111 /* This feature is available in Postfix 2.0 and later.
112 /* .IP \fB-p\fR
113 /* Purge old temporary files that are left over after system or
114 /* software crashes.
115 /* .IP "\fB-r \fIqueue_id\fR"
116 /* Requeue the message with the named queue ID from the named
117 /* mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and
118 /* \fBdeferred\fR).
119 /* To requeue multiple messages, specify multiple \fB-r\fR
120 /* command-line options.
122 /* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified,
123 /* the program reads queue IDs from standard input.
124 /* .sp
125 /* Specify "\fB-r ALL\fR" to requeue all messages. As a safety
126 /* measure, the word \fBALL\fR must be specified in upper case.
127 /* .sp
128 /* A requeued message is moved to the \fBmaildrop\fR queue,
129 /* from where it is copied by the \fBpickup\fR(8) and
130 /* \fBcleanup\fR(8) daemons to a new queue file. In many
131 /* respects its handling differs from that of a new local
132 /* submission.
133 /* .RS
134 /* .IP \(bu
135 /* The message is not subjected to the smtpd_milters or
136 /* non_smtpd_milters settings. When mail has passed through
137 /* an external content filter, this would produce incorrect
138 /* results with Milter applications that depend on original
139 /* SMTP connection state information.
140 /* .IP \(bu
141 /* The message is subjected again to mail address rewriting
142 /* and substitution. This is useful when rewriting rules or
143 /* virtual mappings have changed.
144 /* .sp
145 /* The address rewriting context (local or remote) is the same
146 /* as when the message was received.
147 /* .IP \(bu
148 /* The message is subjected to the same content_filter settings
149 /* (if any) as used for new local mail submissions. This is
150 /* useful when content_filter settings have changed.
151 /* .RE
152 /* .IP
153 /* Warning: Postfix queue IDs are reused.
154 /* There is a very small possibility that \fBpostsuper\fR(1) requeues
155 /* the wrong message file when it is executed while the Postfix mail
156 /* system is running, but no harm should be done.
157 /* .sp
158 /* This feature is available in Postfix 1.1 and later.
159 /* .IP \fB-s\fR
160 /* Structure check and structure repair. This should be done once
161 /* before Postfix startup.
162 /* .RS
163 /* .IP \(bu
164 /* Rename files whose name does not match the message file inode
165 /* number. This operation is necessary after restoring a mail queue
166 /* from a different machine, or from backup media.
167 /* .IP \(bu
168 /* Move queue files that are in the wrong place in the file system
169 /* hierarchy and remove subdirectories that are no longer needed.
170 /* File position rearrangements are necessary after a change in the
171 /* \fBhash_queue_names\fR and/or \fBhash_queue_depth\fR
172 /* configuration parameters.
173 /* .RE
174 /* .IP \fB-v\fR
175 /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
176 /* options make the software increasingly verbose.
177 /* DIAGNOSTICS
178 /* Problems are reported to the standard error stream and to
179 /* \fBsyslogd\fR(8).
181 /* \fBpostsuper\fR(1) reports the number of messages deleted with \fB-d\fR,
182 /* the number of messages requeued with \fB-r\fR, and the number of
183 /* messages whose queue file name was fixed with \fB-s\fR. The report
184 /* is written to the standard error stream and to \fBsyslogd\fR(8).
185 /* ENVIRONMENT
186 /* .ad
187 /* .fi
188 /* .IP MAIL_CONFIG
189 /* Directory with the \fBmain.cf\fR file.
190 /* BUGS
191 /* Mail that is not sanitized by Postfix (i.e. mail in the \fBmaildrop\fR
192 /* queue) cannot be placed "on hold".
193 /* CONFIGURATION PARAMETERS
194 /* .ad
195 /* .fi
196 /* The following \fBmain.cf\fR parameters are especially relevant to
197 /* this program.
198 /* The text below provides only a parameter summary. See
199 /* \fBpostconf\fR(5) for more details including examples.
200 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
201 /* The default location of the Postfix main.cf and master.cf
202 /* configuration files.
203 /* .IP "\fBhash_queue_depth (1)\fR"
204 /* The number of subdirectory levels for queue directories listed with
205 /* the hash_queue_names parameter.
206 /* .IP "\fBhash_queue_names (deferred, defer)\fR"
207 /* The names of queue directories that are split across multiple
208 /* subdirectory levels.
209 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
210 /* The location of the Postfix top-level queue directory.
211 /* .IP "\fBsyslog_facility (mail)\fR"
212 /* The syslog facility of Postfix logging.
213 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
214 /* The mail system name that is prepended to the process name in syslog
215 /* records, so that "smtpd" becomes, for example, "postfix/smtpd".
216 /* SEE ALSO
217 /* sendmail(1), Sendmail-compatible user interface
218 /* postqueue(1), unprivileged queue operations
219 /* LICENSE
220 /* .ad
221 /* .fi
222 /* The Secure Mailer license must be distributed with this software.
223 /* AUTHOR(S)
224 /* Wietse Venema
225 /* IBM T.J. Watson Research
226 /* P.O. Box 704
227 /* Yorktown Heights, NY 10598, USA
228 /*--*/
230 /* System library. */
232 #include <sys_defs.h>
233 #include <sys/stat.h>
234 #include <unistd.h>
235 #include <stdlib.h>
236 #include <errno.h>
237 #include <string.h>
238 #include <signal.h>
239 #include <stdio.h> /* remove() */
240 #include <utime.h>
242 /* Utility library. */
244 #include <mymalloc.h>
245 #include <msg.h>
246 #include <msg_syslog.h>
247 #include <vstream.h>
248 #include <msg_vstream.h>
249 #include <scan_dir.h>
250 #include <vstring.h>
251 #include <safe.h>
252 #include <set_ugid.h>
253 #include <argv.h>
254 #include <vstring_vstream.h>
255 #include <sane_fsops.h>
257 /* Global library. */
259 #include <mail_task.h>
260 #include <mail_conf.h>
261 #include <mail_params.h>
262 #include <mail_version.h>
263 #include <mail_queue.h>
264 #include <mail_open_ok.h>
266 /* Application-specific. */
268 #define MAX_TEMP_AGE (60 * 60 * 24) /* temp file maximal age */
269 #define STR vstring_str /* silly little macro */
271 #define ACTION_STRUCT (1<<0) /* fix file organization */
272 #define ACTION_PURGE (1<<1) /* purge old temp files */
273 #define ACTION_DELETE_ONE (1<<2) /* delete named queue file(s) */
274 #define ACTION_DELETE_ALL (1<<3) /* delete all queue file(s) */
275 #define ACTION_REQUEUE_ONE (1<<4) /* requeue named queue file(s) */
276 #define ACTION_REQUEUE_ALL (1<<5) /* requeue all queue file(s) */
277 #define ACTION_HOLD_ONE (1<<6) /* put named queue file(s) on hold */
278 #define ACTION_HOLD_ALL (1<<7) /* put all messages on hold */
279 #define ACTION_RELEASE_ONE (1<<8) /* release named queue file(s) */
280 #define ACTION_RELEASE_ALL (1<<9) /* release all "on hold" mail */
282 #define ACTION_DEFAULT (ACTION_STRUCT | ACTION_PURGE)
285 * Actions that operate on individually named queue files. These must never
286 * be done when queue file names are changed to match their inode number.
288 #define ACTIONS_BY_QUEUE_ID (ACTION_DELETE_ONE | ACTION_REQUEUE_ONE \
289 | ACTION_HOLD_ONE | ACTION_RELEASE_ONE)
292 * Mass rename operations that are postponed to a second pass after queue
293 * file names are changed to match their inode number.
295 #define ACTIONS_AFTER_INUM_FIX (ACTION_REQUEUE_ALL | ACTION_HOLD_ALL \
296 | ACTION_RELEASE_ALL)
299 * Information about queue directories and what we expect to do there. If a
300 * file has unexpected owner permissions and is older than some threshold,
301 * the file is discarded. We don't step into maildrop subdirectories - if
302 * maildrop is writable, we might end up in the wrong place, deleting the
303 * wrong information.
305 struct queue_info {
306 char *name; /* directory name */
307 int perms; /* expected permissions */
308 int flags; /* see below */
311 #define RECURSE (1<<0) /* step into subdirectories */
312 #define DONT_RECURSE 0 /* don't step into directories */
314 static struct queue_info queue_info[] = {
315 MAIL_QUEUE_MAILDROP, MAIL_QUEUE_STAT_READY, DONT_RECURSE,
316 MAIL_QUEUE_INCOMING, MAIL_QUEUE_STAT_READY, RECURSE,
317 MAIL_QUEUE_ACTIVE, MAIL_QUEUE_STAT_READY, RECURSE,
318 MAIL_QUEUE_DEFERRED, MAIL_QUEUE_STAT_READY, RECURSE,
319 MAIL_QUEUE_HOLD, MAIL_QUEUE_STAT_READY, RECURSE,
320 MAIL_QUEUE_TRACE, 0600, RECURSE,
321 MAIL_QUEUE_DEFER, 0600, RECURSE,
322 MAIL_QUEUE_BOUNCE, 0600, RECURSE,
323 MAIL_QUEUE_FLUSH, 0600, RECURSE,
328 * Directories with per-message meta files.
330 const char *log_queue_names[] = {
331 MAIL_QUEUE_BOUNCE,
332 MAIL_QUEUE_DEFER,
333 MAIL_QUEUE_TRACE,
338 * Cruft that we append to a file name when a queue ID is named after the
339 * message file inode number. This cruft must not pass mail_queue_id_ok() so
340 * that the queue manager will ignore it, should people be so unwise as to
341 * run this operation on a live mail system.
343 #define SUFFIX "#FIX"
344 #define SUFFIX_LEN 4
347 * Grr. These counters are global, because C only has clumsy ways to return
348 * multiple results from a function.
350 static int message_requeued = 0; /* requeued messages */
351 static int message_held = 0; /* messages put on hold */
352 static int message_released = 0; /* messages released from hold */
353 static int message_deleted = 0; /* deleted messages */
354 static int inode_fixed = 0; /* queue id matched to inode number */
355 static int inode_mismatch = 0; /* queue id inode mismatch */
356 static int position_mismatch = 0; /* file position mismatch */
359 * Silly little macros. These translate arcane expressions into something
360 * more at a conceptual level.
362 #define MESSAGE_QUEUE(qp) ((qp)->perms == MAIL_QUEUE_STAT_READY)
363 #define READY_MESSAGE(st) (((st).st_mode & S_IRWXU) == MAIL_QUEUE_STAT_READY)
365 /* find_queue_info - look up expected permissions field by queue name */
367 static struct queue_info *find_queue_info(const char *queue_name)
369 struct queue_info *qp;
371 for (qp = queue_info; qp->name; qp++)
372 if (strcmp(queue_name, qp->name) == 0)
373 return (qp);
374 msg_fatal("invalid directory name: %s", queue_name);
377 /* postremove - remove file with extreme prejudice */
379 static int postremove(const char *path)
381 int ret;
383 if ((ret = remove(path)) < 0) {
384 if (errno != ENOENT)
385 msg_fatal("remove file %s: %m", path);
386 } else {
387 if (msg_verbose)
388 msg_info("removed file %s", path);
390 return (ret);
393 /* postrename - rename file with extreme prejudice */
395 static int postrename(const char *old, const char *new)
397 int ret;
399 if ((ret = sane_rename(old, new)) < 0) {
400 if (errno != ENOENT
401 || mail_queue_mkdirs(new) < 0
402 || sane_rename(old, new) < 0)
403 if (errno != ENOENT)
404 msg_fatal("rename file %s as %s: %m", old, new);
405 } else {
406 if (msg_verbose)
407 msg_info("renamed file %s as %s", old, new);
409 return (ret);
412 /* postrmdir - remove directory with extreme prejudice */
414 static int postrmdir(const char *path)
416 int ret;
418 if ((ret = rmdir(path)) < 0) {
419 if (errno != ENOENT)
420 msg_fatal("remove directory %s: %m", path);
421 } else {
422 if (msg_verbose)
423 msg_info("remove directory %s", path);
425 return (ret);
428 /* delete_one - delete one message instance and all its associated files */
430 static int delete_one(const char **queue_names, const char *queue_id)
432 struct stat st;
433 const char **msg_qpp;
434 const char **log_qpp;
435 const char *msg_path;
436 VSTRING *log_path_buf;
437 int found;
438 int tries;
441 * Sanity check. No early returns beyond this point.
443 if (!mail_queue_id_ok(queue_id)) {
444 msg_warn("invalid mail queue id: %s", queue_id);
445 return (0);
447 log_path_buf = vstring_alloc(100);
450 * Skip meta file directories. Delete trace/defer/bounce logfiles before
451 * deleting the corresponding message file, and only if the message file
452 * exists. This minimizes but does not eliminate a race condition with
453 * queue ID reuse which results in deleting the wrong files.
455 for (found = 0, tries = 0; found == 0 && tries < 2; tries++) {
456 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) {
457 if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp)))
458 continue;
459 if (mail_open_ok(*msg_qpp, queue_id, &st, &msg_path) != MAIL_OPEN_YES)
460 continue;
461 for (log_qpp = log_queue_names; *log_qpp != 0; log_qpp++)
462 postremove(mail_queue_path(log_path_buf, *log_qpp, queue_id));
463 if (postremove(msg_path) == 0) {
464 found = 1;
465 msg_info("%s: removed", queue_id);
466 break;
467 } /* else: maybe lost a race */
470 vstring_free(log_path_buf);
471 return (found);
474 /* requeue_one - requeue one message instance and delete its logfiles */
476 static int requeue_one(const char **queue_names, const char *queue_id)
478 struct stat st;
479 const char **msg_qpp;
480 const char *old_path;
481 VSTRING *new_path_buf;
482 int found;
483 int tries;
484 struct utimbuf tbuf;
487 * Sanity check. No early returns beyond this point.
489 if (!mail_queue_id_ok(queue_id)) {
490 msg_warn("invalid mail queue id: %s", queue_id);
491 return (0);
493 new_path_buf = vstring_alloc(100);
496 * Skip meta file directories. Like the mass requeue operation, we not
497 * delete defer or bounce logfiles, to avoid losing a race where the
498 * queue manager decides to bounce mail after all recipients have been
499 * tried.
501 for (found = 0, tries = 0; found == 0 && tries < 2; tries++) {
502 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) {
503 if (strcmp(*msg_qpp, MAIL_QUEUE_MAILDROP) == 0)
504 continue;
505 if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp)))
506 continue;
507 if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES)
508 continue;
509 (void) mail_queue_path(new_path_buf, MAIL_QUEUE_MAILDROP, queue_id);
510 if (postrename(old_path, STR(new_path_buf)) == 0) {
511 tbuf.actime = tbuf.modtime = time((time_t *) 0);
512 if (utime(STR(new_path_buf), &tbuf) < 0)
513 msg_warn("%s: reset time stamps: %m", STR(new_path_buf));
514 msg_info("%s: requeued", queue_id);
515 found = 1;
516 break;
517 } /* else: maybe lost a race */
520 vstring_free(new_path_buf);
521 return (found);
524 /* hold_one - put "on hold" one message instance */
526 static int hold_one(const char **queue_names, const char *queue_id)
528 struct stat st;
529 const char **msg_qpp;
530 const char *old_path;
531 VSTRING *new_path_buf;
532 int found;
533 int tries;
536 * Sanity check. No early returns beyond this point.
538 if (!mail_queue_id_ok(queue_id)) {
539 msg_warn("invalid mail queue id: %s", queue_id);
540 return (0);
542 new_path_buf = vstring_alloc(100);
545 * Skip meta file directories. Like the mass requeue operation, we not
546 * delete defer or bounce logfiles, to avoid losing a race where the
547 * queue manager decides to bounce mail after all recipients have been
548 * tried.
550 * XXX We must not put maildrop mail on hold because that would mix already
551 * sanitized mail with mail that still needs to be sanitized.
553 for (found = 0, tries = 0; found == 0 && tries < 2; tries++) {
554 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) {
555 if (strcmp(*msg_qpp, MAIL_QUEUE_MAILDROP) == 0)
556 continue;
557 if (strcmp(*msg_qpp, MAIL_QUEUE_HOLD) == 0)
558 continue;
559 if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp)))
560 continue;
561 if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES)
562 continue;
563 (void) mail_queue_path(new_path_buf, MAIL_QUEUE_HOLD, queue_id);
564 if (postrename(old_path, STR(new_path_buf)) == 0) {
565 msg_info("%s: placed on hold", queue_id);
566 found = 1;
567 break;
568 } /* else: maybe lost a race */
571 vstring_free(new_path_buf);
572 return (found);
575 /* release_one - release one message instance that was placed "on hold" */
577 static int release_one(const char **queue_names, const char *queue_id)
579 struct stat st;
580 const char **msg_qpp;
581 const char *old_path;
582 VSTRING *new_path_buf;
583 int found;
586 * Sanity check. No early returns beyond this point.
588 if (!mail_queue_id_ok(queue_id)) {
589 msg_warn("invalid mail queue id: %s", queue_id);
590 return (0);
592 new_path_buf = vstring_alloc(100);
595 * Skip inapplicable directories. This can happen when -H is combined
596 * with other operations.
598 found = 0;
599 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) {
600 if (strcmp(*msg_qpp, MAIL_QUEUE_HOLD) != 0)
601 continue;
602 if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES)
603 continue;
604 (void) mail_queue_path(new_path_buf, MAIL_QUEUE_DEFERRED, queue_id);
605 if (postrename(old_path, STR(new_path_buf)) == 0) {
606 msg_info("%s: released from hold", queue_id);
607 found = 1;
608 break;
611 vstring_free(new_path_buf);
612 return (found);
615 /* operate_stream - operate on queue IDs given on stream */
617 static int operate_stream(VSTREAM *fp,
618 int (*operator) (const char **, const char *),
619 const char **queues)
621 VSTRING *buf = vstring_alloc(20);
622 int found = 0;
624 while (vstring_get_nonl(buf, fp) != VSTREAM_EOF)
625 found += operator(queues, STR(buf));
627 vstring_free(buf);
628 return (found);
631 /* fix_queue_id - make message queue ID match inode number */
633 static int fix_queue_id(const char *actual_path, const char *actual_queue,
634 const char *actual_id, ino_t inum)
636 VSTRING *old_path = vstring_alloc(10);
637 VSTRING *new_path = vstring_alloc(10);
638 VSTRING *new_id = vstring_alloc(10);
639 const char **log_qpp;
640 int ret;
643 * Create the new queue ID from the existing time digits and from the new
644 * inode number. Since we are renaming multiple files, the new name must
645 * be deterministic so that we can recover even when the renaming
646 * operation is interrupted in the middle.
648 vstring_sprintf(new_id, "%.5s%lX", actual_id, (unsigned long) inum);
651 * Rename logfiles before renaming the message file, so that we can
652 * recover when a previous attempt was interrupted.
654 for (log_qpp = log_queue_names; *log_qpp; log_qpp++) {
655 mail_queue_path(old_path, *log_qpp, actual_id);
656 mail_queue_path(new_path, *log_qpp, STR(new_id));
657 vstring_strcat(new_path, SUFFIX);
658 postrename(STR(old_path), STR(new_path));
662 * Rename the message file last, so that we know that we are done with
663 * this message and with all its logfiles.
665 mail_queue_path(new_path, actual_queue, STR(new_id));
666 vstring_strcat(new_path, SUFFIX);
667 ret = postrename(actual_path, STR(new_path));
670 * Clean up.
672 vstring_free(old_path);
673 vstring_free(new_path);
674 vstring_free(new_id);
676 return (ret);
679 /* super - check queue structure, clean up, do wild-card operations */
681 static void super(const char **queues, int action)
683 ARGV *hash_queue_names = argv_split(var_hash_queue_names, " \t\r\n,");
684 VSTRING *actual_path = vstring_alloc(10);
685 VSTRING *wanted_path = vstring_alloc(10);
686 struct stat st;
687 const char *queue_name;
688 SCAN_DIR *info;
689 char *path;
690 int actual_depth;
691 int wanted_depth;
692 char **cpp;
693 struct queue_info *qp;
694 unsigned long inum;
697 * Make sure every file is in the right place, clean out stale files, and
698 * remove non-file/non-directory objects.
700 while ((queue_name = *queues++) != 0) {
702 if (msg_verbose)
703 msg_info("queue: %s", queue_name);
706 * Look up queue-specific properties: desired hashing depth, what
707 * file permissions to look for, and whether or not it is desirable
708 * to step into subdirectories.
710 qp = find_queue_info(queue_name);
711 for (cpp = hash_queue_names->argv; /* void */ ; cpp++) {
712 if (*cpp == 0) {
713 wanted_depth = 0;
714 break;
716 if (strcmp(*cpp, queue_name) == 0) {
717 wanted_depth = var_hash_queue_depth;
718 break;
723 * Sanity check. Some queues just cannot be recursive.
725 if (wanted_depth > 0 && (qp->flags & RECURSE) == 0)
726 msg_fatal("%s queue must not be hashed", queue_name);
729 * Other per-directory initialization.
731 info = scan_dir_open(queue_name);
732 actual_depth = 0;
734 for (;;) {
737 * If we reach the end of a subdirectory, return to its parent.
738 * Delete subdirectories that are no longer needed.
740 if ((path = scan_dir_next(info)) == 0) {
741 if (actual_depth == 0)
742 break;
743 if (actual_depth > wanted_depth)
744 postrmdir(scan_dir_path(info));
745 scan_dir_pop(info);
746 actual_depth--;
747 continue;
751 * If we stumble upon a subdirectory, enter it, if it is
752 * considered safe to do so. Otherwise, try to remove the
753 * subdirectory at a later stage.
755 if (strlen(path) == 1 && (qp->flags & RECURSE) != 0) {
756 actual_depth++;
757 scan_dir_push(info, path);
758 continue;
762 * From here on we need to keep track of operations that
763 * invalidate or revalidate the actual_path and path variables,
764 * otherwise we can hit the wrong files.
766 vstring_sprintf(actual_path, "%s/%s", scan_dir_path(info), path);
767 if (stat(STR(actual_path), &st) < 0)
768 continue;
771 * Remove alien directories. If maildrop is compromised, then we
772 * cannot abort just because we cannot remove someone's
773 * directory.
775 if (S_ISDIR(st.st_mode)) {
776 if (rmdir(STR(actual_path)) < 0) {
777 if (errno != ENOENT)
778 msg_warn("remove subdirectory %s: %m", STR(actual_path));
779 } else {
780 if (msg_verbose)
781 msg_info("remove subdirectory %s", STR(actual_path));
783 /* No further work on this object is possible. */
784 continue;
788 * Mass deletion. We count the deletion of mail that this system
789 * has taken responsibility for. XXX This option does not use
790 * mail_queue_remove(), so that it can avoid having to first move
791 * queue files to the "right" subdirectory level.
793 if (action & ACTION_DELETE_ALL) {
794 if (postremove(STR(actual_path)) == 0)
795 if (MESSAGE_QUEUE(qp) && READY_MESSAGE(st))
796 message_deleted++;
797 /* No further work on this object is possible. */
798 continue;
802 * Remove non-file objects and old temporary files. Be careful
803 * not to delete bounce or defer logs just because they are more
804 * than a couple days old.
806 if (!S_ISREG(st.st_mode)
807 || ((action & ACTION_PURGE) != 0
808 && MESSAGE_QUEUE(qp)
809 && !READY_MESSAGE(st)
810 && time((time_t *) 0) > st.st_mtime + MAX_TEMP_AGE)) {
811 (void) postremove(STR(actual_path));
812 /* No further work on this object is possible. */
813 continue;
817 * Fix queueid#FIX names that were left from a previous pass over
818 * the queue where message queue file names were matched to their
819 * inode number. We strip the suffix and move the file into the
820 * proper subdirectory level. Make sure that the name minus
821 * suffix is well formed and that the name matches the file inode
822 * number.
824 if ((action & ACTION_STRUCT)
825 && strcmp(path + (strlen(path) - SUFFIX_LEN), SUFFIX) == 0) {
826 path[strlen(path) - SUFFIX_LEN] = 0; /* XXX */
827 if (!mail_queue_id_ok(path)) {
828 msg_warn("bogus file name: %s", STR(actual_path));
829 continue;
831 if (MESSAGE_QUEUE(qp)) {
832 if (sscanf(path + 5, "%lx", &inum) != 1) {
833 msg_warn("bogus file name: %s", STR(actual_path));
834 continue;
836 if (inum != (unsigned long) st.st_ino) {
837 msg_warn("name/inode mismatch: %s", STR(actual_path));
838 continue;
841 (void) mail_queue_path(wanted_path, queue_name, path);
842 if (postrename(STR(actual_path), STR(wanted_path)) < 0) {
843 /* No further work on this object is possible. */
844 continue;
845 } else {
846 if (MESSAGE_QUEUE(qp))
847 inode_fixed++;
848 vstring_strcpy(actual_path, STR(wanted_path));
849 /* At this point, path and actual_path are revalidated. */
854 * Skip over files with illegal names. The library routines
855 * refuse to operate on them.
857 if (!mail_queue_id_ok(path)) {
858 msg_warn("bogus file name: %s", STR(actual_path));
859 continue;
863 * See if the file name matches the file inode number. Skip meta
864 * file directories. This option requires that meta files be put
865 * into their proper place before queue files, so that we can
866 * rename queue files and meta files at the same time. Mis-named
867 * files are renamed to newqueueid#FIX on the first pass, and
868 * upon the second pass the #FIX is stripped off the name. Of
869 * course we have to be prepared that the program is interrupted
870 * before it completes, so any left-over newqueueid#FIX files
871 * have to be handled properly. XXX This option cannot use
872 * mail_queue_rename(), because the queue file name violates
873 * normal queue file syntax.
875 if ((action & ACTION_STRUCT) != 0 && MESSAGE_QUEUE(qp)) {
876 if (sscanf(path + 5, "%lx", &inum) != 1) {
877 msg_warn("bogus file name: %s", STR(actual_path));
878 continue;
880 if (inum != (unsigned long) st.st_ino) {
881 inode_mismatch++; /* before we fix */
882 action &= ~ACTIONS_AFTER_INUM_FIX;
883 fix_queue_id(STR(actual_path), queue_name, path, st.st_ino);
884 /* At this point, path and actual_path are invalidated. */
885 continue;
890 * Mass requeuing. The pickup daemon will copy requeued mail to a
891 * new queue file, so that address rewriting is applied again.
892 * XXX This option does not use mail_queue_rename(), so that it
893 * can avoid having to first move queue files to the "right"
894 * subdirectory level. Like the requeue_one() routine, this code
895 * does not touch logfiles.
897 if ((action & ACTION_REQUEUE_ALL)
898 && MESSAGE_QUEUE(qp)
899 && strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0) {
900 (void) mail_queue_path(wanted_path, MAIL_QUEUE_MAILDROP, path);
901 if (postrename(STR(actual_path), STR(wanted_path)) == 0)
902 message_requeued++;
903 /* At this point, path and actual_path are invalidated. */
904 continue;
908 * Mass renaming to the "on hold" queue. XXX This option does not
909 * use mail_queue_rename(), so that it can avoid having to first
910 * move queue files to the "right" subdirectory level. Like the
911 * hold_one() routine, this code does not touch logfiles, and
912 * must not touch files in the maildrop queue, because maildrop
913 * files contain data that has not yet been sanitized and
914 * therefore must not be mixed with already sanitized mail.
916 if ((action & ACTION_HOLD_ALL)
917 && MESSAGE_QUEUE(qp)
918 && strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0
919 && strcmp(queue_name, MAIL_QUEUE_HOLD) != 0) {
920 (void) mail_queue_path(wanted_path, MAIL_QUEUE_HOLD, path);
921 if (postrename(STR(actual_path), STR(wanted_path)) == 0)
922 message_held++;
923 /* At this point, path and actual_path are invalidated. */
924 continue;
928 * Mass release from the "on hold" queue. XXX This option does
929 * not use mail_queue_rename(), so that it can avoid having to
930 * first move queue files to the "right" subdirectory level. Like
931 * the release_one() routine, this code must not touch logfiles.
933 if ((action & ACTION_RELEASE_ALL)
934 && strcmp(queue_name, MAIL_QUEUE_HOLD) == 0) {
935 (void) mail_queue_path(wanted_path, MAIL_QUEUE_DEFERRED, path);
936 if (postrename(STR(actual_path), STR(wanted_path)) == 0)
937 message_released++;
938 /* At this point, path and actual_path are invalidated. */
939 continue;
943 * See if this file sits in the right place in the file system
944 * hierarchy. Its place may be wrong after a change to the
945 * hash_queue_{names,depth} parameter settings. This requires
946 * that the bounce/defer logfiles be at the right subdirectory
947 * level first, otherwise we would fail to properly rename
948 * bounce/defer logfiles.
950 if (action & ACTION_STRUCT) {
951 (void) mail_queue_path(wanted_path, queue_name, path);
952 if (strcmp(STR(actual_path), STR(wanted_path)) != 0) {
953 position_mismatch++; /* before we fix */
954 (void) postrename(STR(actual_path), STR(wanted_path));
955 /* At this point, path and actual_path are invalidated. */
956 continue;
960 scan_dir_close(info);
964 * Clean up.
966 vstring_free(wanted_path);
967 vstring_free(actual_path);
968 argv_free(hash_queue_names);
971 /* interrupted - signal handler */
973 static void interrupted(int sig)
977 * This commands requires root privileges. We therefore do not worry
978 * about hostile signals, and report problems via msg_warn().
980 * We use the in-kernel SIGINT handler address as an atomic variable to
981 * prevent nested interrupted() calls. For this reason, main() must
982 * configure interrupted() as SIGINT handler before other signal handlers
983 * are allowed to invoke interrupted(). See also similar code in
984 * postdrop.
986 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
987 (void) signal(SIGQUIT, SIG_IGN);
988 (void) signal(SIGTERM, SIG_IGN);
989 (void) signal(SIGHUP, SIG_IGN);
990 if (inode_mismatch > 0 || inode_fixed > 0 || position_mismatch > 0)
991 msg_warn("OPERATION INCOMPLETE -- RERUN COMMAND TO FIX THE QUEUE FIRST");
992 if (sig)
993 _exit(sig);
997 /* fatal_warning - print warning if queue fix is incomplete */
999 static void fatal_warning(void)
1001 interrupted(0);
1004 MAIL_VERSION_STAMP_DECLARE;
1006 int main(int argc, char **argv)
1008 int fd;
1009 struct stat st;
1010 char *slash;
1011 int action = 0;
1012 const char **queues;
1013 int c;
1014 ARGV *requeue_names = 0;
1015 ARGV *delete_names = 0;
1016 ARGV *hold_names = 0;
1017 ARGV *release_names = 0;
1018 char **cpp;
1021 * Defaults. The structural checks must fix the directory levels of "log
1022 * file" directories (bounce, defer) before doing structural checks on
1023 * the "message file" directories, so that we can find the logfiles in
1024 * the right place when message files need to be renamed to match their
1025 * inode number.
1027 static char *default_queues[] = {
1028 MAIL_QUEUE_DEFER, /* before message directories */
1029 MAIL_QUEUE_BOUNCE, /* before message directories */
1030 MAIL_QUEUE_MAILDROP,
1031 MAIL_QUEUE_INCOMING,
1032 MAIL_QUEUE_ACTIVE,
1033 MAIL_QUEUE_DEFERRED,
1034 MAIL_QUEUE_HOLD,
1035 MAIL_QUEUE_FLUSH,
1038 static char *default_hold_queues[] = {
1039 MAIL_QUEUE_INCOMING,
1040 MAIL_QUEUE_ACTIVE,
1041 MAIL_QUEUE_DEFERRED,
1044 static char *default_release_queues[] = {
1045 MAIL_QUEUE_HOLD,
1050 * Fingerprint executables and core dumps.
1052 MAIL_VERSION_STAMP_ALLOCATE;
1055 * Be consistent with file permissions.
1057 umask(022);
1060 * To minimize confusion, make sure that the standard file descriptors
1061 * are open before opening anything else. XXX Work around for 44BSD where
1062 * fstat can return EBADF on an open file descriptor.
1064 for (fd = 0; fd < 3; fd++)
1065 if (fstat(fd, &st) == -1
1066 && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
1067 msg_fatal("open /dev/null: %m");
1070 * Process this environment option as early as we can, to aid debugging.
1072 if (safe_getenv(CONF_ENV_VERB))
1073 msg_verbose = 1;
1076 * Initialize logging.
1078 if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
1079 argv[0] = slash + 1;
1080 msg_vstream_init(argv[0], VSTREAM_ERR);
1081 msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
1082 set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
1085 * Disallow unsafe practices, and refuse to run set-uid (or as the child
1086 * of a set-uid process). Whenever a privileged wrapper program is
1087 * needed, it must properly sanitize the real/effective/saved UID/GID,
1088 * the secondary groups, the process environment, and so on. Otherwise,
1089 * accidents can happen. If not with Postfix, then with other software.
1091 if (unsafe() != 0)
1092 msg_fatal("this postfix command must not run as a set-uid process");
1093 if (getuid())
1094 msg_fatal("use of this command is reserved for the superuser");
1097 * Parse JCL.
1099 while ((c = GETOPT(argc, argv, "c:d:h:H:pr:sv")) > 0) {
1100 switch (c) {
1101 default:
1102 msg_fatal("usage: %s "
1103 "[-c config_dir] "
1104 "[-d queue_id (delete)] "
1105 "[-h queue_id (hold)] [-H queue_id (un-hold)] "
1106 "[-p (purge temporary files)] [-r queue_id (requeue)] "
1107 "[-s (structure fix)] [-v (verbose)] "
1108 "[queue...]", argv[0]);
1109 case 'c':
1110 if (*optarg != '/')
1111 msg_fatal("-c requires absolute pathname");
1112 if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
1113 msg_fatal("setenv: %m");
1114 break;
1115 case 'd':
1116 if (delete_names == 0)
1117 delete_names = argv_alloc(1);
1118 argv_add(delete_names, optarg, (char *) 0);
1119 action |= (strcmp(optarg, "ALL") == 0 ?
1120 ACTION_DELETE_ALL : ACTION_DELETE_ONE);
1121 break;
1122 case 'h':
1123 if (hold_names == 0)
1124 hold_names = argv_alloc(1);
1125 argv_add(hold_names, optarg, (char *) 0);
1126 action |= (strcmp(optarg, "ALL") == 0 ?
1127 ACTION_HOLD_ALL : ACTION_HOLD_ONE);
1128 break;
1129 case 'H':
1130 if (release_names == 0)
1131 release_names = argv_alloc(1);
1132 argv_add(release_names, optarg, (char *) 0);
1133 action |= (strcmp(optarg, "ALL") == 0 ?
1134 ACTION_RELEASE_ALL : ACTION_RELEASE_ONE);
1135 break;
1136 case 'p':
1137 action |= ACTION_PURGE;
1138 break;
1139 case 'r':
1140 if (requeue_names == 0)
1141 requeue_names = argv_alloc(1);
1142 argv_add(requeue_names, optarg, (char *) 0);
1143 action |= (strcmp(optarg, "ALL") == 0 ?
1144 ACTION_REQUEUE_ALL : ACTION_REQUEUE_ONE);
1145 break;
1146 case 's':
1147 action |= ACTION_STRUCT;
1148 break;
1149 case 'v':
1150 msg_verbose++;
1151 break;
1156 * Read the global configuration file and extract configuration
1157 * information. The -c command option can override the default
1158 * configuration directory location.
1160 mail_conf_read();
1161 if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0)
1162 msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
1163 if (chdir(var_queue_dir))
1164 msg_fatal("chdir %s: %m", var_queue_dir);
1167 * All file/directory updates must be done as the mail system owner. This
1168 * is because Postfix daemons manipulate the queue with those same
1169 * privileges, so directories must be created with the right ownership.
1171 * Running as a non-root user is also required for security reasons. When
1172 * the Postfix queue hierarchy is compromised, an attacker could trick us
1173 * into entering other file hierarchies and afflicting damage. Running as
1174 * a non-root user limits the damage to the already compromised mail
1175 * owner.
1177 set_ugid(var_owner_uid, var_owner_gid);
1180 * Be sure to log a warning if we do not finish structural repair. Maybe
1181 * we should have an fsck-style "clean" flag so Postfix will not start
1182 * with a broken queue.
1184 * Set up signal handlers after permanently dropping super-user privileges,
1185 * so that signal handlers will always run with the correct privileges.
1187 * XXX Don't enable SIGHUP or SIGTERM if it was ignored by the parent.
1189 * interrupted() uses the in-kernel SIGINT handler address as an atomic
1190 * variable to prevent nested interrupted() calls. For this reason, the
1191 * SIGINT handler must be configured before other signal handlers are
1192 * allowed to invoke interrupted(). See also similar code in postdrop.
1194 signal(SIGINT, interrupted);
1195 signal(SIGQUIT, interrupted);
1196 if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
1197 signal(SIGTERM, interrupted);
1198 if (signal(SIGHUP, SIG_IGN) == SIG_DFL)
1199 signal(SIGHUP, interrupted);
1200 msg_cleanup(fatal_warning);
1203 * Sanity checks.
1205 if ((action & ACTION_DELETE_ALL) && (action & ACTION_DELETE_ONE)) {
1206 msg_warn("option \"-d ALL\" will ignore other command line queue IDs");
1207 action &= ~ACTION_DELETE_ONE;
1209 if ((action & ACTION_REQUEUE_ALL) && (action & ACTION_REQUEUE_ONE)) {
1210 msg_warn("option \"-r ALL\" will ignore other command line queue IDs");
1211 action &= ~ACTION_REQUEUE_ONE;
1213 if ((action & ACTION_HOLD_ALL) && (action & ACTION_HOLD_ONE)) {
1214 msg_warn("option \"-h ALL\" will ignore other command line queue IDs");
1215 action &= ~ACTION_HOLD_ONE;
1217 if ((action & ACTION_RELEASE_ALL) && (action & ACTION_RELEASE_ONE)) {
1218 msg_warn("option \"-H ALL\" will ignore other command line queue IDs");
1219 action &= ~ACTION_RELEASE_ONE;
1223 * Execute the explicitly specified (or default) action, on the
1224 * explicitly specified (or default) queues.
1226 * XXX Work around gcc const brain damage.
1228 * XXX The file name/inode number fix should always run over all message
1229 * file directories, and should always be preceded by a subdirectory
1230 * level check of the bounce and defer logfile directories.
1232 if (action == 0)
1233 action = ACTION_DEFAULT;
1234 if (argv[optind] != 0)
1235 queues = (const char **) argv + optind;
1236 else if (action == ACTION_HOLD_ALL)
1237 queues = (const char **) default_hold_queues;
1238 else if (action == ACTION_RELEASE_ALL)
1239 queues = (const char **) default_release_queues;
1240 else
1241 queues = (const char **) default_queues;
1244 * Basic queue maintenance, as well as mass deletion, mass requeuing, and
1245 * mass name-to-inode fixing. This ensures that queue files are in the
1246 * right place before the file-by-name operations are done.
1248 if (action & ~ACTIONS_BY_QUEUE_ID)
1249 super(queues, action);
1252 * If any file names needed changing to match the message file inode
1253 * number, those files were named newqeueid#FIX. We need a second pass to
1254 * strip the suffix from the new queue ID, and to complete any requested
1255 * operations that had to be skipped in the first pass.
1257 if (inode_mismatch > 0)
1258 super(queues, action);
1261 * Don't do actions by queue file name if any queue files changed name
1262 * because they did not match the queue file inode number. We could be
1263 * acting on the wrong queue file and lose mail.
1265 if ((action & ACTIONS_BY_QUEUE_ID)
1266 && (inode_mismatch > 0 || inode_fixed > 0)) {
1267 msg_error("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS");
1268 msg_fatal("CHECK YOUR QUEUE IDS AND RE-ISSUE THE COMMAND");
1272 * Delete queue files by name. This must not be done when queue file
1273 * names have changed names as a result of inode number mismatches,
1274 * because we could be deleting the wrong message.
1276 if (action & ACTION_DELETE_ONE) {
1277 argv_terminate(delete_names);
1278 queues = (const char **)
1279 (argv[optind] ? argv + optind : default_queues);
1280 for (cpp = delete_names->argv; *cpp; cpp++) {
1281 if (strcmp(*cpp, "ALL") == 0)
1282 continue;
1283 if (strcmp(*cpp, "-") == 0)
1284 message_deleted +=
1285 operate_stream(VSTREAM_IN, delete_one, queues);
1286 else
1287 message_deleted += delete_one(queues, *cpp);
1292 * Requeue queue files by name. This must not be done when queue file
1293 * names have changed names as a result of inode number mismatches,
1294 * because we could be requeuing the wrong message.
1296 if (action & ACTION_REQUEUE_ONE) {
1297 argv_terminate(requeue_names);
1298 queues = (const char **)
1299 (argv[optind] ? argv + optind : default_queues);
1300 for (cpp = requeue_names->argv; *cpp; cpp++) {
1301 if (strcmp(*cpp, "ALL") == 0)
1302 continue;
1303 if (strcmp(*cpp, "-") == 0)
1304 message_requeued +=
1305 operate_stream(VSTREAM_IN, requeue_one, queues);
1306 else
1307 message_requeued += requeue_one(queues, *cpp);
1312 * Put on hold queue files by name. This must not be done when queue file
1313 * names have changed names as a result of inode number mismatches,
1314 * because we could put on hold the wrong message.
1316 if (action & ACTION_HOLD_ONE) {
1317 argv_terminate(hold_names);
1318 queues = (const char **)
1319 (argv[optind] ? argv + optind : default_hold_queues);
1320 for (cpp = hold_names->argv; *cpp; cpp++) {
1321 if (strcmp(*cpp, "ALL") == 0)
1322 continue;
1323 if (strcmp(*cpp, "-") == 0)
1324 message_held +=
1325 operate_stream(VSTREAM_IN, hold_one, queues);
1326 else
1327 message_held += hold_one(queues, *cpp);
1332 * Take "off hold" queue files by name. This must not be done when queue
1333 * file names have changed names as a result of inode number mismatches,
1334 * because we could take off hold the wrong message.
1336 if (action & ACTION_RELEASE_ONE) {
1337 argv_terminate(release_names);
1338 queues = (const char **)
1339 (argv[optind] ? argv + optind : default_release_queues);
1340 for (cpp = release_names->argv; *cpp; cpp++) {
1341 if (strcmp(*cpp, "ALL") == 0)
1342 continue;
1343 if (strcmp(*cpp, "-") == 0)
1344 message_released +=
1345 operate_stream(VSTREAM_IN, release_one, queues);
1346 else
1347 message_released += release_one(queues, *cpp);
1352 * Report.
1354 if (message_requeued > 0)
1355 msg_info("Requeued: %d message%s", message_requeued,
1356 message_requeued > 1 ? "s" : "");
1357 if (message_deleted > 0)
1358 msg_info("Deleted: %d message%s", message_deleted,
1359 message_deleted > 1 ? "s" : "");
1360 if (message_held > 0)
1361 msg_info("Placed on hold: %d message%s",
1362 message_held, message_held > 1 ? "s" : "");
1363 if (message_released > 0)
1364 msg_info("Released from hold: %d message%s",
1365 message_released, message_released > 1 ? "s" : "");
1366 if (inode_fixed > 0)
1367 msg_info("Renamed to match inode number: %d message%s", inode_fixed,
1368 inode_fixed > 1 ? "s" : "");
1369 if (inode_mismatch > 0 || inode_fixed > 0)
1370 msg_warn("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS");
1373 * Clean up.
1375 if (requeue_names)
1376 argv_free(requeue_names);
1377 if (delete_names)
1378 argv_free(delete_names);
1379 if (hold_names)
1380 argv_free(hold_names);
1381 if (release_names)
1382 argv_free(release_names);
1384 exit(0);