summaryrefslogtreecommitdiff
path: root/src/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/log.c')
-rw-r--r--src/log.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/log.c b/src/log.c
new file mode 100644
index 0000000..1c140be
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,60 @@
+#include "log.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+
+static FILE *log_file = NULL;
+static LogLevel min_log_level = LOG_INFO;
+
+static const char *level_str(LogLevel level) {
+ switch (level) {
+ case LOG_DEBUG: return "DEBUG";
+ case LOG_INFO: return "INFO ";
+ case LOG_WARN: return "WARN ";
+ case LOG_ERROR: return "ERROR";
+ default: return "?????";
+ }
+}
+
+void log_init(const char *path, LogLevel min_level) {
+ min_log_level = min_level;
+ if (path) {
+ log_file = fopen(path, "a");
+ if (!log_file) {
+ /* Fall back to stderr if we can't open the log file */
+ fprintf(stderr, "umbrella: could not open log file %s, using stderr\n", path);
+ log_file = stderr;
+ }
+ } else {
+ log_file = stderr;
+ }
+}
+
+void log_close(void) {
+ if (log_file && log_file != stderr) {
+ fclose(log_file);
+ log_file = NULL;
+ }
+}
+
+void log_write(LogLevel level, const char *fmt, ...) {
+ if (level < min_log_level) return;
+ if (!log_file) log_file = stderr;
+
+ /* Timestamp */
+ time_t now = time(NULL);
+ struct tm *tm = localtime(&now);
+ char ts[32];
+ strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", tm);
+
+ fprintf(log_file, "[%s] [%s] ", ts, level_str(level));
+
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(log_file, fmt, args);
+ va_end(args);
+
+ fprintf(log_file, "\n");
+ fflush(log_file);
+}