-
Anjan Chanda authoredAnjan Chanda authored
debug.c 2.91 KiB
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* debug.c - for debug and logging.
*
* Copyright (C) 2025 Genexis AB.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <easy/easy.h>
#include "wifimngr_opts.h"
#include "debug.h"
extern const char *PROG_NAME;
static int loglevel;
static uint32_t features;
static const char *logfile;
static FILE *outfile;
static int ffd = -1;
static int ofd = -1;
static bool syslogging;
static bool logfile_isfifo;
static const int syslog_level[] = { LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG };
uint32_t logfeature_to_enum(const char *s)
{
if (!strncmp(s, "cmd", 3))
return BIT(LOG_CMD);
if (!strncmp(s, "event", 5))
return BIT(LOG_EVENT);
if (!strncmp(s, "default", 7))
return BIT(LOG_DEFAULT);
if (!strncmp(s, "all", 3))
return LOG_FEATURE_ALL;
return 0;
}
const char *logfeature_to_string(uint32_t e)
{
switch (e) {
case LOG_CMD: return "cmd";
case LOG_EVENT: return "event";
case LOG_DEFAULT: return "default";
}
return "";
}
void restart_logging(void *args)
{
struct wifimngr_cmdline_opts *opts = args;
syslogging = opts->syslogging;
logfile = opts->logfile;
logfile_isfifo = opts->logfile_isfifo;
loglevel = opts->loglevel;
features = opts->features;
if (syslogging)
openlog(PROG_NAME, 0, LOG_DAEMON);
if (!logfile) {
outfile = stderr;
ofd = fileno(stderr);
return;
}
if (logfile_isfifo) {
struct stat st;
int rfd;
if (stat(logfile, &st))
unlink(logfile);
mkfifo(logfile, 0600);
if (stat(logfile, &st) == -1 || !S_ISFIFO(st.st_mode))
return;
rfd = open(logfile, O_RDONLY | O_NONBLOCK);
if (rfd) {
ffd = open(logfile, O_WRONLY | O_NONBLOCK);
close(rfd);
}
} else {
ofd = open(logfile, O_CREAT | O_WRONLY | O_APPEND | O_NONBLOCK);
}
}
void stop_logging(void)
{
if (syslogging)
closelog();
if (outfile)
fclose(outfile);
if (ofd > 0) {
close(ofd);
ofd = -1;
}
if (ffd > 0) {
close(ffd);
unlink(logfile);
}
}
static void log_timestamp(int fd)
{
time_t now = time(NULL);
struct tm *tm_now = localtime(&now);
const char *tm_fmt = "[%d-%02d-%02d %02d:%02d:%02d] ";
dprintf(fd, tm_fmt,
tm_now->tm_year + 1900,
tm_now->tm_mon + 1,
tm_now->tm_mday,
tm_now->tm_hour,
tm_now->tm_min,
tm_now->tm_sec);
}
void log_message(int feature, int level, const char *fmt, ...)
{
va_list args;
int fd = -1;
if (!(BIT(feature) & features))
return;
if (level > loglevel)
return;
va_start(args, fmt);
if (syslogging && level >= 0)
vsyslog(syslog_level[level > 3 ? 3 : level], fmt, args);
if (logfile_isfifo && ffd > 0)
fd = ffd;
else if (ofd >= 0)
fd = ofd;
if (fd != -1) {
log_timestamp(fd);
dprintf(fd, "[%d]: ", getpid());
vdprintf(fd, fmt, args);
}
va_end(args);
}