/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 #include #include #include #include #include #include #if !defined(LOG4CXX) #define LOG4CXX 1 #endif #include #if LOG4CXX_HAVE_SYSLOG #include #else /* facility codes */ #define LOG_KERN (0<<3) /* kernel messages */ #define LOG_USER (1<<3) /* random user-level messages */ #define LOG_MAIL (2<<3) /* mail system */ #define LOG_DAEMON (3<<3) /* system daemons */ #define LOG_AUTH (4<<3) /* security/authorization messages */ #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ #define LOG_LPR (6<<3) /* line printer subsystem */ #define LOG_NEWS (7<<3) /* network news subsystem */ #define LOG_UUCP (8<<3) /* UUCP subsystem */ #define LOG_CRON (9<<3) /* clock daemon */ #define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ #define LOG_FTP (11<<3) /* ftp daemon */ /* other codes through 15 reserved for system use */ #define LOG_LOCAL0 (16<<3) /* reserved for local use */ #define LOG_LOCAL1 (17<<3) /* reserved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved for local use */ #define LOG_LOCAL6 (22<<3) /* reserved for local use */ #define LOG_LOCAL7 (23<<3) /* reserved for local use */ #endif #define LOG_UNDEF -1 using namespace log4cxx; using namespace log4cxx::helpers; using namespace log4cxx::net; IMPLEMENT_LOG4CXX_OBJECT(SyslogAppender) SyslogAppender::SyslogAppender() : syslogFacility(LOG_USER), facilityPrinting(false), sw(0) { this->initSyslogFacilityStr(); } SyslogAppender::SyslogAppender(const LayoutPtr& layout1, int syslogFacility1) : syslogFacility(syslogFacility1), facilityPrinting(false), sw(0) { this->layout = layout1; this->initSyslogFacilityStr(); } SyslogAppender::SyslogAppender(const LayoutPtr& layout1, const LogString& syslogHost1, int syslogFacility1) : syslogFacility(syslogFacility1), facilityPrinting(false), sw(0) { this->layout = layout1; this->initSyslogFacilityStr(); setSyslogHost(syslogHost1); } SyslogAppender::~SyslogAppender() { finalize(); } /** Release any resources held by this SyslogAppender.*/ void SyslogAppender::close() { closed = true; if (sw != 0) { delete sw; sw = 0; } } void SyslogAppender::initSyslogFacilityStr() { facilityStr = getFacilityString(this->syslogFacility); if (facilityStr.empty()) { Pool p; LogString msg(LOG4CXX_STR("\"")); StringHelper::toString(syslogFacility, p, msg); msg.append(LOG4CXX_STR("\" is an unknown syslog facility. Defaulting to \"USER\".")); LogLog::error(msg); this->syslogFacility = LOG_USER; facilityStr = LOG4CXX_STR("user:"); } else { facilityStr += LOG4CXX_STR(":"); } } /** Returns the specified syslog facility as a lower-case String, e.g. "kern", "user", etc. */ LogString SyslogAppender::getFacilityString( int syslogFacility) { switch(syslogFacility) { case LOG_KERN: return LOG4CXX_STR("kern"); case LOG_USER: return LOG4CXX_STR("user"); case LOG_MAIL: return LOG4CXX_STR("mail"); case LOG_DAEMON: return LOG4CXX_STR("daemon"); case LOG_AUTH: return LOG4CXX_STR("auth"); case LOG_SYSLOG: return LOG4CXX_STR("syslog"); case LOG_LPR: return LOG4CXX_STR("lpr"); case LOG_NEWS: return LOG4CXX_STR("news"); case LOG_UUCP: return LOG4CXX_STR("uucp"); case LOG_CRON: return LOG4CXX_STR("cron"); #ifdef LOG_AUTHPRIV case LOG_AUTHPRIV: return LOG4CXX_STR("authpriv"); #endif #ifdef LOG_FTP case LOG_FTP: return LOG4CXX_STR("ftp"); #endif case LOG_LOCAL0: return LOG4CXX_STR("local0"); case LOG_LOCAL1: return LOG4CXX_STR("local1"); case LOG_LOCAL2: return LOG4CXX_STR("local2"); case LOG_LOCAL3: return LOG4CXX_STR("local3"); case LOG_LOCAL4: return LOG4CXX_STR("local4"); case LOG_LOCAL5: return LOG4CXX_STR("local5"); case LOG_LOCAL6: return LOG4CXX_STR("local6"); case LOG_LOCAL7: return LOG4CXX_STR("local7"); default: return LogString(); } } int SyslogAppender::getFacility( const LogString& s) { if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("KERN"), LOG4CXX_STR("kern"))) { return LOG_KERN; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("USER"), LOG4CXX_STR("user"))) { return LOG_USER; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("MAIL"), LOG4CXX_STR("mail"))) { return LOG_MAIL; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("DAEMON"), LOG4CXX_STR("daemon"))) { return LOG_DAEMON; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("AUTH"), LOG4CXX_STR("auth"))) { return LOG_AUTH; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("SYSLOG"), LOG4CXX_STR("syslog"))) { return LOG_SYSLOG; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LPR"), LOG4CXX_STR("lpr"))) { return LOG_LPR; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("NEWS"), LOG4CXX_STR("news"))) { return LOG_NEWS; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("UUCP"), LOG4CXX_STR("uucp"))) { return LOG_UUCP; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("CRON"), LOG4CXX_STR("cron"))) { return LOG_CRON; } #ifdef LOG_AUTHPRIV else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("AUTHPRIV"), LOG4CXX_STR("authpriv"))) { return LOG_AUTHPRIV; } #endif #ifdef LOG_FTP else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("FTP"), LOG4CXX_STR("ftp"))) { return LOG_FTP; } #endif else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL0"), LOG4CXX_STR("local0"))) { return LOG_LOCAL0; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL1"), LOG4CXX_STR("local1"))) { return LOG_LOCAL1; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL2"), LOG4CXX_STR("local2"))) { return LOG_LOCAL2; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL3"), LOG4CXX_STR("local3"))) { return LOG_LOCAL3; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL4"), LOG4CXX_STR("local4"))) { return LOG_LOCAL4; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL5"), LOG4CXX_STR("local5"))) { return LOG_LOCAL5; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL6"), LOG4CXX_STR("local6"))) { return LOG_LOCAL6; } else if (StringHelper::equalsIgnoreCase(s, LOG4CXX_STR("LOCAL7"), LOG4CXX_STR("local7"))) { return LOG_LOCAL7; } else { return LOG_UNDEF; } } void SyslogAppender::append(const spi::LoggingEventPtr& event, Pool& p) { if (!isAsSevereAsThreshold(event->getLevel())) return; LogString msg; layout->format(msg, event, p); // On the local host, we can directly use the system function 'syslog' // if it is available #if LOG4CXX_HAVE_SYSLOG if (sw == 0) { std::string sbuf; Transcoder::encode(msg, sbuf); // use of "%s" to avoid a security hole ::syslog(syslogFacility | event->getLevel()->getSyslogEquivalent(), "%s", sbuf.c_str()); return; } #endif // We must not attempt to append if sw is null. if(sw == 0) { errorHandler->error(LOG4CXX_STR("No syslog host is set for SyslogAppedender named \"")+ this->name+LOG4CXX_STR("\".")); return; } LogString sbuf(1, 0x3C /* '<' */); StringHelper::toString((syslogFacility | event->getLevel()->getSyslogEquivalent()), p, sbuf); sbuf.append(1, (logchar) 0x3E /* '>' */); if (facilityPrinting) { sbuf.append(facilityStr); } sbuf.append(msg); sw->write(sbuf); } void SyslogAppender::activateOptions(Pool&) { } void SyslogAppender::setOption(const LogString& option, const LogString& value) { if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SYSLOGHOST"), LOG4CXX_STR("sysloghost"))) { setSyslogHost(value); } else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FACILITY"), LOG4CXX_STR("facility"))) { setFacility(value); } else { AppenderSkeleton::setOption(option, value); } } void SyslogAppender::setSyslogHost(const LogString& syslogHost1) { if (this->sw != 0) { delete this->sw; this->sw = 0; } LogString slHost = syslogHost1; int slHostPort = -1; LogString::size_type colonPos = 0; colonPos = slHost.rfind(':'); if (colonPos != LogString::npos) { slHostPort = StringHelper::toInt(slHost.substr(colonPos+1)); // Erase the :port part of the host name slHost.erase( colonPos ); } // On the local host, we can directly use the system function 'syslog' // if it is available (cf. append) #if LOG4CXX_HAVE_SYSLOG if (syslogHost1 != LOG4CXX_STR("localhost") && syslogHost1 != LOG4CXX_STR("127.0.0.1") && !syslogHost1.empty()) #endif if (slHostPort >= 0) this->sw = new SyslogWriter(slHost, slHostPort); else this->sw = new SyslogWriter(slHost); this->syslogHost = slHost; this->syslogHostPort = slHostPort; } void SyslogAppender::setFacility(const LogString& facilityName) { if (facilityName.empty()) { return; } syslogFacility = getFacility(facilityName); if (syslogFacility == LOG_UNDEF) { LogLog::error(LOG4CXX_STR("[")+facilityName + LOG4CXX_STR("] is an unknown syslog facility. Defaulting to [USER].")); syslogFacility = LOG_USER; } this->initSyslogFacilityStr(); }