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 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 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 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 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