From 4fc80ea7b08c2e7097c291f35a0c2b16c419aba2 Mon Sep 17 00:00:00 2001 From: Bendeguz Pisch Date: Fri, 18 Jul 2025 04:49:51 +0000 Subject: [PATCH] Implement syslog functionality --- include/bits/syslog.h | 6 + src/header/mod.rs | 1 + src/header/stdio/mod.rs | 2 +- src/header/syslog/cbindgen.toml | 10 ++ src/header/syslog/mod.rs | 9 ++ src/header/syslog/redox.rs | 211 ++++++++++++++++++++++++++++++++ tests/Makefile | 4 + tests/syslog/syslog.c | 9 ++ 8 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 include/bits/syslog.h create mode 100644 src/header/syslog/cbindgen.toml create mode 100644 src/header/syslog/mod.rs create mode 100644 src/header/syslog/redox.rs create mode 100644 tests/syslog/syslog.c diff --git a/include/bits/syslog.h b/include/bits/syslog.h new file mode 100644 index 0000000000..06fe014db3 --- /dev/null +++ b/include/bits/syslog.h @@ -0,0 +1,6 @@ +#ifndef _BITS_SYSLOG_H +#define _BITS_SYSLOG_H + +#define LOG_MASK(pri) (1<<(pri)) + +#endif diff --git a/src/header/mod.rs b/src/header/mod.rs index acddf401de..0037bb6faa 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -104,6 +104,7 @@ pub mod sys_un; pub mod sys_utsname; pub mod sys_wait; // TODO: syslog.h +pub mod syslog; pub mod tar; // TODO: term.h (deprecated) pub mod termios; diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 6ee35b27b0..b7c7c7b633 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -42,7 +42,7 @@ mod getdelim; mod ext; mod helpers; mod lookaheadreader; -mod printf; +pub mod printf; mod scanf; use lookaheadreader::LookAheadReader; static mut TMPNAM_BUF: [c_char; L_tmpnam as usize + 1] = [0; L_tmpnam as usize + 1]; diff --git a/src/header/syslog/cbindgen.toml b/src/header/syslog/cbindgen.toml new file mode 100644 index 0000000000..d11110d7a4 --- /dev/null +++ b/src/header/syslog/cbindgen.toml @@ -0,0 +1,10 @@ +sys_includes = ["bits/syslog.h"] +include_guard = "_RELIBC_SYSLOG_H" +language = "C" +style = "Type" +no_includes = true +cpp_compat = true + +[enum] +prefix_with_name = true + diff --git a/src/header/syslog/mod.rs b/src/header/syslog/mod.rs new file mode 100644 index 0000000000..22f5d631ad --- /dev/null +++ b/src/header/syslog/mod.rs @@ -0,0 +1,9 @@ +// This is syslog.h implemented based on POSIX.1-2017 +// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html + +#[cfg(target_os = "redox")] +pub use self::sys::*; + +#[cfg(target_os = "redox")] +#[path = "redox.rs"] +pub mod sys; diff --git a/src/header/syslog/redox.rs b/src/header/syslog/redox.rs new file mode 100644 index 0000000000..dcf10f4dda --- /dev/null +++ b/src/header/syslog/redox.rs @@ -0,0 +1,211 @@ +use crate::{ + c_str::CStr, + error::Errno, + fs::File, + header::{ + fcntl, + stdio::printf::printf, + string::{strlen, strncpy}, + time::time, + unistd::getpid, + }, + io::Write, + platform::types::*, + sync::{ + rwlock::{ReadGuard, RwLock, WriteGuard}, + Once, + }, +}; +use alloc::string::String; +use chrono::{DateTime, Utc}; +use core::{ffi::VaList, ptr::null_mut}; + +// Values for logopt +pub const LOG_PID: c_int = 0x01; +pub const LOG_CONS: c_int = 0x02; +pub const LOG_ODELAY: c_int = 0x04; +pub const LOG_NDELAY: c_int = 0x08; +pub const LOG_NOWAIT: c_int = 0x10; + +// Facilities +// Note: in this case I relied more on MUSL than on POSIX1.2017 +// as it appears there were some Linux-specific facilities +// Which could be used by programs we want to port over +// And GNU Libc had these too +pub const LOG_KERN: c_int = 0 << 3; +pub const LOG_USER: c_int = 1 << 3; +pub const LOG_MAIL: c_int = 2 << 3; +pub const LOG_DAEMON: c_int = 3 << 3; +pub const LOG_AUTH: c_int = 4 << 3; +pub const LOG_SYSLOG: c_int = 5 << 3; +pub const LOG_LPR: c_int = 6 << 3; +pub const LOG_NEWS: c_int = 7 << 3; +pub const LOG_UUCP: c_int = 8 << 3; +pub const LOG_CRON: c_int = 9 << 3; +pub const LOG_AUTHPRIV: c_int = 10 << 3; +pub const LOG_FTP: c_int = 11 << 3; +pub const LOG_LOCAL0: c_int = 16 << 3; +pub const LOG_LOCAL1: c_int = 17 << 3; +pub const LOG_LOCAL2: c_int = 18 << 3; +pub const LOG_LOCAL3: c_int = 19 << 3; +pub const LOG_LOCAL4: c_int = 20 << 3; +pub const LOG_LOCAL5: c_int = 21 << 3; +pub const LOG_LOCAL6: c_int = 22 << 3; +pub const LOG_LOCAL7: c_int = 23 << 3; +pub const LOG_NFACILITIES: c_int = 24; + +// Priorities +pub const LOG_EMERG: c_int = 0; +pub const LOG_ALERT: c_int = 1; +pub const LOG_CRIT: c_int = 2; +pub const LOG_ERR: c_int = 3; +pub const LOG_WARNING: c_int = 4; +pub const LOG_NOTICE: c_int = 5; +pub const LOG_INFO: c_int = 6; +pub const LOG_DEBUG: c_int = 7; + +pub const LOG_FACMASK: c_int = 0x3f8; + +struct LogParams { + log_ident: String, + log_opt: i32, + log_facility: i32, + log_mask: i32, +} + +impl LogParams { + fn new() -> Self { + LogParams { + log_ident: String::new(), + log_opt: 0, + log_facility: LOG_USER, + log_mask: 0xff, + } + } +} + +static LOGFILELOCK: RwLock> = RwLock::new(None); +static PARAMSLOCK: Once> = Once::new(); + +fn paramslock() -> &'static RwLock { + PARAMSLOCK.call_once(|| RwLock::new(LogParams::new())) +} + +fn logfile<'a>() -> ReadGuard<'a, Option> { + LOGFILELOCK.read() +} + +fn logfile_mut<'a>() -> WriteGuard<'a, Option> { + LOGFILELOCK.write() +} + +fn logparams<'a>() -> ReadGuard<'a, LogParams> { + paramslock().read() +} + +fn logparams_mut<'a>() -> WriteGuard<'a, LogParams> { + paramslock().write() +} + +#[no_mangle] +pub extern "C" fn setlogmask(maskpri: c_int) -> c_int { + let mut params = logparams_mut(); + let ret = params.log_mask; + if (maskpri != 0) { + params.log_mask = maskpri; + } + ret +} + +#[no_mangle] +pub extern "C" fn openlog(ident: *const c_char, opt: c_int, facility: c_int) { + let new_ident: &str; + unsafe { + let conv_ident = CStr::from_ptr(ident); + new_ident = conv_ident.to_str().unwrap(); + } + let mut params = logparams_mut(); + if !new_ident.is_empty() { + params.log_ident = new_ident.into(); + } + params.log_opt = opt; + params.log_facility = facility; + if ((opt & LOG_NDELAY) != 0) { + let mut guard = logfile_mut(); + match *guard { + None => { + *guard = Some( + File::open(c"/scheme/log".into(), fcntl::O_WRONLY) + .expect("Could not open log file"), + ); + } + _ => (), + } + } +} + +fn _vsyslog(mut priority: i32, message: *const c_char, mut ap: VaList) { + { + let mut guard = logfile_mut(); + match *guard { + None => { + *guard = Some( + File::open(c"/scheme/log".into(), fcntl::O_WRONLY) + .expect("Could not open log file"), + ); + } + _ => (), + } + } + //Note: trait Local not available due to a dependency loop, so we have to query the time differently + let mut epoch: i64 = 0; + unsafe { + epoch = time(null_mut()); + } + let currtime: DateTime = + DateTime::from_timestamp(epoch, 0).expect("Couldn't retrieve broken-down time."); + let currtime_s = currtime.format("%b %e %T %Y"); + let mut params = logparams_mut(); + let pid = if (params.log_opt & LOG_PID) != 0 { + getpid() + } else { + 0 + }; + if ((priority & LOG_FACMASK) == 0) { + priority |= params.log_facility + }; + let mut final_logmsg = format!("<{}>{} {}{}: ", priority, currtime_s, params.log_ident, pid); + let mut guard = logfile_mut(); + if let Some(filehandle) = guard.as_mut() { + filehandle.write(final_logmsg.as_bytes()); + unsafe { + let _ = printf(&mut *filehandle, message, ap); + } + filehandle.write("\n".as_bytes()); + } +} + +#[no_mangle] +pub extern "C" fn vsyslog(priority: c_int, message: *const c_char, mut ap: VaList) { + { + let params = logparams(); + if (((params.log_mask & (1 << (priority & 7))) == 0) || ((priority & !0x3ff) != 0)) { + return (); + }; + } + _vsyslog(priority, message, ap); +} + +#[no_mangle] +pub unsafe extern "C" fn syslog(priority: c_int, message: *const c_char, mut __valist: ...) { + vsyslog(priority, message, __valist.as_va_list()); +} + +#[no_mangle] +pub extern "C" fn closelog() { + let mut guard = logfile_mut(); + match guard.as_mut() { + Some(log_file) => *guard = None, + _ => (), + } +} diff --git a/tests/Makefile b/tests/Makefile index 9bdcb473cc..b1c7d3dc1e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -162,6 +162,10 @@ EXPECT_NAMES=\ # TODO: Fix these # netdb/netdb \ +ifeq ($(REDOX_TESTS),1) + EXPECT_NAMES+=syslog/syslog +endif + BUILD?=. DYNAMIC_ONLY_NAMES=\ diff --git a/tests/syslog/syslog.c b/tests/syslog/syslog.c new file mode 100644 index 0000000000..c49211e9d8 --- /dev/null +++ b/tests/syslog/syslog.c @@ -0,0 +1,9 @@ +#include + +int main() { + int extraarg = 5; + openlog("testprog", LOG_PID, LOG_USER); + syslog(LOG_EMERG, "This is a test message with extra: %d", extraarg); + closelog(); + return 0; +}