X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=log.cpp;fp=log.cpp;h=ba05a64d1fe5236c4dfe370a947254587c56cf37;hp=0000000000000000000000000000000000000000;hb=d1ad2cf60ca694f742e2061a596bc27c7e58f5c8;hpb=03569c70282f68a4bc9b259fbf5b7a2b4c5594b3 diff --git a/log.cpp b/log.cpp new file mode 100644 index 0000000..ba05a64 --- /dev/null +++ b/log.cpp @@ -0,0 +1,112 @@ +#include "log.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; + +// Yes, it's a bit ugly. +#define SYSLOG_FAKE_FILE (static_cast(NULL)) + +bool logging_started = false; +std::vector log_destinations; + +void add_log_destination_file(const std::string &filename) +{ + FILE *fp = fopen(filename.c_str(), "a"); + if (fp == NULL) { + perror(filename.c_str()); + return; + } + + log_destinations.push_back(fp); +} + +void add_log_destination_console() +{ + log_destinations.push_back(stderr); +} + +void add_log_destination_syslog() +{ + openlog("cubemap", LOG_PID, LOG_DAEMON); + log_destinations.push_back(SYSLOG_FAKE_FILE); +} + +void start_logging() +{ + logging_started = true; +} + +void shut_down_logging() +{ + for (size_t i = 0; i < log_destinations.size(); ++i) { + if (log_destinations[i] == SYSLOG_FAKE_FILE) { + closelog(); + } else if (log_destinations[i] != stderr) { + if (fclose(log_destinations[i]) != 0) { + perror("fclose"); + } + } + } + log_destinations.clear(); + logging_started = false; +} + +void log(LogLevel log_level, const char *fmt, ...) +{ + char formatted_msg[4096]; + va_list ap; + va_start(ap, fmt); + vsnprintf(formatted_msg, sizeof(formatted_msg), fmt, ap); + va_end(ap); + + const char *log_level_str; + int syslog_level; + + switch (log_level) { + case NO_LEVEL: + log_level_str = ""; + syslog_level = LOG_INFO; + break; + case INFO: + log_level_str = "INFO: "; + syslog_level = LOG_INFO; + break; + case WARNING: + log_level_str = "WARNING: "; + syslog_level = LOG_WARNING; + break; + case ERROR: + log_level_str = "ERROR: "; + syslog_level = LOG_ERR; + break; + default: + assert(false); + } + + // Log to stderr if logging hasn't been set up yet. Note that this means + // that such messages will come even if there are no “error_log” lines. + if (!logging_started) { + fprintf(stderr, "%s%s\n", log_level_str, formatted_msg); + return; + } + + for (size_t i = 0; i < log_destinations.size(); ++i) { + if (log_destinations[i] == SYSLOG_FAKE_FILE) { + syslog(syslog_level, "%s", formatted_msg); + } else { + int err = fprintf(log_destinations[i], "%s%s\n", log_level_str, formatted_msg); + if (err < 0) { + perror("fprintf"); + } + if (log_destinations[i] != stderr) { + fflush(log_destinations[i]); + } + } + } +}