#include // UNIX socket for CONOUT (Console Output) - sends log datagrams to a listener on /tmp/miniroute-log.sock static int log_socket_fd = -1; static struct sockaddr_un log_dest; void Log_Init() { log_socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (log_socket_fd < 0) { perror("Log_Init: socket"); return; } memset(&log_dest, 0, sizeof(log_dest)); log_dest.sun_family = AF_UNIX; strncpy(log_dest.sun_path, "/tmp/miniroute-log.sock", sizeof(log_dest.sun_path) - 1); } void Log_Cleanup() { if (log_socket_fd >= 0) { close(log_socket_fd); log_socket_fd = -1; } } static void log_emit(FILE* stream, const char* level, const char* fmt, va_list ap) { // Get UNIX millis struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); unsigned long timestamp = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; char msg[1024]; vsnprintf(msg, sizeof(msg), fmt, ap); char buf[1024]; int len = snprintf(buf, sizeof(buf), "[%lu] [%s] %s\n", timestamp, level, msg); fputs(buf, stream); if (log_socket_fd >= 0) sendto(log_socket_fd, buf, len, 0, (struct sockaddr*)&log_dest, sizeof(log_dest)); } void Log_Info(const char* fmt, ...) { va_list ap; va_start(ap, fmt); log_emit(stdout, "INFO", fmt, ap); va_end(ap); } void Log_Warn(const char* fmt, ...) { va_list ap; va_start(ap, fmt); log_emit(stdout, "WARN", fmt, ap); va_end(ap); } void Log_Err(const char* fmt, ...) { va_list ap; va_start(ap, fmt); log_emit(stderr, "ERROR", fmt, ap); va_end(ap); }