BIND 10 trac899, updated. f1213a3d4df71a4009a3f9a09a9aab002b42ce35 [trac899] Miscellaneous fixes
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri May 20 12:29:06 UTC 2011
The branch, trac899 has been updated
via f1213a3d4df71a4009a3f9a09a9aab002b42ce35 (commit)
via 50dd99f81efde9267569def411a470e082ac312b (commit)
from 2273e3e71f5879cdf51f956c19a153f4280d9531 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit f1213a3d4df71a4009a3f9a09a9aab002b42ce35
Author: Stephen Morris <stephen at isc.org>
Date: Fri May 20 13:28:16 2011 +0100
[trac899] Miscellaneous fixes
commit 50dd99f81efde9267569def411a470e082ac312b
Author: Stephen Morris <stephen at isc.org>
Date: Fri May 20 10:19:12 2011 +0100
[trac899] Remove "in function" argument from logger constructor
That was a hangover from the log4cxx implementation and appears not to
be needed in log4cplus.
-----------------------------------------------------------------------
Summary of changes:
src/lib/log/Makefile.am | 2 +-
src/lib/log/logger.cc | 14 +++-
src/lib/log/logger.h | 35 ++-------
src/lib/log/logger_impl.cc | 108 ++++++++++++++++++++--------
src/lib/log/logger_impl.h | 52 ++++++++++----
src/lib/log/logger_support.cc | 2 +-
src/lib/log/tests/logger_support_test.cc | 2 +-
src/lib/log/tests/logger_unittest.cc | 49 +++++++------
src/lib/log/tests/run_time_init_test.sh.in | 42 ++++++------
9 files changed, 184 insertions(+), 122 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am
index 7555241..69a4770 100644
--- a/src/lib/log/Makefile.am
+++ b/src/lib/log/Makefile.am
@@ -7,7 +7,7 @@ CLEANFILES = *.gcno *.gcda
lib_LTLIBRARIES = liblog.la
liblog_la_SOURCES = b.cc
-liblog_la_SOURCES += logger_levels.h
+liblog_la_SOURCES += logger_level.h
liblog_la_SOURCES += dummylog.h dummylog.cc
liblog_la_SOURCES += log_formatter.h log_formatter.cc
liblog_la_SOURCES += logger.cc logger.h
diff --git a/src/lib/log/logger.cc b/src/lib/log/logger.cc
index 553e3c3..fdca964 100644
--- a/src/lib/log/logger.cc
+++ b/src/lib/log/logger.cc
@@ -31,7 +31,7 @@ namespace log {
// Initialize Logger implementation. Does not check whether the implementation
// has already been initialized - that was done by the caller (getLoggerPtr()).
void Logger::initLoggerImpl() {
- loggerptr_ = new LoggerImpl(name_, infunc_);
+ loggerptr_ = new LoggerImpl(name_);
}
// Destructor.
@@ -166,9 +166,19 @@ Logger::fatal(const isc::log::MessageID& ident) {
}
}
-bool Logger::operator==(Logger& other) {
+// Comparison (testing only)
+
+bool
+Logger::operator==(Logger& other) {
return (*getLoggerPtr() == *other.getLoggerPtr());
}
+// Reset (used in testing only). This is a static method.
+
+void
+Logger::reset() {
+ LoggerImpl::reset();
+}
+
} // namespace log
} // namespace isc
diff --git a/src/lib/log/logger.h b/src/lib/log/logger.h
index a46781f..94c6c94 100644
--- a/src/lib/log/logger.h
+++ b/src/lib/log/logger.h
@@ -55,32 +55,7 @@ public:
/// \param name Name of the logger. If the name is that of the root name,
/// this creates an instance of the root logger; otherwise it creates a
/// child of the root logger.
- ///
- /// \param infunc This argument is present to get round a bug in some
- /// implementations of the logging system. If the logger is declared in
- /// a function (such that it will be deleted when the function exits,
- /// before the program ends), set this true. If declared outside a
- /// function (such that it gets deleted during program rundown), set false
- /// (the default).\n
- /// \n
- /// The problems encountered was that during program rundown, one logging
- /// implementation (log4cxx) threw a MutexException (this is described in
- /// https://issues.apache.org/jira/browse/LOGCXX-322). As this only occurs
- /// during program rundown, the issue is not serious - it just looks bad to
- /// have the program crash instead of shut down cleanly.\n
- /// \n
- /// If log4cxx is chosen as the implementation, this flag controls the
- /// deletion of the underlying log4cxx data structures when the logger is
- /// deleted. Setting it false for externally-declared loggers inhibits
- /// their deletion; so at program exit the memory is not reclaimed during
- /// program rundown, only when the process is selected. Setting it true
- /// for loggers that will be deleted in the normal running of the program
- /// enables their deletion - which causes no issues as the problem only
- /// manifests itself during program rundown.
- /// \n
- /// The flag has no effect on non-log4cxx implementations.
- Logger(const std::string& name, bool infunc = false) :
- loggerptr_(NULL), name_(name), infunc_(infunc)
+ Logger(const std::string& name) : loggerptr_(NULL), name_(name)
{}
/// \brief Destructor
@@ -173,11 +148,16 @@ public:
/// \brief Equality
///
/// Check if two instances of this logger refer to the same stream.
- /// (This method is principally for testing.)
///
/// \return true if the logger objects are instances of the same logger.
bool operator==(Logger& other);
+protected:
+ /// \brief Clear logging hierachy
+ ///
+ /// This is for test use only, hence is protected.
+ static void reset();
+
private:
friend class isc::log::Formatter<Logger>;
@@ -226,7 +206,6 @@ private:
LoggerImpl* loggerptr_; ///< Pointer to the underlying logger
std::string name_; ///< Copy of the logger name
- bool infunc_; ///< Copy of the infunc argument
};
} // namespace log
diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc
index ea6f56f..3cbfb6b 100644
--- a/src/lib/log/logger_impl.cc
+++ b/src/lib/log/logger_impl.cc
@@ -33,36 +33,30 @@
#include <util/strutil.h>
+// Note: as log4cplus and th3e BIND 10 logger have many concepts in common, and
+// thus many similar names, to disambiguate types we don't "use" the log4cplus
+// namespace: instead, all log4cplus types are explicitly qualified.
+
using namespace std;
-using namespace log4cplus;
namespace isc {
namespace log {
-// Static initializations
-
-
// Constructor
-LoggerImpl::LoggerImpl(const std::string& name, bool)
+LoggerImpl::LoggerImpl(const string& name)
{
// Initialize log4cplus if not already done
initLog4cplus();
// Are we the root logger?
if (name == getRootLoggerName()) {
- is_root_ = true;
name_ = name;
logger_ = log4cplus::Logger::getRoot();
} else {
- is_root_ = false;
name_ = getRootLoggerName() + "." + name;
- logger_ = log4cplus::Logger::getInstance(name_);
+ logger_ = log4cplus::Logger::getInstance(name);
}
-
- // Create a formatted name for use in messages (speeds up formatting if
- // we do it now.)
- fmt_name_ = std::string("[") + name_ + std::string("] ");
}
// Destructor. (Here because of virtual declaration.)
@@ -73,23 +67,21 @@ LoggerImpl::~LoggerImpl() {
// Set the severity for logging.
void
LoggerImpl::setSeverity(isc::log::Severity severity, int dbglevel) {
- isc::log::Level level(severity, dbglevel);
+ Level level(severity, dbglevel);
logger_.setLogLevel(LoggerLevelImpl::convertFromBindLevel(level));
}
// Return severity level
isc::log::Severity
LoggerImpl::getSeverity() {
- isc::log::Level level =
- LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel());
+ Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel());
return level.severity;
}
// Return current debug level (only valid if current severity level is DEBUG).
int
LoggerImpl::getDebugLevel() {
- isc::log::Level level =
- LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel());
+ Level level = LoggerLevelImpl::convertToBindLevel(logger_.getLogLevel());
return level.dbglevel;
}
@@ -97,8 +89,7 @@ LoggerImpl::getDebugLevel() {
// severity of the root level.
isc::log::Severity
LoggerImpl::getEffectiveSeverity() {
- isc::log::Level level =
- LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel());
+ Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel());
return level.severity;
}
@@ -106,8 +97,7 @@ LoggerImpl::getEffectiveSeverity() {
// is DEBUG).
int
LoggerImpl::getEffectiveDebugLevel() {
- isc::log::Level level =
- LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel());
+ Level level = LoggerLevelImpl::convertToBindLevel(logger_.getChainedLogLevel());
return level.dbglevel;
}
@@ -123,45 +113,101 @@ void
LoggerImpl::outputRaw(const Severity& severity, const string& message) {
switch (severity) {
case DEBUG:
- LOG4CPLUS_DEBUG(logger_, fmt_name_ << message);
+ LOG4CPLUS_DEBUG(logger_, message);
break;
case INFO:
- LOG4CPLUS_INFO(logger_, fmt_name_ << message);
+ LOG4CPLUS_INFO(logger_, message);
break;
case WARN:
- LOG4CPLUS_WARN(logger_, fmt_name_ << message);
+ LOG4CPLUS_WARN(logger_, message);
break;
case ERROR:
- LOG4CPLUS_ERROR(logger_, fmt_name_ << message);
+ LOG4CPLUS_ERROR(logger_, message);
break;
case FATAL:
- LOG4CPLUS_FATAL(logger_, fmt_name_ << message);
+ LOG4CPLUS_FATAL(logger_, message);
}
}
-// One-time initialization of log4cplus
+// Initialization. This is one initialization for all loggers, so requires
+// a singleton to hold the initialization flag. The flag is held within a
+// static method to ensure that it is created (and initialized) when needed.
+// This avoids a static initialization fiasco.
+bool&
+LoggerImpl::initialized() {
+ static bool initialized = false;
+ return (initialized);
+}
void
LoggerImpl::initLog4cplus() {
- static bool not_initialized = true;
- if (not_initialized) {
- // Set up basic configurator
+ if (! initialized()) {
+
+ // Set up basic configurator. This attaches a ConsoleAppender to the
+ // root logger with suitable output. This is used until we we have
+ // actually read the logging configuration, in which case the output
+ // may well be changed.
log4cplus::BasicConfigurator config;
config.configure();
+ setRootAppenderLayout();
// Add additional debug levels
LoggerLevelImpl::init();
// All done.
- not_initialized = false;
+ initialized() = true;
+ }
+}
+
+void LoggerImpl::setRootAppenderLayout() {
+
+ // Create the pattern we want for the output - local time.
+ string pattern = "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [";
+ pattern += getRootLoggerName() + string(".%c] %m\n");
+
+ // Retrieve the appenders on the root instance and set the layout to
+ // use that pattern.
+ log4cplus::SharedAppenderPtrList list =
+ log4cplus::Logger::getRoot().getAllAppenders();
+
+ for (log4cplus::SharedAppenderPtrList::iterator i = list.begin();
+ i != list.end(); ++i) {
+ auto_ptr<log4cplus::Layout> layout(
+ new log4cplus::PatternLayout(pattern));
+ (*i)->setLayout(layout);
}
}
+// Reset. Just reset logger hierarchy to default settings (don't remove the
+// loggers - this appears awkward); this is effectively the same as removing
+// them.
+void
+LoggerImpl::reset() {
+ log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
+ initialized() = false;
+
+ // N.B. The documentation is not clear, but it does not appear that the
+ // methods used to format the new logging levels are removed from the
+ // log4cxx LogLevelManager class - indeed, there appears to be no way
+ // to do this. This would seem to suggest that a re-initialization may
+ // well add another instance of the toString/fromString to the manager's
+ // list of methods.
+ //
+ // We could get round this by making setting the LogManager a truly
+ // one-shot process. However, apart from taking up memory there is little
+ // overhead if multiple instances are added. The manager walks the list and
+ // uses the first method that processes the argument, so multiple methods
+ // doing the same think will not affect functionality. Besides, this
+ // reset() method is only used in testing and not in the distributed
+ // software.
+}
+
+
} // namespace log
} // namespace isc
diff --git a/src/lib/log/logger_impl.h b/src/lib/log/logger_impl.h
index 53879f0..f655c55 100644
--- a/src/lib/log/logger_impl.h
+++ b/src/lib/log/logger_impl.h
@@ -44,12 +44,25 @@ namespace log {
/// This particular implementation is based on log4cplus (from sourceforge:
/// http://log4cplus.sourceforge.net). Particular items of note:
///
-/// a) BIND 10 loggers have names of the form "root.sublogger". Log4cplus
-/// loggers are always subloggers of a "root" logger. In this implementation,
-/// the name of the logger is checked. If it is the root name (as evidenced
-/// by the setting of the BIND 10 root logger name), the log4cplus root logger
-/// is used. Otherwise the name is used as the name of a logger and a log4cplus
-/// sub-logger created.
+/// a) BIND 10 loggers have names of the form "program.sublogger". In other
+/// words, each of the loggers is a sub-logger of the main program logger.
+/// In log4cplus, there is a root logger (called "root" according to the
+/// documentation, but actually unnamed) and all loggers created are subloggers
+/// if it.
+///
+/// In this implementation, the name of the logger is checked. If it is the
+/// name of the program (as set in the call to isc::log::setRootLoggerName),
+/// the log4cplus root logger is used. Otherwise the name passed is used as
+/// the name of a logger when a log4cplus logger is created.
+///
+/// To clarify: if the program is "b10auth" (and that is used to set the BIND 10
+/// root logger name via a call to isc::log::setRootLoggerName()), the BIND 10
+/// logger "b10auth" corresponds to the log4cplus root logger instance (returned
+/// by a call to log4cplus::Logger::getRoot()). The BIND 10 sub-logger "cache"
+/// corresponds to the log4cplus logger "cache", created by a call to
+/// log4cplus::Logger::getInstance("cache"). The distinction is, however,
+/// invisible to users as the logger reported in messages is always
+/// "programm.sublogger".
///
/// b) The idea of debug levels is implemented. Seee logger_level.h and
/// logger_level_impl.h for more details on this.
@@ -62,10 +75,7 @@ public:
/// Creates a logger of the specific name.
///
/// \param name Name of the logger.
- ///
- /// \param exit_delete This argument is present to get round a bug in
- /// the log4cxx implementation. It is unused here.
- LoggerImpl(const std::string& name, bool);
+ LoggerImpl(const std::string& name);
/// \brief Destructor
@@ -174,18 +184,32 @@ public:
return (name_ == other.name_);
}
+ /// \brief Reset logging
+ ///
+ /// Resets (clears) the log4cplus logging, requiring that an initialization
+ /// call be performed again.
+ static void reset();
+
private:
/// \brief Initialize log4cplus
///
- /// Static method to perform one-time initialization of the log4cplus
- /// system.
+ /// Static method to perform initialization of the log4cplus system.
static void initLog4cplus();
- bool is_root_; ///< Is this BIND 10 root logger?
+ /// \brief Initialization Flag
+ ///
+ /// Static method to access an initialization flag. Doing it this
+ /// way means that there is no static initialization fiasco.
+ static bool& initialized();
+
+ /// \brief Set layout pattern
+ ///
+ /// Sets the layout for root logger appender(s)
+ static void setRootAppenderLayout();
+
std::string name_; ///< Full name of this logger
- std::string fmt_name_; ///< Formatted name for output
log4cplus::Logger logger_; ///< Underlying log4cplus logger
};
diff --git a/src/lib/log/logger_support.cc b/src/lib/log/logger_support.cc
index e17c47d..deb6d88 100644
--- a/src/lib/log/logger_support.cc
+++ b/src/lib/log/logger_support.cc
@@ -107,7 +107,7 @@ initLogger(const string& root, isc::log::Severity severity, int dbglevel,
// debug level. This is the logger that has the name of the application.
// All other loggers created in this application will be its children.
setRootLoggerName(root);
- Logger root_logger(isc::log::getRootLoggerName(), true);
+ Logger root_logger(isc::log::getRootLoggerName());
// Set the severity associated with it. If no other logger has a severity,
// this will be the default.
diff --git a/src/lib/log/tests/logger_support_test.cc b/src/lib/log/tests/logger_support_test.cc
index 0a2338b..ab3b00e 100644
--- a/src/lib/log/tests/logger_support_test.cc
+++ b/src/lib/log/tests/logger_support_test.cc
@@ -52,7 +52,7 @@ int main(int argc, char** argv) {
int dbglevel = -1; // Logger debug level
const char* localfile = NULL; // Local message file
int option; // For getopt() processing
- Logger logger_dlm("dlm", true); // Another example logger
+ Logger logger_dlm("dlm"); // Another example logger
// Parse options
while ((option = getopt(argc, argv, "s:d:")) != -1) {
diff --git a/src/lib/log/tests/logger_unittest.cc b/src/lib/log/tests/logger_unittest.cc
index fddac14..f9b7643 100644
--- a/src/lib/log/tests/logger_unittest.cc
+++ b/src/lib/log/tests/logger_unittest.cc
@@ -25,33 +25,36 @@ using namespace isc;
using namespace isc::log;
using namespace std;
-namespace isc {
-namespace log {
-
-/// \brief Test Logger
+/// \brief Derived logger
///
-/// This logger is a subclass of the logger class under test, but makes
-/// protected methods public (for testing)
+/// Only exists to make the protected static methods in Logger public for
+/// test purposes.
-class TestLogger : public Logger {
+class DerivedLogger : public isc::log::Logger {
public:
- /// \brief constructor
- TestLogger(const string& name) : Logger(name, true)
- {
+ DerivedLogger(std::string name) : isc::log::Logger(name)
+ {}
+ virtual ~DerivedLogger()
+ {}
+
+ static void reset() {
+ isc::log::Logger::reset();
}
};
-} // namespace log
-} // namespace isc
+/// \brief Logger Test
+///
+/// As the logger is only a shell around the implementation, this tests also
+/// checks the logger implementation class as well.
class LoggerTest : public ::testing::Test {
-protected:
+public:
LoggerTest()
+ {}
+ ~LoggerTest()
{
- }
-
- ~LoggerTest() {
+ DerivedLogger::reset();
}
};
@@ -81,14 +84,14 @@ TEST_F(LoggerTest, GetLogger) {
const string name2 = "beta";
// Instantiate two loggers that should be the same
- TestLogger logger1(name1);
- TestLogger logger2(name1);
+ Logger logger1(name1);
+ Logger logger2(name1);
// And check they equal
EXPECT_TRUE(logger1 == logger2);
// Instantiate another logger with another name and check that it
// is different to the previously instantiated ones.
- TestLogger logger3(name2);
+ Logger logger3(name2);
EXPECT_FALSE(logger1 == logger3);
}
@@ -98,7 +101,7 @@ TEST_F(LoggerTest, Severity) {
// Create a logger
setRootLoggerName("test3");
- TestLogger logger("alpha");
+ Logger logger("alpha");
// Now check the levels
logger.setSeverity(isc::log::NONE);
@@ -129,7 +132,7 @@ TEST_F(LoggerTest, DebugLevels) {
// Create a logger
setRootLoggerName("test4");
- TestLogger logger("alpha");
+ Logger logger("alpha");
// Debug level should be 0 if not at debug severity
logger.setSeverity(isc::log::NONE, 20);
@@ -175,8 +178,8 @@ TEST_F(LoggerTest, SeverityInheritance) {
// relationship if the loggers are named <parent> and <parent>.<child>.
setRootLoggerName("test5");
- TestLogger parent("alpha");
- TestLogger child("alpha.beta");
+ Logger parent("alpha");
+ Logger child("alpha.beta");
// By default, newly created loggers should have a level of DEFAULT
// (i.e. default to parent)
diff --git a/src/lib/log/tests/run_time_init_test.sh.in b/src/lib/log/tests/run_time_init_test.sh.in
index eff1b6a..e48a781 100755
--- a/src/lib/log/tests/run_time_init_test.sh.in
+++ b/src/lib/log/tests/run_time_init_test.sh.in
@@ -37,43 +37,43 @@ cat > $localmes << .
echo -n "1. runInitTest default parameters: "
cat > $tempfile << .
-FATAL - [alpha.example] MSG_WRITERR, error writing to test1: 42
-ERROR - [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
-WARN - [alpha.dlm] MSG_READERR, error reading from message file a.txt: dummy reason
-INFO - [alpha.dlm] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
+WARN [alpha.dlm] MSG_READERR, error reading from message file a.txt: dummy reason
+INFO [alpha.dlm] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
.
-./logger_support_test | diff $tempfile -
+./logger_support_test | cut -d' ' -f3- | diff $tempfile -
passfail $?
echo -n "2. Severity filter: "
cat > $tempfile << .
-FATAL - [alpha.example] MSG_WRITERR, error writing to test1: 42
-ERROR - [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
.
-./logger_support_test -s error | diff $tempfile -
+./logger_support_test -s error | cut -d' ' -f3- | diff $tempfile -
passfail $?
echo -n "3. Debug level: "
cat > $tempfile << .
-FATAL - [alpha.example] MSG_WRITERR, error writing to test1: 42
-ERROR - [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
-WARN - [alpha.dlm] MSG_READERR, error reading from message file a.txt: dummy reason
-INFO - [alpha.dlm] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
-DEBUG - [alpha.example] MSG_RDLOCMES, reading local message file dummy/0
-DEBUG - [alpha.example] MSG_RDLOCMES, reading local message file dummy/24
-DEBUG - [alpha.example] MSG_RDLOCMES, reading local message file dummy/25
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, reading local message file dummy/file
+WARN [alpha.dlm] MSG_READERR, error reading from message file a.txt: dummy reason
+INFO [alpha.dlm] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
+DEBUG [alpha.example] MSG_RDLOCMES, reading local message file dummy/0
+DEBUG [alpha.example] MSG_RDLOCMES, reading local message file dummy/24
+DEBUG [alpha.example] MSG_RDLOCMES, reading local message file dummy/25
.
-./logger_support_test -s debug -d 25 | diff $tempfile -
+./logger_support_test -s debug -d 25 | cut -d' ' -f3- | diff $tempfile -
passfail $?
echo -n "4. Local message replacement: "
cat > $tempfile << .
-WARN - [alpha.log] MSG_IDNOTFND, could not replace message text for 'MSG_NOTHERE': no such message
-FATAL - [alpha.example] MSG_WRITERR, error writing to test1: 42
-ERROR - [alpha.example] MSG_RDLOCMES, replacement read local message file, parameter is 'dummy/file'
-WARN - [alpha.dlm] MSG_READERR, replacement read error, parameters: 'a.txt' and 'dummy reason'
+WARN [alpha.log] MSG_IDNOTFND, could not replace message text for 'MSG_NOTHERE': no such message
+FATAL [alpha.example] MSG_WRITERR, error writing to test1: 42
+ERROR [alpha.example] MSG_RDLOCMES, replacement read local message file, parameter is 'dummy/file'
+WARN [alpha.dlm] MSG_READERR, replacement read error, parameters: 'a.txt' and 'dummy reason'
.
-./logger_support_test -s warn $localmes | diff $tempfile -
+./logger_support_test -s warn $localmes | cut -d' ' -f3- | diff $tempfile -
passfail $?
rm -f $localmes
More information about the bind10-changes
mailing list