use std::ops::{BitAnd, Shl};
use std::mem::zeroed;
use std::ffi::CString;
use super::error::{SyRes, SyslogError, SyslogErrCode};
use super::throw_error;
bitflags! {
pub struct LogStat: libc::c_int
{
const LOG_PID = libc::LOG_PID;
const LOG_CONS = libc::LOG_CONS;
const LOG_ODELAY = libc::LOG_ODELAY;
const LOG_NDELAY = libc::LOG_NDELAY;
const LOG_NOWAIT = libc::LOG_NOWAIT;
const LOG_PERROR = 0x20;
}
}
bitflags! {
pub(crate) struct LogMask: libc::c_int
{
const LOG_FACMASK = libc::LOG_FACMASK;
const LOG_PRIMASK = libc::LOG_PRIMASK;
}
}
bitflags! {
pub struct Priority: libc::c_int
{
const LOG_EMERG = libc::LOG_EMERG;
const LOG_ALERT = libc::LOG_ALERT;
const LOG_CRIT = libc::LOG_CRIT;
const LOG_ERR = libc::LOG_ERR;
const LOG_WARNING = libc::LOG_WARNING;
const LOG_NOTICE = libc::LOG_NOTICE;
const LOG_INFO = libc::LOG_INFO;
const LOG_DEBUG = libc::LOG_DEBUG;
}
}
bitflags! {
pub struct LogFacility: libc::c_int
{
const LOG_KERN = libc::LOG_KERN;
const LOG_USER = libc::LOG_USER;
const LOG_MAIL = libc::LOG_MAIL;
const LOG_DAEMON = libc::LOG_DAEMON;
const LOG_AUTH = libc::LOG_AUTH;
const LOG_SYSLOG = libc::LOG_SYSLOG;
const LOG_LPR = libc::LOG_LPR;
const LOG_NEWS = libc::LOG_NEWS;
const LOG_UUCP = libc::LOG_UUCP;
const LOG_LOCAL0 = libc::LOG_LOCAL0;
const LOG_LOCAL1 = libc::LOG_LOCAL1;
const LOG_LOCAL2 = libc::LOG_LOCAL2;
const LOG_LOCAL3 = libc::LOG_LOCAL3;
const LOG_LOCAL4 = libc::LOG_LOCAL4;
const LOG_LOCAL5 = libc::LOG_LOCAL5;
const LOG_LOCAL6 = libc::LOG_LOCAL6;
const LOG_LOCAL7 = libc::LOG_LOCAL7;
}
}
pub const MAXHOSTNAMELEN: usize = 256;
pub const LOG_FACMASK: i32 = 0x03f8;
pub const MAXLINE: u32 = 8192;
pub const NILVALUE: &'static str = "-";
pub const PATH_LOG: &'static str = "/var/run/log";
pub const PATH_LOG_PRIV: &'static str = "/var/run/logpriv";
pub const PATH_OLDLOG: &'static str = "/dev/log";
pub const PATH_OSX: &'static str = "/var/run/syslog";
lazy_static! {
pub static ref PATH_CONSOLE: CString = CString::new("/dev/console").unwrap();
}
#[macro_export]
macro_rules! LOG_MASK
{
($($arg:tt)*) => (
(1 << $($arg)*)
)
}
#[macro_export]
macro_rules! LOG_UPTO
{
($($arg:tt)*) => (
((1 << (($($arg)*) + 1)) - 1)
)
}
pub fn get_internal_log() -> libc::c_int
{
return
Priority::LOG_ERR.bits() |
(LogStat::LOG_CONS| LogStat::LOG_PERROR| LogStat::LOG_PID).bits();
}
impl Shl<Priority> for i32
{
type Output = i32;
fn shl(self, rhs: Priority) -> i32
{
let lhs = self;
return lhs << rhs.bits();
}
}
impl BitAnd<Priority> for i32
{
type Output = i32;
#[inline]
fn bitand(self, rhs: Priority) -> i32
{
return self & rhs.bits();
}
}
impl BitAnd<LogMask> for Priority
{
type Output = Priority;
#[inline]
fn bitand(self, rhs: LogMask) -> Self::Output
{
return Self {bits: self.bits() & rhs.bits()};
}
}
impl BitAnd<LogMask> for LogFacility
{
type Output = LogFacility;
#[inline]
fn bitand(self, rhs: LogMask) -> Self::Output
{
return Self {bits: self.bits() & rhs.bits()};
}
}
impl BitAnd<LogMask> for i32
{
type Output = i32;
#[inline]
fn bitand(self, rhs: LogMask) -> i32
{
return self & rhs.bits();
}
}
pub(crate) fn send_to_stderr(
fd: libc::c_int,
msg: &mut [u8],
newline: &mut String)
{
let mut iov1: libc::iovec = unsafe {zeroed()};
let mut iov2: libc::iovec = unsafe {zeroed()};
iov1.iov_base = msg.as_mut_ptr() as *mut _ as *mut libc::c_void;
iov1.iov_len = msg.len();
iov2.iov_base = newline.as_mut_ptr() as *mut libc::c_void;
iov2.iov_len = 1;
unsafe
{
libc::writev(
fd,
[iov1, iov2].as_ptr() as *const libc::iovec,
2
);
}
}
pub(crate) fn truncate(lt: &str) -> &str
{
let ltt =
match lt.char_indices().nth(lt.len()-1)
{
None => lt,
Some((idx, _)) => <[..idx],
};
return ltt;
}
pub(crate) fn truncate_n(lt: &str, n: usize) -> String
{
let ltt =
match lt.char_indices().nth(n)
{
None => lt,
Some((idx, _)) => <[..idx],
};
return ltt.to_string();
}
pub(crate) fn check_invalid_bits(pri: &mut i32) -> SyRes<()>
{
if (*pri & !(LogMask::LOG_PRIMASK | LogMask::LOG_FACMASK )) != 0
{
let pri_old = *pri;
*pri = *pri & (LogMask::LOG_PRIMASK | LogMask::LOG_FACMASK).bits();
throw_error!("unknwon facility/priority: {:x}", pri_old);
}
return Ok(());
}
#[test]
fn test_truncate()
{
let test = "cat\n";
let trunc = truncate(test);
assert_eq!("cat", trunc);
}
#[test]
fn test_priority_shl()
{
assert_eq!((1 << 5), (1 << Priority::LOG_NOTICE));
}