1/* $NetBSD$ */ 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 84static 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 114void 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 156char *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 178QMGR_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