Skip to content

Commit 596280b

Browse files
committed
refactor: use AsRef<OsStr> on non-Linux and &'static CStr on Linux for ident arg of openlog
1 parent 541801e commit 596280b

File tree

2 files changed

+63
-12
lines changed

2 files changed

+63
-12
lines changed

src/syslog.rs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,64 @@
11
//! Interfaces for controlling system log.
22
33
use crate::{NixPath, Result};
4-
use std::ffi::{CStr, OsStr};
4+
use std::ffi::OsStr;
55
use std::ptr;
66

77
/// Logging options of subsequent [`syslog`] calls can be set by calling [`openlog`].
88
///
99
/// The parameter `ident` is a string that will be prepended to every message. The `logopt`
1010
/// argument specifies logging options. The `facility` parameter encodes a default facility to be
1111
/// assigned to all messages that do not have an explicit facility encoded.
12+
//
13+
// On Linux, the `ident` argument needs to have static lifetime according to the
14+
// man page:
15+
//
16+
// The argument ident in the call of openlog() is probably stored as-is. Thus,
17+
// if the string it points to is changed, syslog() may start prepending the changed
18+
// string, and if the string it points to ceases to exist, the results are
19+
// undefined. Most portable is to use a string constant.
20+
#[cfg(target_os = "linux")]
1221
pub fn openlog(
13-
ident: Option<&'static CStr>,
22+
ident: Option<&'static std::ffi::CStr>,
1423
logopt: LogFlags,
1524
facility: Facility,
1625
) -> Result<()> {
17-
let ident = ident.map_or(ptr::null(), |ident| ident.as_ptr());
1826
let logopt = logopt.bits();
1927
let facility = facility as libc::c_int;
20-
unsafe {
21-
libc::openlog(ident, logopt, facility);
28+
match ident {
29+
None => unsafe {
30+
libc::openlog(ptr::null(), logopt, facility);
31+
},
32+
Some(ident) => ident.with_nix_path(|ident| unsafe {
33+
libc::openlog(ident.as_ptr(), logopt, facility);
34+
})?,
2235
}
36+
37+
Ok(())
38+
}
39+
40+
/// Logging options of subsequent [`syslog`] calls can be set by calling [`openlog`].
41+
///
42+
/// The parameter `ident` is a string that will be prepended to every message. The `logopt`
43+
/// argument specifies logging options. The `facility` parameter encodes a default facility to be
44+
/// assigned to all messages that do not have an explicit facility encoded.
45+
#[cfg(not(target_os = "linux"))]
46+
pub fn openlog<S: AsRef<OsStr> + ?Sized>(
47+
ident: Option<&S>,
48+
logopt: LogFlags,
49+
facility: Facility,
50+
) -> Result<()> {
51+
let logopt = logopt.bits();
52+
let facility = facility as libc::c_int;
53+
match ident.map(OsStr::new) {
54+
None => unsafe {
55+
libc::openlog(ptr::null(), logopt, facility);
56+
},
57+
Some(ident) => ident.with_nix_path(|ident| unsafe {
58+
libc::openlog(ident.as_ptr(), logopt, facility);
59+
})?,
60+
}
61+
2362
Ok(())
2463
}
2564

@@ -31,15 +70,14 @@ pub fn openlog(
3170
/// # Examples
3271
///
3372
/// ```rust
34-
/// use nix::syslog::{openlog, syslog, Facility, LogFlags, Severity};
73+
/// use nix::syslog::{openlog, syslog, Facility, LogFlags, Severity, Priority};
3574
///
36-
/// let flags = LogFlags::LOG_PID;
37-
/// openlog(None, flags, Facility::LOG_USER).unwrap();
38-
/// syslog(Severity::LOG_EMERG, "Hello, nix!").unwrap();
75+
/// let priority = Priority::new(Severity::LOG_EMERG, Facility::LOG_USER);
76+
/// syslog(priority, "Hello, nix!").unwrap();
3977
///
4078
/// // use `format!` to format the message
4179
/// let name = "syslog";
42-
/// syslog(Severity::LOG_EMERG, &format!("Hello, {name}!")).unwrap();
80+
/// syslog(priority, &format!("Hello, {name}!")).unwrap();
4381
/// ```
4482
pub fn syslog<P, S>(priority: P, message: &S) -> Result<()>
4583
where

test/test_syslog.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
use nix::syslog::{openlog, syslog, Facility, LogFlags, Severity};
2-
use std::ffi::CStr;
32

43
#[test]
54
fn test_syslog_hello_world() {
65
let flags = LogFlags::LOG_PID;
6+
7+
#[cfg(not(target_os = "linux"))]
8+
openlog(None::<&str>, flags, Facility::LOG_USER).unwrap();
9+
#[cfg(target_os = "linux")]
710
openlog(None, flags, Facility::LOG_USER).unwrap();
8-
syslog(Severity::LOG_EMERG, "Hello, nix!").unwrap();
911

12+
syslog(Severity::LOG_EMERG, "Hello, nix!").unwrap();
1013
let name = "syslog";
1114
syslog(Severity::LOG_NOTICE, &format!("Hello, {name}!")).unwrap();
1215
}
1316

1417
#[test]
18+
#[cfg(target_os = "linux")]
1519
fn test_openlog_with_ident() {
1620
const IDENT: &CStr = unsafe {
1721
CStr::from_bytes_with_nul_unchecked(b"test_openlog_with_ident\0")
@@ -21,3 +25,12 @@ fn test_openlog_with_ident() {
2125
openlog(Some(IDENT), flags, Facility::LOG_USER).unwrap();
2226
syslog(Severity::LOG_EMERG, "Hello, ident!").unwrap();
2327
}
28+
29+
#[test]
30+
#[cfg(not(target_os = "linux"))]
31+
fn test_openlog_with_ident() {
32+
let flags = LogFlags::LOG_PID;
33+
openlog(Some("test_openlog_with_ident"), flags, Facility::LOG_USER)
34+
.unwrap();
35+
syslog(Severity::LOG_EMERG, "Hello, ident!").unwrap();
36+
}

0 commit comments

Comments
 (0)