subclass of Utility. git-svn-id: https://svn.microneil.com/svn/SNFUtility/trunk@7 aa37657e-1934-4a5f-aa6d-2d8eab27ff7cmaster
@@ -12,19 +12,23 @@ CXXFLAGS = $(SNF_CXXFLAGS) -I@top_srcdir@/SNFMulti \ | |||
-DSNF_OSTYPE=\"$(SNF_OSTYPE)\" -DDEFAULT_DATA_DIR=\"@datadir@/$(PACKAGE_NAME)\" \ | |||
-DSBIN_DIR=\"$(DESTDIR)$(sbindir)\" | |||
noinst_LIBRARIES = \ | |||
noinst_LIBRARIES = \ | |||
libUtilityCommon.a | |||
libUtilityCommon_a_SOURCES = \ | |||
@top_srcdir@/SNFUtility/Common/UtilityConfig.cpp \ | |||
libUtilityCommon_a_SOURCES = \ | |||
@top_srcdir@/SNFUtility/Common/Utility.cpp \ | |||
@top_srcdir@/SNFUtility/Common/UtilityConfig.cpp \ | |||
@top_srcdir@/SNFUtility/Common/MtaIntegrate.cpp \ | |||
@top_srcdir@/SNFUtility/Common/FileBackup.cpp | |||
noinst_HEADERS = \ | |||
@top_srcdir@/SNFUtility/Common/UtilityConfig.hpp \ | |||
noinst_HEADERS = \ | |||
@top_srcdir@/SNFUtility/Common/Utility.hpp \ | |||
@top_srcdir@/SNFUtility/Common/UtilityConfig.hpp \ | |||
@top_srcdir@/SNFUtility/Common/MtaIntegrate.hpp \ | |||
@top_srcdir@/SNFUtility/Common/FileBackup.hpp | |||
EXTRA_DIST = \ | |||
Makefile.am \ | |||
EXTRA_DIST = \ | |||
Makefile.am \ | |||
ChangeLog | |||
clean-local: |
@@ -0,0 +1,22 @@ | |||
// /file MtaIntegrate.cpp | |||
// | |||
// Copyright (C) 2011, ARM Research Labs, LLC. | |||
// See www.armresearch.com for the copyright terms. | |||
// | |||
// This file contains the functions for MtaIntegrate. | |||
// | |||
// $Id$ | |||
// | |||
/////////////////////////////////////////////////////////////////////////////////////////////////// | |||
#include <iostream> | |||
#include "MtaIntegrate.hpp" | |||
MtaIntegrate::MtaIntegrate() { | |||
SetExplain(false); | |||
SetVerbose(false); | |||
SetHelp(false); | |||
} |
@@ -0,0 +1,64 @@ | |||
// \file MtaIntegrate.hpp | |||
// | |||
// Copyright (C) 2011 ARM Research Labs, LLC. | |||
// See www.armresearch.com for the copyright terms. | |||
// | |||
// This file defines the MtaIntegrate interface. | |||
// | |||
// $Id$ | |||
// | |||
/////////////////////////////////////////////////////////////////////////////////////////////////// | |||
#ifndef MtaIntegratehpp_included | |||
#define MtaIntegratehpp_included | |||
#include <string> | |||
#include "Utility.hpp" | |||
#include "FileBackup.hpp" | |||
/// Base class to manage a Sniffer integration with an MTA. | |||
// | |||
// This class defines the interface to integrate and unintegrate with an MTA. | |||
// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class MtaIntegrate : public Utility { | |||
public: | |||
/// Constructor. | |||
MtaIntegrate(); | |||
/// Specifies the operating system type. | |||
// | |||
// \param[in] OperatingSystemType is the value of SNF_OSTYPE | |||
// specified when configuring sniffer for *nix, or "Windows". | |||
// | |||
virtual void SetOperatingSystem(std::string OperatingSystemType) = 0; | |||
/// Integrate with the MTA. | |||
// | |||
// If the MTA is already integrated, this method does nothing. | |||
// | |||
// \param[in] SaveFile is the object to back up any configuration | |||
// files. | |||
// | |||
virtual void Integrate(FileBackup *SaveFile) = 0; | |||
/// Unintegrate with the MTA. | |||
// | |||
// If the MTA is not integrated, this method does nothing. | |||
// | |||
// \param[in] SaveFile is the object to back up any configuration | |||
// files. | |||
// | |||
virtual void Unintegrate(FileBackup *SaveFile) = 0; | |||
private: | |||
/// Determine whether the MTA is integrated. | |||
virtual bool IsIntegrated() = 0; | |||
}; | |||
#endif |
@@ -0,0 +1,325 @@ | |||
// Utility.cpp | |||
// | |||
// Copyright (C) 2011, ARM Research Labs, LLC. | |||
// See www.armresearch.com for the copyright terms. | |||
// | |||
// This file implements the common functionality for the configuration | |||
// utilities. | |||
#include <cerrno> | |||
#include <cstring> | |||
#include <unistd.h> | |||
#include <pwd.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <stdexcept> | |||
#include <sstream> | |||
#include <iostream> | |||
#include <fstream> | |||
#include <vector> | |||
#include "Utility.hpp" | |||
using namespace std; | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
// Configuration. //////////////////////////////////////////////////////////////////////////////////////// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
const std::string Utility::DirectorySeparator("/"); | |||
/// SNF user name. | |||
const string SNFUserName = "snfuser"; | |||
/// SNF group name. | |||
const string SNFGroupName = "snfuser"; | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
bool | |||
Utility::FileExists(const std::string File) { | |||
if (Verbose()) { | |||
cout << "Check whether " << File << " exists..."; | |||
} | |||
bool Exists; | |||
std::ifstream Input; | |||
errno = 0; | |||
Input.open(File.c_str()); | |||
if (ENOENT == errno) { | |||
Exists = false; | |||
} else { | |||
Exists = true; | |||
} | |||
Input.close(); | |||
OutputVerboseEnd(); | |||
return Exists; | |||
} | |||
void | |||
Utility::Copy(std::string From, std::string To) { | |||
if (Verbose()) { | |||
cout << "Copy " << From << " to " << To << "..."; | |||
} | |||
if (!Explain()) { | |||
std::ifstream Input; | |||
Input.open(From.c_str()); | |||
if (!Input) { | |||
std::string Temp; | |||
Temp = "Error opening the file " + From; | |||
Temp += " to read from: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
std::ofstream Output; | |||
Output.open(To.c_str(), std::ios::trunc); | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error opening the file " + To; | |||
Temp += " to copy to: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
if (!Input.eof()) { // Copy if there are characters. | |||
// Copying an empty file causes | |||
Output << Input.rdbuf(); // failbit to be set. | |||
} | |||
if (Output.bad() || Output.fail()) { | |||
std::string Temp; | |||
Temp = "Error copying " + From; | |||
Temp += " to " + To; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
Input.close(); | |||
if (!Input) { | |||
std::string Temp; | |||
Temp = "Error closing the file " + From; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
Output.close(); | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error closing the file " + To; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
Utility::SetOwnerGroup(std::string &File) { | |||
struct passwd *SNFPasswd; | |||
uid_t SNFUid; | |||
struct group *SNFGroup; | |||
gid_t SNFGid; | |||
if (Verbose()) { | |||
cout << "Set owner:group of " << File << " to " | |||
<< SNFUserName << ":" << SNFGroupName << "..."; | |||
} | |||
if (!Explain()) { | |||
SNFPasswd = getpwnam(SNFUserName.c_str()); | |||
if (SNFPasswd == 0) { | |||
string Temp; | |||
Temp = "Error getting info for Sniffer user " + SNFUserName; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
SNFUid = SNFPasswd->pw_uid; | |||
SNFGid = SNFPasswd->pw_gid; | |||
if (chown(File.c_str(), SNFUid, SNFGid) != 0) { | |||
string Temp; | |||
Temp = "Error changing group and owner of file " + File; | |||
Temp += " to " + SNFUserName + ":" + SNFGroupName; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
Utility::SetMode(std::string &File, mode_t mode) { | |||
if (Verbose()) { | |||
cout << "Set mode of " << File << " to " | |||
<< std::oct << mode << "..."; | |||
} | |||
if (!Explain()) { | |||
if (chmod(File.c_str(), mode) != 0) { | |||
ostringstream Temp; | |||
Temp << "Error changing permissions of file " << File | |||
<< " to " << mode << ": " << strerror(errno); | |||
throw runtime_error(Temp.str()); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
Utility::MkDir(std::string &Dir) { | |||
if (Verbose()) { | |||
cout << "Create directory " << Dir << "..."; | |||
} | |||
if (!Explain()) { | |||
if (mkdir(Dir.c_str(), 0) != 0) { | |||
ostringstream Temp; | |||
Temp << "Error creating directory " << Dir << ": " << strerror(errno); | |||
throw runtime_error(Temp.str()); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
bool | |||
Utility::CheckForString(std::string Line, std::string SearchString) { | |||
string::size_type Indx; | |||
Indx = Line.find_first_not_of(" \t"); // Trim leading whitespace. | |||
if (string::npos != Indx) { | |||
Line = Line.substr(Indx); | |||
} | |||
if (Line.substr(0, SearchString.length()) == SearchString) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
void | |||
Utility::SetVerbose(bool Mode) { | |||
VerboseRequested = Mode; | |||
} | |||
bool | |||
Utility::Verbose() { | |||
return (VerboseRequested || ExplainRequested); | |||
} | |||
void | |||
Utility::SetExplain(bool Mode) { | |||
ExplainRequested = Mode; | |||
} | |||
bool | |||
Utility::Explain() { | |||
return ExplainRequested; | |||
} | |||
void | |||
Utility::SetHelp(bool Mode) { | |||
HelpRequested = Mode; | |||
} | |||
bool | |||
Utility::Help() { | |||
return HelpRequested; | |||
} | |||
void | |||
Utility::OutputVerboseEnd() { | |||
if (Verbose() && !Explain()) { | |||
cout << "done.\n"; | |||
} else if (Explain()) { | |||
cout << "\n"; | |||
} | |||
} |
@@ -0,0 +1,139 @@ | |||
// Utility.hpp | |||
// | |||
// Copyright (C) 2011 ARM Research Labs, LLC. | |||
// See www.armresearch.com for the copyright terms. | |||
// | |||
// This file defines the interface used by the configuration utilities. | |||
// | |||
#ifndef Utilityhpp_included | |||
#define Utilityhpp_included | |||
#include <sys/stat.h> | |||
#include <string> | |||
/// Base class for the Sniffer configuration. | |||
// | |||
// This class provides capability common to the configuration classes. | |||
// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class Utility { | |||
public: | |||
/// Default constructor. | |||
Utility(); | |||
/// Check whether a file exists. | |||
// | |||
// \returns true if the file exists, false otherwise. | |||
// | |||
bool FileExists(std::string File); | |||
/// Copy a file. | |||
// | |||
// \param[in] From is the name of the source file. | |||
// | |||
// \param[in] To is the name of the destination file. | |||
// | |||
void Copy(std::string From, std::string To); | |||
/// Set the owner and group of the specified file. | |||
// | |||
// This function sets the owner and group of the specified file to the | |||
// value specified in Utility.cpp. | |||
// | |||
// \param[in] File is the specified file. | |||
// | |||
// \see SNFUserName. | |||
// | |||
// \see SNFGroupName. | |||
// | |||
void SetOwnerGroup(std::string &File); | |||
/// Set the mode of a file. | |||
// | |||
// This function sets the mode of the specified file. If an error | |||
// occurs, an exception is thrown. | |||
// | |||
// \param[in] File is the specified file. | |||
// | |||
// \param[in] is the mode. | |||
// | |||
void SetMode(std::string &File, mode_t mode); | |||
/// Create a directory. | |||
// | |||
// This function creates the specified directory. If an error | |||
// occurs, an exception is thrown. | |||
// | |||
// \param[in] Dir is the directory to create. | |||
// | |||
void MkDir(std::string &Dir); | |||
/// Check for a specified string at the beginning of a line. | |||
// | |||
// This function checks for the specified string at the beginning of a | |||
// line. Leading whitespace in the line is ignored. | |||
// | |||
// \param[in] Line is the line. | |||
// | |||
// \param[in] SearchString is the string to check for. | |||
// | |||
static bool CheckForString(std::string Line, std::string SearchString); | |||
/// Store the Verbose mode. | |||
// | |||
// \param[in] Mode stores the Verbose mode. | |||
// | |||
void SetVerbose(bool Mode); | |||
/// Provide verbose output? | |||
// | |||
// \returns true if the application is to provide verbose output. | |||
// | |||
bool Verbose(); | |||
/// Store the Explain mode. | |||
// | |||
// \param[in] Mode stores the Explain mode. | |||
// | |||
void SetExplain(bool Mode); | |||
/// Provide an explanation of the actions only? | |||
// | |||
// \returns true if the application is to provide an explanation | |||
// of the actions without executing any commands. | |||
// | |||
bool Explain(); | |||
/// Store the Help mode. | |||
// | |||
// \param[in] Mode stores the Help mode. | |||
// | |||
void SetHelp(bool Mode); | |||
/// Provide help? | |||
// | |||
// \returns true if the application is to output a help message. | |||
// | |||
bool Help(); | |||
/// Output the end of a verbose output line. | |||
void OutputVerboseEnd(); | |||
/// Directory separator. | |||
static const std::string DirectorySeparator; | |||
private: | |||
bool VerboseRequested; ///< User requested verbose processing. | |||
bool ExplainRequested; ///< User requested verbose processing but without actually executing the commands. | |||
bool HelpRequested; ///< User requested help. | |||
}; | |||
#endif |
@@ -71,9 +71,7 @@ const std::string UtilityConfig::SampleRulebaseScriptFile(SBIN_DIR "/getRulebase | |||
#ifdef WIN | |||
// Windows OS. | |||
const std::string UtilityConfig::OperatingSystemType("Windows"); | |||
const std::string DirectorySeparator("\\"); | |||
#else | |||
const std::string DirectorySeparator("/"); | |||
#ifdef SNF_OSTYPE | |||
// *nix, SNF_OSTYPE is specified on the compile command line. | |||
const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE); | |||
@@ -84,12 +82,6 @@ const std::string UtilityConfig::OperatingSystemType(SNF_OSTYPE); | |||
#endif | |||
#endif | |||
/// SNF user name. | |||
const string SNFUserName = "snfuser"; | |||
/// SNF group name. | |||
const string SNFGroupName = "snfuser"; | |||
/// Verbose command-line input. | |||
const string VerboseKey("-v"); | |||
@@ -103,46 +95,13 @@ const string HelpKey("-h"); | |||
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
UtilityConfig::UtilityConfig() : | |||
ExplainRequested(false), VerboseRequested(false), HelpRequested(false) { | |||
} | |||
bool | |||
UtilityConfig::FileExists(const std::string File) { | |||
if (Verbose()) { | |||
cout << "Check whether " << File << " exists..."; | |||
} | |||
struct stat StatBuf; | |||
if (0 != stat(File.c_str(), &StatBuf)) { // Error checking whether file exists. | |||
UtilityConfig::UtilityConfig() { | |||
if (ENOENT == errno) { // Doesn't exist. | |||
OutputVerboseEnd(); | |||
return false; | |||
} | |||
string Temp; // Other error from stat(). | |||
Temp = "Error getting info for file " + File; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
OutputVerboseEnd(); | |||
SetExplain(false); | |||
SetVerbose(false); | |||
SetHelp(false); | |||
return true; | |||
} | |||
} | |||
void | |||
UtilityConfig::CheckAndLoadConfigFile(const std::string DefaultFile[], int NumDefaultFiles) { | |||
@@ -311,192 +270,6 @@ UtilityConfig::GetRulebaseScriptName(void) { | |||
} | |||
void | |||
UtilityConfig::Copy(std::string From, std::string To) { | |||
if (Verbose()) { | |||
cout << "Copy " << From << " to " << To << "..."; | |||
} | |||
if (!Explain()) { | |||
ifstream Input; | |||
Input.open(From.c_str()); // Read the contents. | |||
if (!Input) { | |||
string Temp; | |||
Temp = "Error opening the file " + From; | |||
Temp += " to copy from: "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
string Content; | |||
string Line; | |||
while (getline(Input, Line)) { | |||
Content += Line + "\n"; // Copy this line. | |||
} | |||
if (!Input.eof()) { // Should be at end-of-file. | |||
string Temp; | |||
Temp = "Error reading the " + From; | |||
Temp += " to copy from: "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
Input.close(); | |||
if (Input.bad()) { | |||
string Temp; | |||
Temp = "Error closing the file " + From; | |||
Temp += " to copy from: "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
ofstream Output; // Write the contents. | |||
Output.open(To.c_str(), ios::trunc); | |||
if (!Output) { | |||
string Temp; | |||
Temp = "Error opening the file " + To; | |||
Temp += " to copy to: "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
Output << Content; | |||
if (!Output) { | |||
string Temp; | |||
Temp = "Error writing the file " + To; | |||
Temp += " to copy to: "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
Output.close(); | |||
if (!Output) { | |||
string Temp; | |||
Temp = "Error closing the file " + To; | |||
Temp += " to copy to: "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
UtilityConfig::SetOwnerGroup(std::string &File) { | |||
struct passwd *SNFPasswd; | |||
uid_t SNFUid; | |||
struct group *SNFGroup; | |||
gid_t SNFGid; | |||
if (Verbose()) { | |||
cout << "Set owner:group of " << File << " to " | |||
<< SNFUserName << ":" << SNFGroupName << "..."; | |||
} | |||
if (!Explain()) { | |||
SNFPasswd = getpwnam(SNFUserName.c_str()); | |||
if (SNFPasswd == 0) { | |||
string Temp; | |||
Temp = "Error getting info for Sniffer user " + SNFUserName; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
SNFUid = SNFPasswd->pw_uid; | |||
SNFGid = SNFPasswd->pw_gid; | |||
if (chown(File.c_str(), SNFUid, SNFGid) != 0) { | |||
string Temp; | |||
Temp = "Error changing group and owner of file " + File; | |||
Temp += " to " + SNFUserName + ":" + SNFGroupName; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw runtime_error(Temp); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
UtilityConfig::SetMode(std::string &File, mode_t mode) { | |||
if (Verbose()) { | |||
cout << "Set mode of " << File << " to " | |||
<< std::oct << mode << "..."; | |||
} | |||
if (!Explain()) { | |||
if (chmod(File.c_str(), mode) != 0) { | |||
ostringstream Temp; | |||
Temp << "Error changing permissions of file " << File | |||
<< " to " << mode << ": " << strerror(errno); | |||
throw runtime_error(Temp.str()); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
UtilityConfig::MkDir(std::string &Dir) { | |||
if (Verbose()) { | |||
cout << "Create directory " << Dir << "..."; | |||
} | |||
if (!Explain()) { | |||
if (mkdir(Dir.c_str(), 0) != 0) { | |||
ostringstream Temp; | |||
Temp << "Error creating directory " << Dir << ": " << strerror(errno); | |||
throw runtime_error(Temp.str()); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
UtilityConfig::StartOrRestartMta(std::string Mta) { | |||
@@ -516,29 +289,6 @@ UtilityConfig::StartOrRestartMta(std::string Mta) { | |||
} | |||
bool | |||
UtilityConfig::CheckForString(std::string Line, std::string SearchString) { | |||
string::size_type Indx; | |||
Indx = Line.find_first_not_of(" \t"); // Trim leading whitespace. | |||
if (string::npos != Indx) { | |||
Line = Line.substr(Indx); | |||
} | |||
if (Line.substr(0, SearchString.length()) == SearchString) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
void | |||
UtilityConfig::LoadInfo(){ | |||
@@ -594,14 +344,17 @@ UtilityConfig::UpdateIgnoreListFile() { | |||
IgnoreListFile = IgnoreListPath + DirectorySeparator; | |||
IgnoreListFile += "GBUdbIgnoreList.txt"; | |||
SaveFile.CreateBackupFile(IgnoreListFile); // Save any existing file. | |||
if (!FileExists(IgnoreListFile)) { | |||
Copy(SampleIgnoreListFile, IgnoreListFile); // Use SNFMilter.xml.sample. | |||
Copy(SampleIgnoreListFile, IgnoreListFile); // Use SNFMilter.xml.sample. | |||
} | |||
SetMode(IgnoreListFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. | |||
SetOwnerGroup(IgnoreListFile); // Set to sniffer user. | |||
SetMode(IgnoreListFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. | |||
SetOwnerGroup(IgnoreListFile); // Set to sniffer user. | |||
} | |||
@@ -628,17 +381,17 @@ UtilityConfig::ProcessCommandLineItem(std::string OneInput) { | |||
if (OneInput == VerboseKey) { | |||
VerboseRequested = true; | |||
SetVerbose(true); | |||
ValidCommand = true; | |||
} else if (OneInput == ExplainKey) { | |||
ExplainRequested = true; | |||
SetExplain(true); | |||
ValidCommand = true; | |||
} else if (OneInput == HelpKey) { | |||
HelpRequested = true; | |||
SetHelp(true); | |||
ValidCommand = true; | |||
} | |||
@@ -647,27 +400,6 @@ UtilityConfig::ProcessCommandLineItem(std::string OneInput) { | |||
} | |||
bool | |||
UtilityConfig::Verbose() { | |||
return (VerboseRequested || ExplainRequested); | |||
} | |||
bool | |||
UtilityConfig::Explain() { | |||
return ExplainRequested; | |||
} | |||
bool | |||
UtilityConfig::Help() { | |||
return HelpRequested; | |||
} | |||
std::string | |||
UtilityConfig::HelpCommandLine() { | |||
@@ -691,18 +423,3 @@ UtilityConfig::HelpDescription() { | |||
return Desc; | |||
} | |||
void | |||
UtilityConfig::OutputVerboseEnd() { | |||
if (Verbose() && !Explain()) { | |||
cout << "done.\n"; | |||
} else if (Explain()) { | |||
cout << "\n"; | |||
} | |||
} |
@@ -9,28 +9,26 @@ | |||
#ifndef UtilityConfighpp_included | |||
#define UtilityConfighpp_included | |||
#include "SNFMulti.hpp" | |||
#include <string> | |||
#include "SNFMulti.hpp" | |||
#include "Utility.hpp" | |||
#include "FileBackup.hpp" | |||
/// Base class for the Sniffer configuration. | |||
// | |||
// This class provides capability common to the configuration applications. | |||
// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class UtilityConfig { | |||
class UtilityConfig : public Utility { | |||
public: | |||
/// Default constructor. | |||
UtilityConfig(); | |||
/// Check whether a file exists. | |||
// | |||
// \returns true if the file exists, false otherwise. | |||
// | |||
bool FileExists(std::string File); | |||
/// Object to back up and restore files. | |||
FileBackup SaveFile; | |||
/// Load the specified or default config file. | |||
// | |||
@@ -102,47 +100,6 @@ public: | |||
// \returns the rulebase script file name. | |||
std::string GetRulebaseScriptName(void); | |||
/// Copy a file. | |||
// | |||
// \param[in] From is the name of the source file. | |||
// | |||
// \param[in] To is the name of the destination file. | |||
// | |||
void Copy(std::string From, std::string To); | |||
/// Set the owner and group of the specified file. | |||
// | |||
// This function sets the owner and group of the specified file to the | |||
// value specified in UtilityConfig.cpp. | |||
// | |||
// \param[in] File is the specified file. | |||
// | |||
// \see SNFUserName. | |||
// | |||
// \see SNFGroupName. | |||
// | |||
void SetOwnerGroup(std::string &File); | |||
/// Set the mode of a file. | |||
// | |||
// This function sets the mode of the specified file. If an error | |||
// occurs, an exception is thrown. | |||
// | |||
// \param[in] File is the specified file. | |||
// | |||
// \param[in] is the mode. | |||
// | |||
void SetMode(std::string &File, mode_t mode); | |||
/// Create a directory. | |||
// | |||
// This function creates the specified directory. If an error | |||
// occurs, an exception is thrown. | |||
// | |||
// \param[in] Dir is the directory to create. | |||
// | |||
void MkDir(std::string &Dir); | |||
/// Restart the MTA. | |||
// | |||
// This function starts or restarts the MTA. | |||
@@ -152,17 +109,6 @@ public: | |||
// | |||
void StartOrRestartMta(std::string Mta); | |||
/// Check for a specified string at the beginning of a line. | |||
// | |||
// This function checks for the specified string at the beginning of a | |||
// line. Leading whitespace in the line is ignored. | |||
// | |||
// \param[in] Line is the line. | |||
// | |||
// \param[in] SearchString is the string to check for. | |||
// | |||
static bool CheckForString(std::string Line, std::string SearchString); | |||
/// Operating system specification. | |||
enum OperatingSystemSpecEnum { | |||
OpenBSD, ///< OpenBSD OS. | |||
@@ -185,7 +131,7 @@ public: | |||
/// Postfix main.cf file path. | |||
std::string PostfixMainCfPath; | |||
/// Postfix main.cf file path. | |||
/// Postfix master.cf file path. | |||
std::string PostfixMasterCfPath; | |||
/// Create or update the ignore list file. | |||
@@ -210,42 +156,14 @@ public: | |||
// | |||
bool ProcessCommandLineItem(std::string OneInput); | |||
/// Provide verbose output? | |||
// | |||
// \returns true if the application is to provide verbose output. | |||
// | |||
bool Verbose(); | |||
/// Provide an explanation of the actions only? | |||
// | |||
// \returns true if the application is to provide an explanation | |||
// of the actions without executing any commands. | |||
// | |||
bool Explain(); | |||
/// Provide help? | |||
// | |||
// \returns true if the application is to output a help message. | |||
// | |||
bool Help(); | |||
/// Output the legal command-line input. | |||
std::string HelpCommandLine(); | |||
/// Output the description of the legal command-line input. | |||
std::string HelpDescription(); | |||
/// Output the end of a verbose output line. | |||
void OutputVerboseEnd(); | |||
private: | |||
bool VerboseRequested; ///< User requested verbose processing. | |||
bool ExplainRequested; ///< User requested verbose processing but without actually executing the commands. | |||
bool HelpRequested; ///< User requested help. | |||
std::string ConfigFile; ///< Configuration file name. | |||
static const std::string SampleIgnoreListFile; ///< Sample ignore list file. | |||
static const std::string SampleRulebaseScriptFile; ///< Sample rulebase script file. |
@@ -22,10 +22,12 @@ sbin_PROGRAMS = \ | |||
SNFMilterConfig_SOURCES = \ | |||
@top_srcdir@/SNFUtility/SNFMilterConfig/main.cpp \ | |||
@top_srcdir@/SNFUtility/SNFMilterConfig/SNFMilterConfig.cpp | |||
@top_srcdir@/SNFUtility/SNFMilterConfig/SNFMilterConfig.cpp \ | |||
@top_srcdir@/SNFUtility/SNFMilterConfig/PostfixIntegrate.cpp | |||
noinst_HEADERS = \ | |||
@top_srcdir@/SNFUtility/SNFMilterConfig/SNFMilterConfig.hpp | |||
@top_srcdir@/SNFUtility/SNFMilterConfig/SNFMilterConfig.hpp \ | |||
@top_srcdir@/SNFUtility/SNFMilterConfig/PostfixIntegrate.hpp | |||
EXTRA_DIST = \ | |||
Makefile.am \ |
@@ -0,0 +1,303 @@ | |||
// /file PostfixIntegrate.cpp | |||
// | |||
// Copyright (C) 2011, ARM Research Labs, LLC. | |||
// See www.armresearch.com for the copyright terms. | |||
// | |||
// This file contains the functions for PostfixIntegrate. | |||
// | |||
// $Id$ | |||
// | |||
/////////////////////////////////////////////////////////////////////////////////////////////////// | |||
#include <errno.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <sys/types.h> | |||
#include <pwd.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <unistd.h> | |||
#include <iostream> | |||
#include <exception> | |||
#include <stdexcept> | |||
#include <sstream> | |||
#include <fstream> | |||
#include <vector> | |||
#include "PostfixIntegrate.hpp" | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
// Configuration. //////////////////////////////////////////////////////////////////////////////////////// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
const std::string SnfMilterMainCfSearchString("Added by PostfixIntegrate"); | |||
const std::string SnfMilterMainCfIntegrationString("smtpd_milters = unix:/var/snf-milter/socket $smtpd_milters # Added by PostfixIntegrate"); | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
// End of configuration. ///////////////////////////////////////////////////////////////////////////////// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
void | |||
PostfixIntegrate::SetOperatingSystem(std::string OperatingSystemType) { | |||
if ("OpenBSD" == OperatingSystemType) { | |||
PostfixMainCfPath = "/usr/local/etc/postfix/main.cf"; | |||
PostfixMasterCfPath = "/usr/local/etc/postfix/master.cf"; | |||
} else if ("FreeBSD" == OperatingSystemType) { | |||
PostfixMainCfPath = "/etc/postfix/main.cf"; | |||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | |||
} else if ("Ubuntu" == OperatingSystemType) { | |||
PostfixMainCfPath = "/etc/postfix/main.cf"; | |||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | |||
} else if ("RedHat" == OperatingSystemType) { | |||
PostfixMainCfPath = "/etc/postfix/main.cf"; | |||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | |||
} else if ("Suse" == OperatingSystemType) { | |||
PostfixMainCfPath = "/etc/postfix/main.cf"; | |||
PostfixMasterCfPath = "/etc/postfix/master.cf"; | |||
} else { | |||
std::ostringstream Temp; | |||
Temp << "***Error from PostfixIntegrate::SetOperatingSystem: Invalid value of OperatingSystemType: " | |||
<< OperatingSystemType; | |||
throw std::runtime_error(Temp.str()); | |||
} | |||
} | |||
void | |||
PostfixIntegrate::Integrate(FileBackup *SaveFile) { | |||
if (IsIntegrated()) { | |||
return; | |||
} | |||
if (Verbose()) { | |||
std::cout << "Add to postfix file " << PostfixMainCfPath << ": '" | |||
<< SnfMilterMainCfIntegrationString << "'..."; | |||
} | |||
if (!Explain()) { | |||
std::ofstream Output; // Append the configuration. | |||
Output.open(PostfixMainCfPath.c_str(), std::ios::app); | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " for writing: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
Output << SnfMilterMainCfIntegrationString << "\n"; | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error appending to the postfix configuration file " + PostfixMainCfPath; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
Output.close(); | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " after appending: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
void | |||
PostfixIntegrate::Unintegrate(FileBackup *SaveFile) { | |||
if (!IsIntegrated()) { | |||
return; | |||
} | |||
std::ifstream Input; | |||
if (Verbose()) { | |||
std::cout << "Remove integration in postfix file " << PostfixMainCfPath << "--\n"; | |||
} | |||
Input.open(PostfixMainCfPath.c_str()); // Read the contents. | |||
if (!Input) { | |||
std::string Temp; | |||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " for reading: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
std::string Content; | |||
std::string Line; | |||
while (getline(Input, Line)) { | |||
if (std::string::npos != Line.find(SnfMilterMainCfSearchString)) { // Check for integration line. | |||
if (Verbose()) { | |||
std::cout << " Remove '" << Line << "'...\n"; | |||
} | |||
continue; // Do not copy this line. | |||
} | |||
Content += Line + "\n"; // Copy this line. | |||
} | |||
if (!Input.eof()) { // Should be at end-of-file. | |||
std::string Temp; | |||
Temp = "Error reading the postfix configuration file " + PostfixMainCfPath; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
Input.close(); | |||
if (Input.bad()) { | |||
std::string Temp; | |||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " after reading: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
if (!Explain()) { | |||
std::ofstream Output; // Write the updated contents. | |||
Output.open(PostfixMainCfPath.c_str(), std::ios::trunc); | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " for writing: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
Output << Content; | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error writing the postfix configuration file " + PostfixMainCfPath; | |||
Temp += ": "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
Output.close(); | |||
if (!Output) { | |||
std::string Temp; | |||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " after writing: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
} | |||
OutputVerboseEnd(); | |||
} | |||
bool | |||
PostfixIntegrate::IsIntegrated() { | |||
if (!FileExists(PostfixMainCfPath)) { | |||
return false; | |||
} | |||
bool Integrated = false; | |||
if (Verbose()) { | |||
std::cout << "Checking for any SNFMilter integration in the postfix file " << PostfixMainCfPath << "--\n"; | |||
} | |||
std::ifstream Input; | |||
Input.open(PostfixMainCfPath.c_str()); // Read the contents. | |||
if (!Input) { | |||
std::string Temp; | |||
Temp = "Error opening the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " for reading: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
std::string Line; | |||
while (getline(Input, Line)) { | |||
if (std::string::npos != Line.find(SnfMilterMainCfSearchString)) { // Check for integration line. | |||
Integrated = true; // Found it. | |||
break; | |||
} | |||
} | |||
Input.close(); | |||
if (Input.bad()) { | |||
std::string Temp; | |||
Temp = "Error closing the postfix configuration file " + PostfixMainCfPath; | |||
Temp += " after reading: "; | |||
Temp += strerror(errno); | |||
throw std::runtime_error(Temp); | |||
} | |||
OutputVerboseEnd(); | |||
return Integrated; | |||
} |
@@ -0,0 +1,44 @@ | |||
// \file PostfixIntegrate.hpp | |||
// | |||
// Copyright (C) 2011 ARM Research Labs, LLC. | |||
// See www.armresearch.com for the copyright terms. | |||
// | |||
// This file defines the PostfixIntegrate interface. | |||
// | |||
// $Id$ | |||
// | |||
/////////////////////////////////////////////////////////////////////////////////////////////////// | |||
#ifndef PostfixIntegratehpp_included | |||
#define PostfixIntegratehpp_included | |||
#include "MtaIntegrate.hpp" | |||
/// Class to manage the SNFMilter integration with postfix. | |||
// | |||
// This class implements the MtaIntegrate interface for postfix. | |||
// | |||
////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class PostfixIntegrate : public MtaIntegrate { | |||
public: | |||
virtual void SetOperatingSystem(std::string OperatingSystemType); | |||
virtual void Integrate(FileBackup *SaveFile); | |||
virtual void Unintegrate(FileBackup *SaveFile); | |||
private: | |||
virtual bool IsIntegrated(); | |||
/// Postfix main.cf file path. | |||
std::string PostfixMainCfPath; | |||
/// Postfix master.cf file path. | |||
std::string PostfixMasterCfPath; | |||
}; | |||
#endif |
@@ -208,14 +208,16 @@ SNFMilterConfig::UpdateConfigFiles() { | |||
std::string ConfigFileName = GetConfigFileName(); | |||
SaveFile.CreateBackupFile(ConfigFileName); // Save any existing file. | |||
if (!FileExists(ConfigFileName)) { | |||
Copy(DefaultSampleConfigFile, ConfigFileName); // Use SNFMilter.xml.sample. | |||
Copy(DefaultSampleConfigFile, ConfigFileName); // Use SNFMilter.xml.sample. | |||
} | |||
SetMode(ConfigFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. | |||
SetOwnerGroup(ConfigFileName); // Set to sniffer user. | |||
SetMode(ConfigFileName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // Set permissions. | |||
SetOwnerGroup(ConfigFileName); // Set to sniffer user. | |||
UpdateLogDir(); | |||
UpdateIgnoreListFile(); | |||
@@ -228,15 +230,17 @@ SNFMilterConfig::DoIntegrationCommand() { | |||
switch (Command) { | |||
case IntegrateWithNoneCmd: | |||
UnintegrateWithAll(); | |||
UnintegrateWithAllExcept(); | |||
break; | |||
case IntegrateWithPostfixCmd: | |||
IntegrateWithPostfix(); | |||
UnintegrateWithAllExcept("postfix"); | |||
Postfix.Integrate(&SaveFile); | |||
break; | |||
case IntegrateWithSendmailCmd: | |||
IntegrateWithSendmail(); | |||
UnintegrateWithAllExcept("sendmail"); | |||
// Sendmail.Integrate(&SaveFile); | |||
break; | |||
default: | |||
@@ -244,7 +248,8 @@ SNFMilterConfig::DoIntegrationCommand() { | |||
{ | |||
ostringstream Temp; | |||
Temp << "Internal error in SNFMilterConfig::DoCommand: Invalid value of command: " << Command; | |||
Temp << "Internal error in SNFMilterConfig::DoIntegrationCommand: Invalid value of command: " | |||
<< Command; | |||
throw runtime_error(Temp.str()); | |||
@@ -255,25 +260,27 @@ SNFMilterConfig::DoIntegrationCommand() { | |||
} | |||
void | |||
SNFMilterConfig::UnintegrateWithAll() { | |||
SNFMilterConfig::UnintegrateWithAllExcept(std::string Except) { | |||
if (Except != "postfix") { | |||
Postfix.Unintegrate(&SaveFile); | |||
UnintegrateWithPostfix(); | |||
UnintegrateWithSendmail(); | |||
} | |||
#if 0 | |||
if (Except != "sendmail") { | |||
// TODO: Restart MTA. | |||
Sendmail.Unintegrate(&SaveFile); | |||
// Do not remove the socket directory; users might have placed | |||
// files in it. This happened with the /tmp directory; it was | |||
// supposed to be only for files that would be deleted on reboot. | |||
// However, admins stored files that they wished to be persistent | |||
// across reboots in /tmp. | |||
} | |||
#endif | |||
} | |||
void | |||
SNFMilterConfig::IntegrateWithPostfix() { | |||
UnintegrateWithAll(); // Remove any existing integration. | |||
// UnintegrateWithAll(); // Remove any existing integration. | |||
if (Verbose()) { | |||
@@ -15,6 +15,7 @@ | |||
#include <string> | |||
#include "UtilityConfig.hpp" | |||
#include "PostfixIntegrate.hpp" | |||
/// Class to manage the SNFMilter configuration. | |||
// | |||
@@ -71,6 +72,8 @@ private: | |||
void CreateSocketDir(); | |||
PostfixIntegrate Postfix; ///< Postfix integration object. | |||
void IntegrateWithPostfix(); ///< Integrate with postfix. | |||
void UnintegrateWithPostfix(); ///< Unintegrate with postfix. | |||
@@ -79,7 +82,22 @@ private: | |||
void UnintegrateWithSendmail(); ///< Unintegrate with sendmail. | |||
void UnintegrateWithAll(); ///< Unintegrate with all MTAs. | |||
///< Unintegrate with MTAs. | |||
// | |||
// Unintegrate with all MTAs except the specified MTA. | |||
// | |||
// \param[in] Except is the MTA to not integrate with. The | |||
// acceptable values are: | |||
// | |||
// <ol> | |||
// <li> "postfix" </li> | |||
// <li> "" </li> | |||
// </ol> | |||
// | |||
// The default value is "", which specifies unintegration with all | |||
// MTAs. | |||
// | |||
void UnintegrateWithAllExcept(std::string Except = ""); | |||
CommandEnum Command; ///< Specified command. | |||