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