| /* |
| * |
| * Copyright (c) 2006 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| #include "qpid/log/posix/SinkOptions.h" |
| #include "qpid/log/SinkOptions.h" |
| #include "qpid/log/Logger.h" |
| #include "qpid/log/OstreamOutput.h" |
| #include "qpid/memory.h" |
| #include "qpid/Exception.h" |
| #include <iostream> |
| #include <map> |
| #include <string> |
| #include <syslog.h> |
| |
| using std::string; |
| using qpid::Exception; |
| |
| namespace qpid { |
| namespace log { |
| namespace posix { |
| |
| namespace { |
| |
| // SyslogFacilities maps from syslog values to the text equivalents. |
| class SyslogFacilities { |
| public: |
| typedef std::map<string, int> ByName; |
| typedef std::map<int, string> ByValue; |
| |
| SyslogFacilities() { |
| struct NameValue { const char* name; int value; }; |
| NameValue nameValue[] = { |
| { "AUTH", LOG_AUTH }, |
| #ifdef HAVE_LOG_AUTHPRIV |
| { "AUTHPRIV", LOG_AUTHPRIV }, |
| #endif |
| { "CRON", LOG_CRON }, |
| { "DAEMON", LOG_DAEMON }, |
| #ifdef HAVE_LOG_FTP |
| { "FTP", LOG_FTP }, |
| #endif |
| { "KERN", LOG_KERN }, |
| { "LOCAL0", LOG_LOCAL0 }, |
| { "LOCAL1", LOG_LOCAL1 }, |
| { "LOCAL2", LOG_LOCAL2 }, |
| { "LOCAL3", LOG_LOCAL3 }, |
| { "LOCAL4", LOG_LOCAL4 }, |
| { "LOCAL5", LOG_LOCAL5 }, |
| { "LOCAL6", LOG_LOCAL6 }, |
| { "LOCAL7", LOG_LOCAL7 }, |
| { "LPR", LOG_LPR }, |
| { "MAIL", LOG_MAIL }, |
| { "NEWS", LOG_NEWS }, |
| { "SYSLOG", LOG_SYSLOG }, |
| { "USER", LOG_USER }, |
| { "UUCP", LOG_UUCP } |
| }; |
| for (size_t i = 0; i < sizeof(nameValue)/sizeof(nameValue[0]); ++i) { |
| byName.insert(ByName::value_type(nameValue[i].name, nameValue[i].value)); |
| // Recognise with and without LOG_ prefix e.g.: AUTH and LOG_AUTH |
| byName.insert(ByName::value_type(string("LOG_")+nameValue[i].name, nameValue[i].value)); |
| byValue.insert(ByValue::value_type(nameValue[i].value, string("LOG_")+nameValue[i].name)); |
| } |
| } |
| |
| int value(const string& name) const { |
| string key(name); |
| std::transform(key.begin(), key.end(), key.begin(), ::toupper); |
| ByName::const_iterator i = byName.find(key); |
| if (i == byName.end()) |
| throw Exception("Not a valid syslog facility: " + name); |
| return i->second; |
| } |
| |
| string name(int value) const { |
| ByValue::const_iterator i = byValue.find(value); |
| if (i == byValue.end()) |
| throw Exception("Not a valid syslog value: " + value); |
| return i->second; |
| } |
| |
| private: |
| ByName byName; |
| ByValue byValue; |
| }; |
| |
| // 'priorities' maps qpid log levels to syslog priorities. They are in |
| // order of qpid log levels and must map to: |
| // "trace", "debug", "info", "notice", "warning", "error", "critical" |
| static int priorities[qpid::log::LevelTraits::COUNT] = { |
| LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_NOTICE, |
| LOG_WARNING, LOG_ERR, LOG_CRIT |
| }; |
| |
| std::string basename(const std::string path) { |
| size_t i = path.find_last_of('/'); |
| return path.substr((i == std::string::npos) ? 0 : i+1); |
| } |
| |
| } // namespace |
| |
| std::ostream& operator<<(std::ostream& o, const SyslogFacility& f) { |
| return o << SyslogFacilities().name(f.value); |
| } |
| |
| std::istream& operator>>(std::istream& i, SyslogFacility& f) { |
| std::string name; |
| i >> name; |
| f.value = SyslogFacilities().value(name); |
| return i; |
| } |
| |
| class SyslogOutput : public qpid::log::Logger::Output { |
| public: |
| SyslogOutput(const std::string& logName, const SyslogFacility& logFacility) |
| : name(logName), facility(logFacility.value) |
| { |
| ::openlog(name.c_str(), LOG_PID, facility); |
| } |
| |
| virtual ~SyslogOutput() { |
| ::closelog(); |
| } |
| |
| virtual void log(const Statement& s, const std::string& m) |
| { |
| syslog(priorities[s.level], "%s", m.c_str()); |
| } |
| |
| private: |
| std::string name; |
| int facility; |
| }; |
| |
| SinkOptions::SinkOptions(const std::string& argv0) |
| : qpid::log::SinkOptions(), |
| logToStderr(true), |
| logToStdout(false), |
| logToSyslog(false), |
| syslogName(basename(argv0)), |
| syslogFacility(LOG_DAEMON) { |
| |
| addOptions() |
| ("log-to-stderr", optValue(logToStderr, "yes|no"), "Send logging output to stderr") |
| ("log-to-stdout", optValue(logToStdout, "yes|no"), "Send logging output to stdout") |
| ("log-to-file", optValue(logFile, "FILE"), "Send log output to FILE.") |
| ("log-to-syslog", optValue(logToSyslog, "yes|no"), "Send logging output to syslog;\n\tcustomize using --syslog-name and --syslog-facility") |
| ("syslog-name", optValue(syslogName, "NAME"), "Name to use in syslog messages") |
| ("syslog-facility", optValue(syslogFacility,"LOG_XXX"), "Facility to use in syslog messages") |
| ; |
| |
| } |
| |
| qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs) { |
| const SinkOptions *prhs = dynamic_cast<const SinkOptions*>(&rhs); |
| if (this != prhs) { |
| logToStderr = prhs->logToStderr; |
| logToStdout = prhs->logToStdout; |
| logToSyslog = prhs->logToSyslog; |
| logFile = prhs->logFile; |
| syslogName = prhs->syslogName; |
| syslogFacility.value = prhs->syslogFacility.value; |
| } |
| return *this; |
| } |
| |
| void SinkOptions::detached(void) { |
| if (logToStderr && !logToStdout && !logToSyslog && logFile.empty()) { |
| logToStderr = false; |
| logToSyslog = true; |
| } |
| } |
| |
| // The Logger acting on these options calls setup() to request any |
| // Sinks be set up and fed back to the logger. |
| void SinkOptions::setup(qpid::log::Logger *logger) { |
| if (logToStderr) |
| logger->output(make_auto_ptr<qpid::log::Logger::Output> |
| (new qpid::log::OstreamOutput(std::clog))); |
| if (logToStdout) |
| logger->output(make_auto_ptr<qpid::log::Logger::Output> |
| (new qpid::log::OstreamOutput(std::cout))); |
| |
| if (logFile.length() > 0) |
| logger->output(make_auto_ptr<qpid::log::Logger::Output> |
| (new qpid::log::OstreamOutput(logFile))); |
| |
| if (logToSyslog) |
| logger->output(make_auto_ptr<qpid::log::Logger::Output> |
| (new SyslogOutput(syslogName, syslogFacility))); |
| |
| } |
| |
| } // namespace qpid::log::posix |
| |
| SinkOptions* SinkOptions::create(const std::string& argv0) { |
| return new qpid::log::posix::SinkOptions (argv0); |
| } |
| |
| }} // namespace qpid::log |