• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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