Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

main.cpp 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // main.cpp
  2. //
  3. // Copyright (C) 2007, ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // This is the entry point for the SNF Milter.
  7. // The main() function acquires the configuration file path, sets up the
  8. // SNF engine, and passes control to the SNFMilter module via runSNFMilter().
  9. //
  10. // SNFMilter() makes use of the SNF engine until it is dismissed by the MTA via
  11. // the appropriate libmilter call.
  12. //
  13. // While SNFMilter() is running, it will get new configuration data for each
  14. // scan it is asked to perform. A configuration packet will be produced on
  15. // demand by the main module. The main module will check the configuration once
  16. // every second or so to make sure it has the correct current data. The
  17. // configuration data structure is defined in SNFMilter.hpp.
  18. //
  19. // When the SNFMilter() function returns, the main() function closes down the
  20. // SNF Engine and exits the program.
  21. #include <errno.h>
  22. #include <string.h>
  23. #include <exception>
  24. #include <iostream>
  25. #include "SNFMulti.hpp"
  26. #include "SNFMilter.hpp"
  27. #include "config.h"
  28. using namespace std;
  29. const char* SNF_MILTER_VERSION = "SNFMilter " PACKAGE_VERSION " Build: " __DATE__ " " __TIME__;
  30. static const string XCIShutdownResponse =
  31. "<snf><xci><server><response message=\'shutdown in progress\' code=\'1\'/></server></xci></snf>\n";
  32. class XCIShutdownWatcher : public snfXCIServerCommandHandler { // Shutdown watcher.
  33. public:
  34. XCIShutdownWatcher(){}
  35. string processXCIRequest(snf_xci& X) { // Here is how we process requests.
  36. if(0 == X.xci_server_command.find("shutdown")) { // If we find shutdown then
  37. smfi_stop(); // Stop processing messages.
  38. return XCIShutdownResponse; // respond with a message.
  39. } // If we get some other request
  40. return XCIErrorResponse; // return the error response.
  41. }
  42. };
  43. class SignalCatcher : public Thread { // Class to catch a signal.
  44. private:
  45. sigset_t *MySignalSet;
  46. snf_RulebaseHandler *MyRulebase;
  47. public:
  48. SignalCatcher(sigset_t *Signal_Set, snf_RulebaseHandler* Rulebase) : // Construct.
  49. MySignalSet(Signal_Set), // Set of signals to catch.
  50. MyRulebase(Rulebase) { // Used for error logging.
  51. run(); // Start the thread.
  52. }
  53. void myTask() {
  54. int ReceivedSignal;
  55. int Status = sigwait(MySignalSet, &ReceivedSignal);
  56. if (0 != Status) {
  57. // Log error.
  58. ostringstream Temp;
  59. Temp << "Error waiting for signal: " << strerror(Status) << ".";
  60. MyRulebase->logThisError("Signal Catcher", 1, Temp.str());
  61. return;
  62. }
  63. smfi_stop(); // Stop processing.
  64. }
  65. };
  66. const int CorrectARGc = 2; // How many arguments we expect.
  67. void displayHelp() { // Display some help.
  68. cout
  69. << SNF_MILTER_VERSION << endl
  70. << "Copyright (C) 2007, ARM Research Labs, LLC (www.armresearch.com)" << endl
  71. << endl
  72. << "Use snfmilter <full path to configuration file>" << endl
  73. << "Example: /home/snfmilter/snfmilter /home/snfmilter/snf_milter.xml" << endl;
  74. };
  75. int main(int argc, char* argv[]) {
  76. // Get and check the command line arguments.
  77. if(CorrectARGc != argc) { // If our command line arguments
  78. displayHelp(); // don't look right then display
  79. return 0; // our help screen.
  80. }
  81. bool DebugMode = false; // This will be our debug mode.
  82. string argv0(argv[0]); // Capture how we were called.
  83. if(
  84. string::npos != argv0.find("Debug") || // If we find "Debug" or
  85. string::npos != argv0.find("debug") // "debug" in our command path
  86. ) { // then we are in DebugMode.
  87. DebugMode = true; // Set the flag and tell the
  88. cout << "Debug Mode" << endl; // watchers.
  89. }
  90. sigset_t SignalSet; // Set of signals to mask.
  91. SignalCatcher *SigCatcher; // Object to catch signal.
  92. try { // Catch anything that breaks loose.
  93. int PthreadStatus;
  94. if ( (0 != sigemptyset(&SignalSet)) || // Mask signal for this thread and
  95. // all threads to be created.
  96. (0 != sigaddset(&SignalSet, ShutdownSignal)) ) {
  97. ostringstream Temp;
  98. Temp << "Error masking signal on startup: " << strerror(errno) << ".";
  99. throw runtime_error(Temp.str());
  100. }
  101. PthreadStatus = pthread_sigmask(SIG_BLOCK, &SignalSet, 0);
  102. if (0 != PthreadStatus) {
  103. ostringstream Temp;
  104. Temp << "Error masking signal on startup (pthread_sigmask): " << strerror(PthreadStatus) << ".";
  105. throw runtime_error(Temp.str());
  106. }
  107. snf_RulebaseHandler* MilterRulebase = new snf_RulebaseHandler(); // Allocate a rulebase handler.
  108. MilterRulebase->PlatformVersion(SNF_MILTER_VERSION); // Record our version identification.
  109. XCIShutdownWatcher ShutdownWatcher; // Make a server shutdown processor
  110. MilterRulebase->XCIServerCommandHandler(ShutdownWatcher); // and register it with the engine.
  111. MilterRulebase->open(argv[1], "", ""); // Open the rulebase.
  112. SNFMilterContextPool* MilterContexts =
  113. new SNFMilterContextPool(MilterRulebase); // Create the Milter Context Pool.
  114. SigCatcher = new SignalCatcher(&SignalSet, MilterRulebase); // Create thread object to catch the signal.
  115. runLibMilter(MilterContexts, DebugMode); // Run the milter.
  116. ThreadState const &SigCatcherState = SigCatcher->MyState();
  117. if (Thread::ThreadStarted.Name == SigCatcherState.Name) { // Is the signal catcher thread running?
  118. PthreadStatus = pthread_kill(SigCatcher->getMyThread(), ShutdownSignal); // Yes. Send it a signal.
  119. if (0 == PthreadStatus) {
  120. SigCatcher->join(); // Wait for signal catcher to complete.
  121. } else {
  122. ostringstream Temp;
  123. Temp << "Error terminating signal catcher: " << strerror(PthreadStatus) << ".";
  124. throw runtime_error(Temp.str());
  125. }
  126. }
  127. delete MilterContexts; // Destroy the context pool.
  128. MilterContexts = 0; // Forget it.
  129. MilterRulebase->close(); // Close down the rulebase handler.
  130. delete MilterRulebase; // Destroy the rulebase.
  131. MilterRulebase = 0; // Forget it.
  132. delete SigCatcher; // Destroy the signal catcher.
  133. SigCatcher = 0; // Forget it.
  134. } // That's all folks.
  135. catch(exception& e) { // Report any normal exceptions.
  136. cerr << "SNFMilter Exception: " << e.what() << endl;
  137. }
  138. catch(...) { // Report any unexpected exceptions.
  139. cerr << "SNFMilter Panic! Unknown Exception!" << endl;
  140. }
  141. return 0; // Normally we return zero.
  142. }