use std::borrow::Cow;
use std::io;
use std::io::BufWriter;
use std::os::unix::net::UnixDatagram;
use std::os::unix::net::UnixStream;
use std::path::Path;
use crate::format::SyslogContext;
use crate::sender::internal::impl_syslog_sender_common;
use crate::sender::internal::impl_syslog_stream_send_formatted;
use crate::sender::SyslogSender;
pub fn unix_datagram(path: impl AsRef<Path>) -> io::Result<UnixDatagramSender> {
UnixDatagramSender::connect(path)
}
pub fn unix_stream(path: impl AsRef<Path>) -> io::Result<UnixStreamSender> {
UnixStreamSender::connect(path)
}
pub fn unix(path: impl AsRef<Path>) -> io::Result<SyslogSender> {
const EPROTOTYPE: i32 = nix::errno::Errno::EPROTOTYPE as i32;
let path = path.as_ref();
match unix_datagram(path) {
Ok(sender) => Ok(SyslogSender::UnixDatagram(sender)),
Err(err) => match err.raw_os_error() {
Some(EPROTOTYPE) => unix_stream(path).map(SyslogSender::UnixStream),
_ => Err(err),
},
}
}
pub fn unix_well_known() -> io::Result<SyslogSender> {
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
unix("/var/run/syslog")
} else if #[cfg(target_os = "freebsd")] {
unix("/var/run/log")
} else {
unix("/dev/log")
}
}
}
#[derive(Debug)]
pub struct UnixDatagramSender {
socket: UnixDatagram,
context: SyslogContext,
}
impl UnixDatagramSender {
pub fn connect(path: impl AsRef<Path>) -> io::Result<Self> {
let socket = UnixDatagram::unbound()?;
socket.connect(path)?;
Ok(Self {
socket,
context: SyslogContext::default(),
})
}
pub fn set_context(&mut self, context: SyslogContext) {
self.context = context;
}
pub fn mut_context(&mut self) -> &mut SyslogContext {
&mut self.context
}
pub fn send_formatted(&mut self, formatted: &[u8]) -> io::Result<()> {
self.socket.send(formatted)?;
Ok(())
}
}
impl_syslog_sender_common!(UnixDatagramSender);
#[derive(Debug)]
pub struct UnixStreamSender {
writer: BufWriter<UnixStream>,
context: SyslogContext,
postfix: Cow<'static, str>,
}
impl UnixStreamSender {
pub fn connect(path: impl AsRef<Path>) -> io::Result<Self> {
let socket = UnixStream::connect(path)?;
Ok(Self {
writer: BufWriter::new(socket),
context: SyslogContext::default(),
postfix: Cow::Borrowed("\r\n"),
})
}
pub fn set_postfix(&mut self, postfix: impl Into<Cow<'static, str>>) {
self.postfix = postfix.into();
}
pub fn set_context(&mut self, context: SyslogContext) {
self.context = context;
}
pub fn mut_context(&mut self) -> &mut SyslogContext {
&mut self.context
}
}
impl_syslog_sender_common!(UnixStreamSender);
impl_syslog_stream_send_formatted!(UnixStreamSender);