#include #include #include #include "log.h" /* TODO: replace this with something thread-safe later. */ static unsigned log_level = LOG_INFO; void vl_log_setlevel(unsigned level) { log_level = level; } #define MAX_LOGLEN ((size_t)4096) #define MAX_LOGTIMELEN ((size_t)64) /* december 999th of 10000 A.D. at 100 o'clock */ static const char *const log_names[] = { "TRACE", "DEBUG", "INFO", "WARN", "ERROR", NULL }; static FILE *log_stream(unsigned level) { switch (level) { case LOG_TRACE: case LOG_DEBUG: case LOG_INFO: return stdout; default: return stderr; } } void vl_logv(unsigned level, const char *fmt, va_list args) { char buf[MAX_LOGLEN]; char datebuf[MAX_LOGTIMELEN]; time_t now; struct tm now_tm; int en = errno; if (log_level > level) return; if (level > LOG_ERROR) return; vsnprintf(buf, MAX_LOGLEN, fmt, args); strcpy(buf + MAX_LOGLEN - 4, "..."); now = time(NULL); localtime_r(&now, &now_tm); if (!strftime(datebuf, MAX_LOGTIMELEN, "%H:%M:%S", &now_tm)) { strcpy(datebuf, "???"); } fprintf(log_stream(level), "[%s] %5s: %s\n", datebuf, log_names[level], buf); errno = en; } void vl_log(unsigned level, const char *fmt, ...) { va_list args; va_start(args, fmt); vl_logv(level, fmt, args); va_end(args); }