blob: bf06e36e7cb036899d63f398105be8b4e800d89d [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! A syslog server interface for use with EventMultiplexer.
use std::boxed::Box;
use std::fs::remove_file;
use std::io::{Error as IoError, Read};
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::path::Path;
use sys_util::{self, error, handle_eintr};
use super::events::{AddEventSourceMutator, EventSource, Mutator, RemoveFdMutator};
pub const SYSLOG_PATH: &str = "/dev/log";
/// Encapsulates a connection with a a syslog client.
struct SyslogClient(UnixStream);
impl AsRawFd for SyslogClient {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
/// This currently just makes sure the read buffer doesn't fill up, but will eventually need to be
/// written out to have a handler for the data is that is read from the stream.
impl EventSource for SyslogClient {
fn on_event(&mut self) -> Result<Option<Box<dyn Mutator>>, String> {
let mut buffer = [0; 1024];
Ok(if handle_eintr!(self.0.read(&mut buffer)).is_err() {
Some(Box::new(RemoveFdMutator(self.0.as_raw_fd())))
} else {
None
})
}
}
/// Encapsulates a unix socket listener for a syslog server that accepts client connections.
pub struct Syslog(UnixListener);
impl Syslog {
/// Return true if there is already a syslog socket open at SYSLOG_PATH.
pub fn is_syslog_present() -> bool {
Path::new(SYSLOG_PATH).exists()
}
/// Binds a new unix socket listener at the SYSLOG_PATH.
pub fn new() -> Result<Self, IoError> {
Ok(Syslog(UnixListener::bind(Path::new(SYSLOG_PATH))?))
}
}
/// Cleanup the unix socket by removing SYSLOG_PATH whenever the Syslog is dropped.
impl Drop for Syslog {
fn drop(&mut self) {
if let Err(e) = remove_file(SYSLOG_PATH) {
eprintln!("Failed to cleanup syslog: {:?}", e);
}
}
}
impl AsRawFd for Syslog {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
/// Creates a EventSource that adds any accept connections and returns a Mutator that will add the
/// client connection to the EventMultiplexer when applied.
impl EventSource for Syslog {
fn on_event(&mut self) -> Result<Option<Box<dyn Mutator>>, String> {
Ok(Some(match handle_eintr!(self.0.accept()) {
Ok((instance, _)) => Box::new(AddEventSourceMutator(Some(Box::new(SyslogClient(
instance,
))))),
Err(e) => {
error!("syslog socket error: {:?}", e);
Box::new(RemoveFdMutator(self.0.as_raw_fd()))
}
}))
}
}