1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::ffi::CStr;
6
7 use log::{self, Level, LevelFilter, Metadata, Record, SetLoggerError};
8
9 static LOGGER: SyslogLogger = SyslogLogger;
10
11 struct SyslogLogger;
12
13 impl log::Log for SyslogLogger {
enabled(&self, metadata: &Metadata) -> bool14 fn enabled(&self, metadata: &Metadata) -> bool {
15 if cfg!(debug_assertions) {
16 metadata.level() <= Level::Debug
17 } else {
18 metadata.level() <= Level::Info
19 }
20 }
21
log(&self, record: &Record)22 fn log(&self, record: &Record) {
23 if !self.enabled(&record.metadata()) {
24 return;
25 }
26
27 let level = match record.level() {
28 Level::Error => libc::LOG_ERR,
29 Level::Warn => libc::LOG_WARNING,
30 Level::Info => libc::LOG_INFO,
31 Level::Debug => libc::LOG_DEBUG,
32 Level::Trace => libc::LOG_DEBUG,
33 };
34
35 let msg = format!("{}\0", record.args());
36 let cmsg = if let Ok(m) = CStr::from_bytes_with_nul(msg.as_bytes()) {
37 m
38 } else {
39 // For now we just drop messages with interior nuls.
40 return;
41 };
42
43 // Safe because this doesn't modify any memory. There's not much use
44 // in checking the return value because this _is_ the logging function
45 // so there's no way for us to tell anyone about the error.
46 unsafe {
47 libc::syslog(level, cmsg.as_ptr());
48 }
49 }
flush(&self)50 fn flush(&self) {}
51 }
52
53 /// Initializes the logger to send log messages to syslog.
init(ident: &'static CStr) -> Result<(), SetLoggerError>54 pub fn init(ident: &'static CStr) -> Result<(), SetLoggerError> {
55 // Safe because this only modifies libc's internal state and is safe to call
56 // multiple times.
57 unsafe {
58 libc::openlog(
59 ident.as_ptr(),
60 libc::LOG_NDELAY | libc::LOG_PID,
61 libc::LOG_USER,
62 )
63 };
64 log::set_logger(&LOGGER)?;
65 let level = if cfg!(debug_assertions) {
66 LevelFilter::Debug
67 } else {
68 LevelFilter::Info
69 };
70 log::set_max_level(level);
71
72 Ok(())
73 }
74