| // SPDX-License-Identifier: GPL-2.0-or-later |
| /* |
| * Copyright (C) 2012-2013 ProFUSION embedded systems |
| */ |
| |
| #include <errno.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <syslog.h> |
| |
| #include <libkmod/libkmod.h> |
| |
| #include "kmod.h" |
| |
| #define PRIO_MAX_SIZE 32 |
| |
| static bool log_use_syslog; |
| static int log_priority = LOG_WARNING; |
| |
| static const char *prio_to_str(char buf[static PRIO_MAX_SIZE], int prio) |
| { |
| const char *prioname; |
| |
| switch (prio) { |
| case LOG_CRIT: |
| prioname = "FATAL"; |
| break; |
| case LOG_ERR: |
| prioname = "ERROR"; |
| break; |
| case LOG_WARNING: |
| prioname = "WARNING"; |
| break; |
| case LOG_NOTICE: |
| prioname = "NOTICE"; |
| break; |
| case LOG_INFO: |
| prioname = "INFO"; |
| break; |
| case LOG_DEBUG: |
| prioname = "DEBUG"; |
| break; |
| default: |
| snprintf(buf, PRIO_MAX_SIZE, "LOG-%03d", prio); |
| prioname = buf; |
| } |
| |
| return prioname; |
| } |
| |
| _printf_format_(6, 0) static void log_kmod(void *data, int priority, const char *file, |
| int line, const char *fn, const char *format, |
| va_list args) |
| { |
| char buf[PRIO_MAX_SIZE]; |
| const char *prioname; |
| char *str; |
| |
| prioname = prio_to_str(buf, priority); |
| |
| if (vasprintf(&str, format, args) < 0) |
| return; |
| |
| if (log_use_syslog) { |
| if (ENABLE_DEBUG == 1) |
| syslog(priority, "%s: %s:%d %s() %s", prioname, file, line, fn, |
| str); |
| else |
| syslog(priority, "%s: %s", prioname, str); |
| } else { |
| if (ENABLE_DEBUG == 1) |
| fprintf(stderr, "%s: %s: %s:%d %s() %s", |
| program_invocation_short_name, prioname, file, line, fn, |
| str); |
| else |
| fprintf(stderr, "%s: %s: %s", program_invocation_short_name, |
| prioname, str); |
| } |
| |
| free(str); |
| (void)data; |
| } |
| |
| void log_open(bool use_syslog) |
| { |
| log_use_syslog = use_syslog; |
| |
| if (log_use_syslog) |
| openlog(program_invocation_short_name, LOG_CONS, LOG_DAEMON); |
| } |
| |
| void log_close(void) |
| { |
| if (log_use_syslog) |
| closelog(); |
| } |
| |
| void log_printf(int prio, const char *fmt, ...) |
| { |
| char buf[PRIO_MAX_SIZE]; |
| const char *prioname; |
| char *msg; |
| va_list args; |
| |
| if (prio > log_priority) |
| return; |
| |
| va_start(args, fmt); |
| if (vasprintf(&msg, fmt, args) < 0) |
| msg = NULL; |
| va_end(args); |
| if (msg == NULL) |
| return; |
| |
| prioname = prio_to_str(buf, prio); |
| |
| if (log_use_syslog) |
| syslog(prio, "%s: %s", prioname, msg); |
| else |
| fprintf(stderr, "%s: %s: %s", program_invocation_short_name, prioname, |
| msg); |
| free(msg); |
| |
| if (prio <= LOG_CRIT) |
| exit(EXIT_FAILURE); |
| } |
| |
| void log_setup_kmod_log(struct kmod_ctx *ctx, int priority) |
| { |
| log_priority = priority; |
| |
| kmod_set_log_priority(ctx, log_priority); |
| kmod_set_log_fn(ctx, log_kmod, NULL); |
| } |