From 2b3fe0630fd027566f978ce502a2020642e4583a Mon Sep 17 00:00:00 2001 From: Suyono Date: Tue, 17 Mar 2026 11:45:14 +1100 Subject: [PATCH] added log level --- .gitignore | 1 + pam-module/include/rust_backend_ffi.h | 24 +++++++++++- pam-module/src/pam_module.cpp | 2 +- rust-backend/src/lib.rs | 19 +++++++++- rust-backend/src/logging.rs | 53 ++++++++++++++++++++++++++- 5 files changed, 93 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 4b26dfc..5b2f4f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.vscode/settings.json build/ rust-backend/target/ pam-module/*.so diff --git a/pam-module/include/rust_backend_ffi.h b/pam-module/include/rust_backend_ffi.h index f7695b9..96b99a7 100644 --- a/pam-module/include/rust_backend_ffi.h +++ b/pam-module/include/rust_backend_ffi.h @@ -6,6 +6,16 @@ #pragma once +// Log level constants shared between C/C++ and Rust +typedef enum { + RUST_LOG_LEVEL_FATAL = 0, + RUST_LOG_LEVEL_ERROR = 1, + RUST_LOG_LEVEL_WARN = 2, + RUST_LOG_LEVEL_INFO = 3, + RUST_LOG_LEVEL_DEBUG = 4, + RUST_LOG_LEVEL_TRACE = 5, +} RustLogLevel; + #ifdef __cplusplus extern "C" { #endif @@ -16,9 +26,21 @@ void rust_init_logging(const char* log_path); // Authenticate user (stub) int rust_auth_user(const char* user, const char* password); -// Log event (file sink) +// Legacy: Log event (file sink) — forwards to INFO level on Rust side void rust_log_event(const char* event); +// New: Log event with explicit level +void rust_log_event_with_level(const char* event, RustLogLevel level); + #ifdef __cplusplus } #endif + +// Convenience macros for C/C++ callers +#define RUST_LOG_FATAL(msg) rust_log_event_with_level((msg), RUST_LOG_LEVEL_FATAL) +#define RUST_LOG_ERROR(msg) rust_log_event_with_level((msg), RUST_LOG_LEVEL_ERROR) +#define RUST_LOG_WARN(msg) rust_log_event_with_level((msg), RUST_LOG_LEVEL_WARN) +#define RUST_LOG_INFO(msg) rust_log_event_with_level((msg), RUST_LOG_LEVEL_INFO) +#define RUST_LOG_DEBUG(msg) rust_log_event_with_level((msg), RUST_LOG_LEVEL_DEBUG) +#define RUST_LOG_TRACE(msg) rust_log_event_with_level((msg), RUST_LOG_LEVEL_TRACE) + diff --git a/pam-module/src/pam_module.cpp b/pam-module/src/pam_module.cpp index ba25a4b..98db6a3 100644 --- a/pam-module/src/pam_module.cpp +++ b/pam-module/src/pam_module.cpp @@ -15,7 +15,7 @@ extern "C" { int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv) { try { rust_init_logging(nullptr); // Ensure logger is initialized - rust_log_event("PAM authentication attempt"); + RUST_LOG_INFO("PAM authentication attempt"); const char* user = nullptr; diff --git a/rust-backend/src/lib.rs b/rust-backend/src/lib.rs index 854dbe0..ddb5ace 100644 --- a/rust-backend/src/lib.rs +++ b/rust-backend/src/lib.rs @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -use std::ffi::{CStr, CString}; +use std::ffi::CStr; use std::os::raw::c_char; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -35,7 +35,22 @@ pub extern "C" fn rust_log_event(event: *const c_char) { } CStr::from_ptr(event).to_str().unwrap_or("") }; - logging::log_event(msg); + // Legacy wrapper: default to INFO + logging::log_event_with_level(logging::LogLevel::Info, msg); + })); +} + +#[no_mangle] +pub extern "C" fn rust_log_event_with_level(event: *const c_char, level: i32) { + let _ = catch_unwind(AssertUnwindSafe(|| { + let msg = unsafe { + if event.is_null() { + return; + } + CStr::from_ptr(event).to_str().unwrap_or("") + }; + let lvl = logging::LogLevel::from(level); + logging::log_event_with_level(lvl, msg); })); } diff --git a/rust-backend/src/logging.rs b/rust-backend/src/logging.rs index e3188b7..f2e8430 100644 --- a/rust-backend/src/logging.rs +++ b/rust-backend/src/logging.rs @@ -9,6 +9,50 @@ use std::io::Write; use std::sync::Mutex; use once_cell::sync::OnceCell; +#[repr(i32)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum LogLevel { + Fatal = 0, + Error = 1, + Warn = 2, + Info = 3, + Debug = 4, + Trace = 5, +} + +impl LogLevel { + pub fn as_str(self) -> &'static str { + match self { + LogLevel::Fatal => "FATAL", + LogLevel::Error => "ERROR", + LogLevel::Warn => "WARN", + LogLevel::Info => "INFO", + LogLevel::Debug => "DEBUG", + LogLevel::Trace => "TRACE", + } + } +} + +impl From for LogLevel { + fn from(v: i32) -> Self { + match v { + 0 => LogLevel::Fatal, + 1 => LogLevel::Error, + 2 => LogLevel::Warn, + 3 => LogLevel::Info, + 4 => LogLevel::Debug, + 5 => LogLevel::Trace, + _ => LogLevel::Info, + } + } +} + +impl Default for LogLevel { + fn default() -> Self { + LogLevel::Info + } +} + static LOGGER: OnceCell> = OnceCell::new(); pub fn init_logger(path: &str) { @@ -24,9 +68,14 @@ pub fn init_logger(path: &str) { LOGGER.set(Mutex::new(file)).ok(); } -pub fn log_event(event: &str) { +pub fn log_event_with_level(level: LogLevel, event: &str) { if let Some(logger) = LOGGER.get() { let mut file = logger.lock().unwrap(); - writeln!(file, "{}", event).ok(); + writeln!(file, "[{}] {}", level.as_str(), event).ok(); } } + +// Backwards-compatible wrapper: default to INFO +pub fn log_event(event: &str) { + log_event_with_level(LogLevel::Info, event); +}