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