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