15 // Yes, it's a bit ugly.
16 #define SYSLOG_FAKE_FILE (static_cast<FILE *>(NULL))
18 bool logging_started = false;
19 std::vector<FILE *> log_destinations;
21 void add_log_destination_file(const std::string &filename)
23 FILE *fp = fopen(filename.c_str(), "a");
25 perror(filename.c_str());
29 log_destinations.push_back(fp);
32 void add_log_destination_console()
34 log_destinations.push_back(stderr);
37 void add_log_destination_syslog()
39 openlog("cubemap", LOG_PID, LOG_DAEMON);
40 log_destinations.push_back(SYSLOG_FAKE_FILE);
45 logging_started = true;
48 void shut_down_logging()
50 for (size_t i = 0; i < log_destinations.size(); ++i) {
51 if (log_destinations[i] == SYSLOG_FAKE_FILE) {
53 } else if (log_destinations[i] != stderr) {
54 if (fclose(log_destinations[i]) != 0) {
59 log_destinations.clear();
60 logging_started = false;
63 void log(LogLevel log_level, const char *fmt, ...)
65 char formatted_msg[4096];
68 vsnprintf(formatted_msg, sizeof(formatted_msg), fmt, ap);
71 const char *log_level_str;
76 log_level_str = "INFO: ";
77 syslog_level = LOG_INFO;
80 log_level_str = "WARNING: ";
81 syslog_level = LOG_WARNING;
84 log_level_str = "ERROR: ";
85 syslog_level = LOG_ERR;
91 // Log to stderr if logging hasn't been set up yet. Note that this means
92 // that such messages will come even if there are no “error_log” lines.
93 if (!logging_started) {
94 fprintf(stderr, "%s%s\n", log_level_str, formatted_msg);
98 for (size_t i = 0; i < log_destinations.size(); ++i) {
99 if (log_destinations[i] == SYSLOG_FAKE_FILE) {
100 syslog(syslog_level, "%s", formatted_msg);
102 int err = fprintf(log_destinations[i], "%s%s\n", log_level_str, formatted_msg);
106 if (log_destinations[i] != stderr) {
107 fflush(log_destinations[i]);
113 void log_perror(const char *msg)
116 log(ERROR, "%s: %s", msg, strerror_r(errno, errbuf, sizeof(errbuf)));