123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- // main.cpp
- //
- // Copyright (C) 2007, ARM Research Labs, LLC.
- // See www.armresearch.com for the copyright terms.
- //
- // This is the entry point for the SNF Milter.
- // The main() function acquires the configuration file path, sets up the
- // SNF engine, and passes control to the SNFMilter module via runSNFMilter().
- //
- // SNFMilter() makes use of the SNF engine until it is dismissed by the MTA via
- // the appropriate libmilter call.
- //
- // While SNFMilter() is running, it will get new configuration data for each
- // scan it is asked to perform. A configuration packet will be produced on
- // demand by the main module. The main module will check the configuration once
- // every second or so to make sure it has the correct current data. The
- // configuration data structure is defined in SNFMilter.hpp.
- //
- // When the SNFMilter() function returns, the main() function closes down the
- // SNF Engine and exits the program.
-
- #include <errno.h>
- #include <string.h>
-
- #include <exception>
- #include <iostream>
- #include "SNFMulti.hpp"
- #include "SNFMilter.hpp"
-
- #include "config.h"
-
- using namespace std;
-
- const char* SNF_MILTER_VERSION = "SNFMilter " PACKAGE_VERSION " Build: " __DATE__ " " __TIME__;
-
- static const string XCIShutdownResponse =
- "<snf><xci><server><response message=\'shutdown in progress\' code=\'1\'/></server></xci></snf>\n";
-
- class XCIShutdownWatcher : public snfXCIServerCommandHandler { // Shutdown watcher.
- public:
- XCIShutdownWatcher(){}
- string processXCIRequest(snf_xci& X) { // Here is how we process requests.
- if(0 == X.xci_server_command.find("shutdown")) { // If we find shutdown then
- smfi_stop(); // Stop processing messages.
- return XCIShutdownResponse; // respond with a message.
- } // If we get some other request
- return XCIErrorResponse; // return the error response.
- }
- };
-
- class SignalCatcher : public Thread { // Class to catch a signal.
- private:
- sigset_t *MySignalSet;
- snf_RulebaseHandler *MyRulebase;
- public:
- SignalCatcher(sigset_t *Signal_Set, snf_RulebaseHandler* Rulebase) : // Construct.
- MySignalSet(Signal_Set), // Set of signals to catch.
- MyRulebase(Rulebase) { // Used for error logging.
- run(); // Start the thread.
- }
- void myTask() {
- int ReceivedSignal;
- int Status = sigwait(MySignalSet, &ReceivedSignal);
- if (0 != Status) {
- // Log error.
- ostringstream Temp;
- Temp << "Error waiting for signal: " << strerror(Status) << ".";
- MyRulebase->logThisError("Signal Catcher", 1, Temp.str());
- return;
- }
- smfi_stop(); // Stop processing.
- }
- };
-
- const int CorrectARGc = 2; // How many arguments we expect.
-
- void displayHelp() { // Display some help.
- cout
- << SNF_MILTER_VERSION << endl
- << "Copyright (C) 2007, ARM Research Labs, LLC (www.armresearch.com)" << endl
- << endl
- << "Use snfmilter <full path to configuration file>" << endl
- << "Example: /home/snfmilter/snfmilter /home/snfmilter/snf_milter.xml" << endl;
- };
-
- int main(int argc, char* argv[]) {
-
- // Get and check the command line arguments.
-
- if(CorrectARGc != argc) { // If our command line arguments
- displayHelp(); // don't look right then display
- return 0; // our help screen.
- }
-
- bool DebugMode = false; // This will be our debug mode.
- string argv0(argv[0]); // Capture how we were called.
- if(
- string::npos != argv0.find("Debug") || // If we find "Debug" or
- string::npos != argv0.find("debug") // "debug" in our command path
- ) { // then we are in DebugMode.
- DebugMode = true; // Set the flag and tell the
- cout << "Debug Mode" << endl; // watchers.
- }
-
- sigset_t SignalSet; // Set of signals to mask.
- SignalCatcher *SigCatcher; // Object to catch signal.
-
- try { // Catch anything that breaks loose.
-
- int PthreadStatus;
-
- if ( (0 != sigemptyset(&SignalSet)) || // Mask signal for this thread and
- // all threads to be created.
- (0 != sigaddset(&SignalSet, ShutdownSignal)) ) {
- ostringstream Temp;
-
- Temp << "Error masking signal on startup: " << strerror(errno) << ".";
- throw runtime_error(Temp.str());
- }
- PthreadStatus = pthread_sigmask(SIG_BLOCK, &SignalSet, 0);
- if (0 != PthreadStatus) {
- ostringstream Temp;
- Temp << "Error masking signal on startup (pthread_sigmask): " << strerror(PthreadStatus) << ".";
- throw runtime_error(Temp.str());
- }
-
- snf_RulebaseHandler* MilterRulebase = new snf_RulebaseHandler(); // Allocate a rulebase handler.
- MilterRulebase->PlatformVersion(SNF_MILTER_VERSION); // Record our version identification.
- XCIShutdownWatcher ShutdownWatcher; // Make a server shutdown processor
- MilterRulebase->XCIServerCommandHandler(ShutdownWatcher); // and register it with the engine.
- MilterRulebase->open(argv[1], "", ""); // Open the rulebase.
-
- SNFMilterContextPool* MilterContexts =
- new SNFMilterContextPool(MilterRulebase); // Create the Milter Context Pool.
-
- SigCatcher = new SignalCatcher(&SignalSet, MilterRulebase); // Create thread object to catch the signal.
-
- runLibMilter(MilterContexts, DebugMode); // Run the milter.
-
- ThreadState const &SigCatcherState = SigCatcher->MyState();
- if (Thread::ThreadStarted.Name == SigCatcherState.Name) { // Is the signal catcher thread running?
- PthreadStatus = pthread_kill(SigCatcher->getMyThread(), ShutdownSignal); // Yes. Send it a signal.
- if (0 == PthreadStatus) {
- SigCatcher->join(); // Wait for signal catcher to complete.
- } else {
- ostringstream Temp;
- Temp << "Error terminating signal catcher: " << strerror(PthreadStatus) << ".";
- throw runtime_error(Temp.str());
- }
- }
-
- delete MilterContexts; // Destroy the context pool.
- MilterContexts = 0; // Forget it.
- MilterRulebase->close(); // Close down the rulebase handler.
- delete MilterRulebase; // Destroy the rulebase.
- MilterRulebase = 0; // Forget it.
- delete SigCatcher; // Destroy the signal catcher.
- SigCatcher = 0; // Forget it.
-
- } // That's all folks.
-
- catch(exception& e) { // Report any normal exceptions.
- cerr << "SNFMilter Exception: " << e.what() << endl;
- }
- catch(...) { // Report any unexpected exceptions.
- cerr << "SNFMilter Panic! Unknown Exception!" << endl;
- }
-
- return 0; // Normally we return zero.
- }
-
|