blob: 0a12ae29f884864f92db62bbb83e8853db9e6c08 [file] [log] [blame]
// Copyright 2018 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.
use std::ffi::CStr;
use log::{self, Level, LevelFilter, Metadata, Record, SetLoggerError};
static LOGGER: SyslogLogger = SyslogLogger;
struct SyslogLogger;
impl log::Log for SyslogLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
if cfg!(debug_assertions) {
metadata.level() <= Level::Debug
} else {
metadata.level() <= Level::Info
}
}
fn log(&self, record: &Record) {
if !self.enabled(&record.metadata()) {
return;
}
let level = match record.level() {
Level::Error => libc::LOG_ERR,
Level::Warn => libc::LOG_WARNING,
Level::Info => libc::LOG_INFO,
Level::Debug => libc::LOG_DEBUG,
Level::Trace => libc::LOG_DEBUG,
};
let msg = format!("{}\0", record.args());
let cmsg = if let Ok(m) = CStr::from_bytes_with_nul(msg.as_bytes()) {
m
} else {
// For now we just drop messages with interior nuls.
return;
};
// Safe because this doesn't modify any memory. There's not much use
// in checking the return value because this _is_ the logging function
// so there's no way for us to tell anyone about the error.
unsafe {
libc::syslog(level, cmsg.as_ptr());
}
}
fn flush(&self) {}
}
/// Initializes the logger to send log messages to syslog.
pub fn init(ident: &'static CStr) -> Result<(), SetLoggerError> {
// Safe because this only modifies libc's internal state and is safe to call
// multiple times.
unsafe {
libc::openlog(
ident.as_ptr(),
libc::LOG_NDELAY | libc::LOG_PID,
libc::LOG_USER,
)
};
log::set_logger(&LOGGER)?;
let level = if cfg!(debug_assertions) {
LevelFilter::Debug
} else {
LevelFilter::Info
};
log::set_max_level(level);
Ok(())
}