forked from nix-rust/nix
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Stub for wrap syslog.h Signed-off-by: tison <wander4096@gmail.com> * Wrap openlog Signed-off-by: tison <wander4096@gmail.com> * Make it work Signed-off-by: tison <wander4096@gmail.com> * lib_enums and docs Signed-off-by: tison <wander4096@gmail.com> * wrap priority Signed-off-by: tison <wander4096@gmail.com> * reduce error handle noise and add docs Signed-off-by: tison <wander4096@gmail.com> * try add setlogmask Signed-off-by: tison <wander4096@gmail.com> * Revert "try add setlogmask" This reverts commit 98289d5. * fixup tests Signed-off-by: tison <wander4096@gmail.com> * fixup all Signed-off-by: tison <wander4096@gmail.com> * add changelog Signed-off-by: tison <wander4096@gmail.com> * turn on syslog for tests Signed-off-by: tison <wander4096@gmail.com> * revert irrelevant format Signed-off-by: tison <wander4096@gmail.com> * add new feature flags Signed-off-by: tison <wander4096@gmail.com> * Add back closelog Signed-off-by: tison <wander4096@gmail.com> * Use AsRef<OsStr> for openlog.ident Signed-off-by: tison <wander4096@gmail.com> * polish APIs Signed-off-by: tison <wander4096@gmail.com> * fixup Signed-off-by: tison <wander4096@gmail.com> * test on linux Signed-off-by: tison <wander4096@gmail.com> * test on unix Signed-off-by: tison <wander4096@gmail.com> * fixup flags Signed-off-by: tison <wander4096@gmail.com> * fixup all Signed-off-by: tison <wander4096@gmail.com> * Update src/syslog.rs Co-authored-by: SteveLauC <stevelauc@outlook.com> * refactor: use AsRef<OsStr> on non-Linux and &'static CStr on Linux for ident arg of openlog * style: fmt * fix: Linux build by importing CStr --------- Signed-off-by: tison <wander4096@gmail.com> Co-authored-by: SteveLauC <stevelauc@outlook.com>
- Loading branch information
Showing
6 changed files
with
266 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add support for `syslog`, `openlog`, `closelog` on all `unix`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
//! Interfaces for controlling system log. | ||
use crate::{NixPath, Result}; | ||
use std::ffi::OsStr; | ||
use std::ptr; | ||
|
||
/// Logging options of subsequent [`syslog`] calls can be set by calling [`openlog`]. | ||
/// | ||
/// The parameter `ident` is a string that will be prepended to every message. The `logopt` | ||
/// argument specifies logging options. The `facility` parameter encodes a default facility to be | ||
/// assigned to all messages that do not have an explicit facility encoded. | ||
// | ||
// On Linux, the `ident` argument needs to have static lifetime according to the | ||
// man page: | ||
// | ||
// The argument ident in the call of openlog() is probably stored as-is. Thus, | ||
// if the string it points to is changed, syslog() may start prepending the changed | ||
// string, and if the string it points to ceases to exist, the results are | ||
// undefined. Most portable is to use a string constant. | ||
#[cfg(target_os = "linux")] | ||
pub fn openlog( | ||
ident: Option<&'static std::ffi::CStr>, | ||
logopt: LogFlags, | ||
facility: Facility, | ||
) -> Result<()> { | ||
let logopt = logopt.bits(); | ||
let facility = facility as libc::c_int; | ||
match ident { | ||
None => unsafe { | ||
libc::openlog(ptr::null(), logopt, facility); | ||
}, | ||
Some(ident) => ident.with_nix_path(|ident| unsafe { | ||
libc::openlog(ident.as_ptr(), logopt, facility); | ||
})?, | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Logging options of subsequent [`syslog`] calls can be set by calling [`openlog`]. | ||
/// | ||
/// The parameter `ident` is a string that will be prepended to every message. The `logopt` | ||
/// argument specifies logging options. The `facility` parameter encodes a default facility to be | ||
/// assigned to all messages that do not have an explicit facility encoded. | ||
#[cfg(not(target_os = "linux"))] | ||
pub fn openlog<S: AsRef<OsStr> + ?Sized>( | ||
ident: Option<&S>, | ||
logopt: LogFlags, | ||
facility: Facility, | ||
) -> Result<()> { | ||
let logopt = logopt.bits(); | ||
let facility = facility as libc::c_int; | ||
match ident.map(OsStr::new) { | ||
None => unsafe { | ||
libc::openlog(ptr::null(), logopt, facility); | ||
}, | ||
Some(ident) => ident.with_nix_path(|ident| unsafe { | ||
libc::openlog(ident.as_ptr(), logopt, facility); | ||
})?, | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Writes message to the system message logger. | ||
/// | ||
/// The message is then written to the system console, log files, logged-in users, or forwarded | ||
/// to other machines as appropriate. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ```rust | ||
/// use nix::syslog::{openlog, syslog, Facility, LogFlags, Severity, Priority}; | ||
/// | ||
/// let priority = Priority::new(Severity::LOG_EMERG, Facility::LOG_USER); | ||
/// syslog(priority, "Hello, nix!").unwrap(); | ||
/// | ||
/// // use `format!` to format the message | ||
/// let name = "syslog"; | ||
/// syslog(priority, &format!("Hello, {name}!")).unwrap(); | ||
/// ``` | ||
pub fn syslog<P, S>(priority: P, message: &S) -> Result<()> | ||
where | ||
P: Into<Priority>, | ||
S: AsRef<OsStr> + ?Sized, | ||
{ | ||
let priority = priority.into(); | ||
let formatter = OsStr::new("%s"); | ||
let message = OsStr::new(message); | ||
formatter.with_nix_path(|formatter| { | ||
message.with_nix_path(|message| unsafe { | ||
libc::syslog(priority.0, formatter.as_ptr(), message.as_ptr()) | ||
}) | ||
})??; | ||
Ok(()) | ||
} | ||
|
||
/// Closes the log file. | ||
pub fn closelog() { | ||
unsafe { libc::closelog() } | ||
} | ||
|
||
/// The priority for a log message. | ||
#[derive(Debug, Clone, Copy)] | ||
pub struct Priority(libc::c_int); | ||
|
||
impl Priority { | ||
/// Create a new priority from a facility and severity level. | ||
pub fn new(severity: Severity, facility: Facility) -> Self { | ||
let priority = (facility as libc::c_int) | (severity as libc::c_int); | ||
Priority(priority) | ||
} | ||
} | ||
|
||
impl From<Severity> for Priority { | ||
fn from(severity: Severity) -> Self { | ||
let priority = severity as libc::c_int; | ||
Priority(priority) | ||
} | ||
} | ||
|
||
libc_bitflags! { | ||
/// Options for system logging. | ||
pub struct LogFlags: libc::c_int { | ||
/// Log the process id with each message: useful for identifying instantiations of | ||
/// daemons. | ||
LOG_PID; | ||
/// If syslog() cannot pass the message to syslogd(8) it will attempt to write the | ||
/// message to the console ("/dev/console"). | ||
LOG_CONS; | ||
/// The converse of [`LOG_NDELAY`][LogFlags::LOG_NDELAY]; opening of the connection is | ||
/// delayed until `syslog` is called. | ||
/// | ||
/// This is the default, and need not be specified. | ||
LOG_ODELAY; | ||
/// Open the connection to syslogd(8) immediately. Normally the open is delayed until | ||
/// the first message is logged. Useful for programs that need to manage the order in | ||
/// which file descriptors are allocated. | ||
LOG_NDELAY; | ||
/// Write the message to standard error output as well to the system log. | ||
#[cfg(not(any(target_os = "redox", target_os = "illumos")))] | ||
LOG_PERROR; | ||
} | ||
} | ||
|
||
libc_enum! { | ||
/// Severity levels for log messages. | ||
#[repr(i32)] | ||
#[non_exhaustive] | ||
pub enum Severity { | ||
/// A panic condition. | ||
/// | ||
/// This is normally broadcast to all users. | ||
LOG_EMERG, | ||
/// A condition that should be corrected immediately, such as a corrupted system database. | ||
LOG_ALERT, | ||
/// Critical conditions, e.g., hard device errors. | ||
LOG_CRIT, | ||
/// Errors. | ||
LOG_ERR, | ||
/// Warning messages. | ||
LOG_WARNING, | ||
/// Conditions that are not error conditions, but should possibly be handled specially. | ||
LOG_NOTICE, | ||
/// Informational messages. | ||
LOG_INFO, | ||
/// Messages that contain information normally of use only when debugging a program. | ||
LOG_DEBUG, | ||
} | ||
} | ||
|
||
libc_enum! { | ||
/// Facilities for log messages. | ||
#[repr(i32)] | ||
#[non_exhaustive] | ||
pub enum Facility { | ||
/// Messages generated by the kernel. | ||
/// | ||
/// These cannot be generated by any user processes. | ||
LOG_KERN, | ||
/// Messages generated by random user processes. | ||
/// | ||
/// This is the default facility identifier if none is specified. | ||
LOG_USER, | ||
/// The mail system. | ||
LOG_MAIL, | ||
/// System daemons, such as routed(8), that are not provided for explicitly by other facilities. | ||
LOG_DAEMON, | ||
/// The authorization system: login(1), su(1), getty(8), etc. | ||
LOG_AUTH, | ||
/// Messages generated internally by syslogd(8). | ||
LOG_SYSLOG, | ||
/// The line printer spooling system: cups-lpd(8), cupsd(8), etc. | ||
LOG_LPR, | ||
/// The network news system. | ||
LOG_NEWS, | ||
/// The uucp system. | ||
LOG_UUCP, | ||
/// Reserved for local use. | ||
LOG_LOCAL0, | ||
/// Reserved for local use. | ||
LOG_LOCAL1, | ||
/// Reserved for local use. | ||
LOG_LOCAL2, | ||
/// Reserved for local use. | ||
LOG_LOCAL3, | ||
/// Reserved for local use. | ||
LOG_LOCAL4, | ||
/// Reserved for local use. | ||
LOG_LOCAL5, | ||
/// Reserved for local use. | ||
LOG_LOCAL6, | ||
/// Reserved for local use. | ||
LOG_LOCAL7, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,8 @@ mod test_sendfile; | |
))] | ||
mod test_spawn; | ||
|
||
mod test_syslog; | ||
|
||
mod test_time; | ||
mod test_unistd; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use nix::syslog::{openlog, syslog, Facility, LogFlags, Severity}; | ||
|
||
#[test] | ||
fn test_syslog_hello_world() { | ||
let flags = LogFlags::LOG_PID; | ||
|
||
#[cfg(not(target_os = "linux"))] | ||
openlog(None::<&str>, flags, Facility::LOG_USER).unwrap(); | ||
#[cfg(target_os = "linux")] | ||
openlog(None, flags, Facility::LOG_USER).unwrap(); | ||
|
||
syslog(Severity::LOG_EMERG, "Hello, nix!").unwrap(); | ||
let name = "syslog"; | ||
syslog(Severity::LOG_NOTICE, &format!("Hello, {name}!")).unwrap(); | ||
} | ||
|
||
#[test] | ||
#[cfg(target_os = "linux")] | ||
fn test_openlog_with_ident() { | ||
use std::ffi::CStr; | ||
|
||
const IDENT: &CStr = unsafe { | ||
CStr::from_bytes_with_nul_unchecked(b"test_openlog_with_ident\0") | ||
}; | ||
|
||
let flags = LogFlags::LOG_PID; | ||
openlog(Some(IDENT), flags, Facility::LOG_USER).unwrap(); | ||
syslog(Severity::LOG_EMERG, "Hello, ident!").unwrap(); | ||
} | ||
|
||
#[test] | ||
#[cfg(not(target_os = "linux"))] | ||
fn test_openlog_with_ident() { | ||
let flags = LogFlags::LOG_PID; | ||
openlog(Some("test_openlog_with_ident"), flags, Facility::LOG_USER) | ||
.unwrap(); | ||
syslog(Severity::LOG_EMERG, "Hello, ident!").unwrap(); | ||
} |