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