95 lines
3.0 KiB
Rust
95 lines
3.0 KiB
Rust
|
use anyhow::anyhow;
|
||
|
use std::{fs::File, io::Read, path::PathBuf, time::Duration};
|
||
|
use toml::Value;
|
||
|
|
||
|
#[derive(Debug, Clone, Copy)]
|
||
|
pub enum DialogBackend {
|
||
|
Gtk3,
|
||
|
}
|
||
|
|
||
|
impl DialogBackend {
|
||
|
pub fn binary_name(&self) -> &str {
|
||
|
match self {
|
||
|
Self::Gtk3 => "bscreensaver-dialog-gtk3",
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl TryFrom<&str> for DialogBackend {
|
||
|
type Error = anyhow::Error;
|
||
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||
|
match value {
|
||
|
"gtk3" => Ok(Self::Gtk3),
|
||
|
other => Err(anyhow!("'{}' is not a valid dialog backend (valid: 'gtk3')", other)),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Clone)]
|
||
|
pub struct Configuration {
|
||
|
pub lock_timeout: Duration,
|
||
|
pub blank_before_locking: Duration,
|
||
|
pub dialog_backend: DialogBackend,
|
||
|
pub new_login_command: Option<String>,
|
||
|
}
|
||
|
|
||
|
impl Configuration {
|
||
|
pub fn load() -> anyhow::Result<Configuration> {
|
||
|
use humantime::parse_duration;
|
||
|
|
||
|
let config_tomls = xdg::BaseDirectories::new()?
|
||
|
.find_config_files("bscreensaver/bscreensaver.toml")
|
||
|
.map(|config_path| parse_config_toml(&config_path))
|
||
|
.collect::<Result<Vec<Value>, _>>()?;
|
||
|
|
||
|
let mut config = Configuration::default();
|
||
|
|
||
|
for config_toml in config_tomls {
|
||
|
config.lock_timeout = match config_toml.get("lock-timeout") {
|
||
|
None => config.lock_timeout,
|
||
|
Some(val) => parse_duration(val.as_str().ok_or(anyhow!("'lock-timeout' must be a duration string like '10m' or '90s'"))?)?,
|
||
|
};
|
||
|
config.blank_before_locking = match config_toml.get("blank-before-locking") {
|
||
|
None => config.blank_before_locking,
|
||
|
Some(val) => parse_duration(val.as_str().ok_or(anyhow!("'blank-before-locking' must be a duration string like '10m' or '90s'"))?)?,
|
||
|
};
|
||
|
config.dialog_backend = match config_toml.get("dialog-backend") {
|
||
|
None => config.dialog_backend,
|
||
|
Some(val) => DialogBackend::try_from(val.as_str().ok_or(anyhow!("'dialog-backend' must be a string"))?)?,
|
||
|
};
|
||
|
config.new_login_command = match config_toml.get("new-login-command") {
|
||
|
None => config.new_login_command,
|
||
|
Some(val) => val.as_str().map(|s| s.to_string()),
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if config.blank_before_locking >= config.lock_timeout {
|
||
|
Err(anyhow!("'blank-before-locking' cannot be greater than 'lock-timeout'"))
|
||
|
} else {
|
||
|
Ok(config)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn parse_config_toml(config_path: &PathBuf) -> anyhow::Result<Value> {
|
||
|
let mut f = File::open(config_path)?;
|
||
|
let mut config = String::new();
|
||
|
f.read_to_string(&mut config)?;
|
||
|
drop(f);
|
||
|
|
||
|
let config_toml = config.parse::<Value>()?;
|
||
|
Ok(config_toml)
|
||
|
}
|
||
|
|
||
|
impl Default for Configuration {
|
||
|
fn default() -> Self {
|
||
|
Self {
|
||
|
lock_timeout: Duration::from_secs(60 * 10),
|
||
|
blank_before_locking: Duration::ZERO,
|
||
|
dialog_backend: DialogBackend::Gtk3,
|
||
|
new_login_command: None,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|