/*++ /* NAME /* qmgr_scan 3 /* SUMMARY /* queue scanning /* SYNOPSIS /* #include "qmgr.h" /* /* QMGR_SCAN *qmgr_scan_create(queue_name) /* const char *queue_name; /* /* char *qmgr_scan_next(scan_info) /* QMGR_SCAN *scan_info; /* /* void qmgr_scan_request(scan_info, flags) /* QMGR_SCAN *scan_info; /* int flags; /* DESCRIPTION /* This module implements queue scans. A queue scan always runs /* to completion, so that all files get a fair chance. The caller /* can request that a queue scan be restarted once it completes. /* /* qmgr_scan_create() creates a context for scanning the named queue, /* but does not start a queue scan. /* /* qmgr_scan_next() returns the base name of the next queue file. /* A null pointer means that no file was found. qmgr_scan_next() /* automagically restarts a queue scan when a scan request had /* arrived while the scan was in progress. /* /* qmgr_scan_request() records a request for the next queue scan. The /* flags argument is the bit-wise OR of zero or more of the following, /* unrecognized flags being ignored: /* .IP QMGR_FLUSH_ONCE /* Forget state information about dead hosts or transports. /* This request takes effect immediately. /* .IP QMGR_FLUSH_DFXP /* Override the defer_transports setting. This takes effect /* immediately when a queue scan is in progress, and affects /* the next queue scan. /* .IP QMGR_SCAN_ALL /* Ignore queue file time stamps. This takes effect immediately /* when a queue scan is in progress, and affects the next queue /* scan. /* .IP QMGR_SCAN_START /* Start a queue scan when none is in progress, or restart the /* current scan upon completion. /* DIAGNOSTICS /* Fatal: out of memory. /* Panic: interface violations, internal consistency errors. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include /* Utility library. */ #include #include #include /* Global library. */ #include /* Application-specific. */ #include "qmgr.h" /* qmgr_scan_start - start queue scan */ static void qmgr_scan_start(QMGR_SCAN *scan_info) { const char *myname = "qmgr_scan_start"; /* * Sanity check. */ if (scan_info->handle) msg_panic("%s: %s queue scan in progress", myname, scan_info->queue); /* * Give the poor tester a clue. */ if (msg_verbose) msg_info("%s: %sstart %s queue scan", myname, scan_info->nflags & QMGR_SCAN_START ? "re" : "", scan_info->queue); /* * Start or restart the scan. */ scan_info->flags = scan_info->nflags; scan_info->nflags = 0; scan_info->handle = scan_dir_open(scan_info->queue); } /* qmgr_scan_request - request for future scan */ void qmgr_scan_request(QMGR_SCAN *scan_info, int flags) { /* * Apply "forget all dead destinations" requests immediately. Throttle * dead transports and queues at the earliest opportunity: preferably * during an already ongoing queue scan, otherwise the throttling will * have to wait until a "start scan" trigger arrives. * * The QMGR_FLUSH_ONCE request always comes with QMGR_FLUSH_DFXP, and * sometimes it also comes with QMGR_SCAN_ALL. It becomes a completely * different story when a flush request is encoded in file permissions. */ if (flags & QMGR_FLUSH_ONCE) qmgr_enable_all(); /* * Apply "ignore time stamp" requests also towards the scan that is * already in progress. */ if (scan_info->handle != 0 && (flags & QMGR_SCAN_ALL)) scan_info->flags |= QMGR_SCAN_ALL; /* * Apply "override defer_transports" requests also towards the scan that * is already in progress. */ if (scan_info->handle != 0 && (flags & QMGR_FLUSH_DFXP)) scan_info->flags |= QMGR_FLUSH_DFXP; /* * If a scan is in progress, just record the request. */ scan_info->nflags |= flags; if (scan_info->handle == 0 && (flags & QMGR_SCAN_START) != 0) { scan_info->nflags &= ~QMGR_SCAN_START; qmgr_scan_start(scan_info); } } /* qmgr_scan_next - look for next queue file */ char *qmgr_scan_next(QMGR_SCAN *scan_info) { char *path = 0; /* * Restart the scan if we reach the end and a queue scan request has * arrived in the mean time. */ if (scan_info->handle && (path = mail_scan_dir_next(scan_info->handle)) == 0) { scan_info->handle = scan_dir_close(scan_info->handle); if (msg_verbose && (scan_info->nflags & QMGR_SCAN_START) == 0) msg_info("done %s queue scan", scan_info->queue); } if (!scan_info->handle && (scan_info->nflags & QMGR_SCAN_START)) { qmgr_scan_start(scan_info); path = mail_scan_dir_next(scan_info->handle); } return (path); } /* qmgr_scan_create - create queue scan context */ QMGR_SCAN *qmgr_scan_create(const char *queue) { QMGR_SCAN *scan_info; scan_info = (QMGR_SCAN *) mymalloc(sizeof(*scan_info)); scan_info->queue = mystrdup(queue); scan_info->flags = scan_info->nflags = 0; scan_info->handle = 0; return (scan_info); }