//
// Syd: rock-solid application kernel
// src/kernel/syslog.rs: syslog(2) handler
//
// Copyright (c) 2023, 2024, 2025 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0

#[cfg(feature = "log")]
use libseccomp::ScmpNotifResp;
#[cfg(feature = "log")]
use nix::errno::Errno;

#[cfg(feature = "log")]
use crate::req::UNotifyEventRequest;

#[cfg(feature = "log")]
pub(crate) fn sys_syslog(request: UNotifyEventRequest) -> ScmpNotifResp {
    syscall_handler!(request, |request: UNotifyEventRequest| {
        // SAFETY: syslog(2) is only allowed if the sandbox lock is off,
        // unless trace/allow_safe_syslog:1 is set at startup.
        let req = request.scmpreq;
        let sandbox = request.get_sandbox();
        if !sandbox.flags.allow_safe_syslog() && sandbox.locked_for(req.pid()) {
            return Err(Errno::EPERM);
        }
        drop(sandbox); // release the read-lock.

        // SAFETY: Return EPERM if the global Syslog has not be initialized.
        let syslog = if let Some(syslog) = crate::syslog::global_syslog() {
            syslog
        } else {
            return Err(Errno::EPERM);
        };

        let action: libc::c_int = req.data.args[0].try_into().or(Err(Errno::EINVAL))?;
        let len: usize = req.data.args[2].try_into().unwrap_or(0);
        let (count, buf) = syslog.syslog(action, len)?;
        #[expect(clippy::cast_possible_wrap)]
        if let Some(buf) = buf {
            let n = request.write_mem(&buf, req.data.args[1])?;
            Ok(request.return_syscall(n as i64))
        } else {
            Ok(request.return_syscall(count as i64))
        }
    })
}
