#![doc = include_str!("../README.md")]
#![deny(missing_docs)]
#![deny(clippy::all)]
#![deny(clippy::cargo)]
#![deny(clippy::pedantic)]
pub(crate) mod cli;
#[cfg(feature = "admin-gui")]
pub(crate) mod gui;
use crate::cli::LogOptions;
use std::process::ExitCode;
use clap::Parser;
use tracing_subscriber::filter::{filter_fn, FilterExt};
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::{prelude::*, EnvFilter};
pub const MDB_VERSION: &str = env!("CARGO_PKG_VERSION");
pub(crate) fn init_logger(logger: Option<LogOptions>) {
let env_filter = if let Some(logger) = &logger {
EnvFilter::builder().parse_lossy(logger.log_filter.as_ref().unwrap_or(&String::new()))
} else {
EnvFilter::from_default_env()
};
let target_filter = filter_fn(|meta| {
let target = meta.target();
[
"malwaredb",
"malwaredb_server",
"malwaredb_types",
#[cfg(debug_assertions)]
"deadpool_postgres",
#[cfg(debug_assertions)]
"postgres",
#[cfg(all(feature = "sqlite", debug_assertions))]
"rusqlite",
#[cfg(feature = "vt")]
"malwaredb_virustotal",
]
.into_iter()
.any(|name| target.eq(name) || target.starts_with(&format!("{name}::")))
});
let log_filter = env_filter.and(target_filter);
if let Some(logger) = logger {
let fmt_layer = tracing_subscriber::fmt::layer()
.pretty()
.with_writer(move || -> Box<dyn std::io::Write> {
match logger.log_target {
cli::LogTarget::Stdout => Box::new(std::io::stdout()),
cli::LogTarget::Stderr => Box::new(std::io::stderr()),
}
})
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
.with_filter(log_filter);
#[cfg(target_os = "linux")]
if let Ok(layer) = tracing_journald::layer() {
tracing_subscriber::registry()
.with(fmt_layer)
.with(layer)
.init();
} else {
tracing_subscriber::registry().with(fmt_layer).init();
}
#[cfg(target_os = "windows")]
if let Ok(eventlog) = tracing_layer_win_eventlog::EventLogLayer::new("MalwareDB Service") {
tracing_subscriber::registry()
.with(fmt_layer)
.with(eventlog)
.init();
} else {
tracing_subscriber::registry().with(fmt_layer).init();
}
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
tracing_subscriber::registry().with(fmt_layer).init();
} else {
let fmt_layer = tracing_subscriber::fmt::layer()
.pretty()
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
.with_filter(log_filter);
#[cfg(target_os = "linux")]
if let Ok(layer) = tracing_journald::layer() {
tracing_subscriber::registry()
.with(fmt_layer)
.with(layer)
.init();
} else {
tracing_subscriber::registry().with(fmt_layer).init();
}
#[cfg(target_os = "windows")]
if let Ok(eventlog) = tracing_layer_win_eventlog::EventLogLayer::new("MalwareDB Service") {
tracing_subscriber::registry()
.with(fmt_layer)
.with(eventlog)
.init();
} else {
tracing_subscriber::registry().with(fmt_layer).init();
}
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
tracing_subscriber::registry().with(fmt_layer).init();
}
}
#[tokio::main]
async fn main() -> anyhow::Result<ExitCode> {
let app = cli::Options::parse();
init_logger(Some(app.logger.clone()));
app.execute().await
}