// -*- mode: c++; c-basic-offset: 2; -*- #include "common.hh" #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #ifndef _DEFAULT_SOURCE #define _DEFAULT_SOURCE #endif #include #include #include #include #include #include "logger.hh" namespace { class LoggerStdErr : public Logger { public: void out(Level lvl, char const* format, ...) override { if (lvl == DBG) { #ifdef NDEBUG return; #endif } char* tmp; va_list args; va_start(args, format); auto ret = vasprintf(&tmp, format, args); va_end(args); if (ret == -1) return; std::cerr << tmp << std::endl; free(tmp); } }; class LoggerSyslog : public Logger { public: LoggerSyslog(std::string const& name) : name_(name) { openlog(name_.c_str(), LOG_PID, LOG_DAEMON); } ~LoggerSyslog() override { closelog(); } void out(Level lvl, char const* format, ...) override { if (lvl == DBG) { #ifdef NDEBUG return; #endif } va_list args; va_start(args, format); vsyslog(lvl2prio(lvl), format, args); va_end(args); } private: static int lvl2prio(Level lvl) { switch (lvl) { case ERR: return LOG_ERR; case WARN: return LOG_WARNING; case INFO: return LOG_INFO; case DBG: return LOG_DEBUG; } assert(false); return LOG_INFO; } // Copy of name to keep pointer alive while syslog has access to it std::string const name_; }; class LoggerFile : public Logger { public: LoggerFile() : fh_(nullptr) { } bool open(std::string const& path) { if (fh_) fclose(fh_); fh_ = fopen(path.c_str(), "a"); return fh_ != NULL; } ~LoggerFile() override { if (fh_) fclose(fh_); } void out(Level lvl, char const* format, ...) override { if (lvl == DBG) { #ifdef NDEBUG return; #endif } fputs(lvl2str(lvl), fh_); fwrite(": ", 1, 2, fh_); va_list args; va_start(args, format); vfprintf(fh_, format, args); va_end(args); fputc('\n', fh_); } private: static char const* lvl2str(Level lvl) { switch (lvl) { case ERR: return "Error"; case WARN: return "Warning"; case INFO: return "Info"; case DBG: return "Debug"; } assert(false); return "Info"; } FILE* fh_; }; class NullLogger : public Logger { public: void out(Level, char const*, ...) override { } }; } // namespace // static Logger* Logger::create_stderr() { return new LoggerStdErr(); } // static Logger* Logger::create_syslog(std::string const& name) { return new LoggerSyslog(name); } // static Logger* Logger::create_file(std::string const& path) { std::unique_ptr ret(new LoggerFile()); if (ret->open(path)) { return ret.release(); } return nullptr; } // static Logger* Logger::null() { static NullLogger logger; return &logger; }