| // 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(()) |
| } |