xref: /netbsd-src/external/ibm-public/postfix/dist/src/qmgr/qmgr_scan.c (revision 41fbaed053f8fbfdf9d2a4ee0a7386a3c83f8505)
1 /*	$NetBSD: qmgr_scan.c,v 1.1.1.1 2009/06/23 10:08:53 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	qmgr_scan 3
6 /* SUMMARY
7 /*	queue scanning
8 /* SYNOPSIS
9 /*	#include "qmgr.h"
10 /*
11 /*	QMGR_SCAN *qmgr_scan_create(queue_name)
12 /*	const char *queue_name;
13 /*
14 /*	char	*qmgr_scan_next(scan_info)
15 /*	QMGR_SCAN *scan_info;
16 /*
17 /*	void	qmgr_scan_request(scan_info, flags)
18 /*	QMGR_SCAN *scan_info;
19 /*	int	flags;
20 /* DESCRIPTION
21 /*	This module implements queue scans. A queue scan always runs
22 /*	to completion, so that all files get a fair chance. The caller
23 /*	can request that a queue scan be restarted once it completes.
24 /*
25 /*	qmgr_scan_create() creates a context for scanning the named queue,
26 /*	but does not start a queue scan.
27 /*
28 /*	qmgr_scan_next() returns the base name of the next queue file.
29 /*	A null pointer means that no file was found. qmgr_scan_next()
30 /*	automagically restarts a queue scan when a scan request had
31 /*	arrived while the scan was in progress.
32 /*
33 /*	qmgr_scan_request() records a request for the next queue scan. The
34 /*	flags argument is the bit-wise OR of zero or more of the following,
35 /*	unrecognized flags being ignored:
36 /* .IP QMGR_FLUSH_ONCE
37 /*	Forget state information about dead hosts or transports.
38 /*	This request takes effect immediately.
39 /* .IP QMGR_FLUSH_DFXP
40 /*	Override the defer_transports setting. This takes effect
41 /*	immediately when a queue scan is in progress, and affects
42 /*	the next queue scan.
43 /* .IP QMGR_SCAN_ALL
44 /*	Ignore queue file time stamps. This takes effect immediately
45 /*	when a queue scan is in progress, and affects the next queue
46 /*	scan.
47 /* .IP QMGR_SCAN_START
48 /*	Start a queue scan when none is in progress, or restart the
49 /*	current scan upon completion.
50 /* DIAGNOSTICS
51 /*	Fatal: out of memory.
52 /*	Panic: interface violations, internal consistency errors.
53 /* LICENSE
54 /* .ad
55 /* .fi
56 /*	The Secure Mailer license must be distributed with this software.
57 /* AUTHOR(S)
58 /*	Wietse Venema
59 /*	IBM T.J. Watson Research
60 /*	P.O. Box 704
61 /*	Yorktown Heights, NY 10598, USA
62 /*--*/
63 
64 /* System library. */
65 
66 #include <sys_defs.h>
67 
68 /* Utility library. */
69 
70 #include <msg.h>
71 #include <mymalloc.h>
72 #include <scan_dir.h>
73 
74 /* Global library. */
75 
76 #include <mail_scan_dir.h>
77 
78 /* Application-specific. */
79 
80 #include "qmgr.h"
81 
82 /* qmgr_scan_start - start queue scan */
83 
qmgr_scan_start(QMGR_SCAN * scan_info)84 static void qmgr_scan_start(QMGR_SCAN *scan_info)
85 {
86     const char *myname = "qmgr_scan_start";
87 
88     /*
89      * Sanity check.
90      */
91     if (scan_info->handle)
92 	msg_panic("%s: %s queue scan in progress",
93 		  myname, scan_info->queue);
94 
95     /*
96      * Give the poor tester a clue.
97      */
98     if (msg_verbose)
99 	msg_info("%s: %sstart %s queue scan",
100 		 myname,
101 		 scan_info->nflags & QMGR_SCAN_START ? "re" : "",
102 		 scan_info->queue);
103 
104     /*
105      * Start or restart the scan.
106      */
107     scan_info->flags = scan_info->nflags;
108     scan_info->nflags = 0;
109     scan_info->handle = scan_dir_open(scan_info->queue);
110 }
111 
112 /* qmgr_scan_request - request for future scan */
113 
qmgr_scan_request(QMGR_SCAN * scan_info,int flags)114 void    qmgr_scan_request(QMGR_SCAN *scan_info, int flags)
115 {
116 
117     /*
118      * Apply "forget all dead destinations" requests immediately. Throttle
119      * dead transports and queues at the earliest opportunity: preferably
120      * during an already ongoing queue scan, otherwise the throttling will
121      * have to wait until a "start scan" trigger arrives.
122      *
123      * The QMGR_FLUSH_ONCE request always comes with QMGR_FLUSH_DFXP, and
124      * sometimes it also comes with QMGR_SCAN_ALL. It becomes a completely
125      * different story when a flush request is encoded in file permissions.
126      */
127     if (flags & QMGR_FLUSH_ONCE)
128 	qmgr_enable_all();
129 
130     /*
131      * Apply "ignore time stamp" requests also towards the scan that is
132      * already in progress.
133      */
134     if (scan_info->handle != 0 && (flags & QMGR_SCAN_ALL))
135 	scan_info->flags |= QMGR_SCAN_ALL;
136 
137     /*
138      * Apply "override defer_transports" requests also towards the scan that
139      * is already in progress.
140      */
141     if (scan_info->handle != 0 && (flags & QMGR_FLUSH_DFXP))
142 	scan_info->flags |= QMGR_FLUSH_DFXP;
143 
144     /*
145      * If a scan is in progress, just record the request.
146      */
147     scan_info->nflags |= flags;
148     if (scan_info->handle == 0 && (flags & QMGR_SCAN_START) != 0) {
149 	scan_info->nflags &= ~QMGR_SCAN_START;
150 	qmgr_scan_start(scan_info);
151     }
152 }
153 
154 /* qmgr_scan_next - look for next queue file */
155 
qmgr_scan_next(QMGR_SCAN * scan_info)156 char   *qmgr_scan_next(QMGR_SCAN *scan_info)
157 {
158     char   *path = 0;
159 
160     /*
161      * Restart the scan if we reach the end and a queue scan request has
162      * arrived in the mean time.
163      */
164     if (scan_info->handle && (path = mail_scan_dir_next(scan_info->handle)) == 0) {
165 	scan_info->handle = scan_dir_close(scan_info->handle);
166 	if (msg_verbose && (scan_info->nflags & QMGR_SCAN_START) == 0)
167 	    msg_info("done %s queue scan", scan_info->queue);
168     }
169     if (!scan_info->handle && (scan_info->nflags & QMGR_SCAN_START)) {
170 	qmgr_scan_start(scan_info);
171 	path = mail_scan_dir_next(scan_info->handle);
172     }
173     return (path);
174 }
175 
176 /* qmgr_scan_create - create queue scan context */
177 
qmgr_scan_create(const char * queue)178 QMGR_SCAN *qmgr_scan_create(const char *queue)
179 {
180     QMGR_SCAN *scan_info;
181 
182     scan_info = (QMGR_SCAN *) mymalloc(sizeof(*scan_info));
183     scan_info->queue = mystrdup(queue);
184     scan_info->flags = scan_info->nflags = 0;
185     scan_info->handle = 0;
186     return (scan_info);
187 }
188