modular session management daemon
Something went wrong. Try again.
3.4 kB · 133 lines
Rust
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134use serde::{Deserialize, Serialize};use std::collections::BTreeMap;use std::{fs, io, num, path, result, sync};use toml::{de, ser};
#[cfg(feature = "monitor")]pub mod monitor;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]#[serde(rename_all = "kebab-case")]pub enum SessionClass { #[default] User, Greeter, LockScreen, Background, BackgroundLight, Manager, ManagerEarly, #[serde(other)] Unknown,}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]#[serde(rename_all = "kebab-case")]pub enum SessionState { #[default] Online, Active, Closing, Opening, #[serde(other)] Unknown,}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]#[serde(rename_all = "kebab-case")]pub enum UserState { Offline, Lingering, Online, Active, Closing, #[serde(other)] Unknown,}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]#[serde(rename_all = "kebab-case")]pub struct User { pub state: UserState,}
#[derive(Default, Debug, Serialize, Deserialize)]#[serde(rename_all = "kebab-case")]pub struct State { #[serde(skip)] path: sync::Arc<path::PathBuf>, pub next_session_id: u32, #[serde(default)] pub users: BTreeMap<u32, User>, #[serde(default)] pub sessions: BTreeMap<String, Session>,}
#[derive(Debug, Serialize, Deserialize)]#[serde(rename_all = "kebab-case")]pub struct Session { pub uid: u32, pub class: SessionClass, pub vt: Option<num::NonZeroU32>, pub leader: Option<num::NonZeroU32>, pub remote_host: Option<sync::Arc<str>>, pub timestamp: u128, pub env: BTreeMap<sync::Arc<str>, sync::Arc<str>>, #[serde(alias = "active")] pub state: SessionState, pub recoverable: bool, pub display: u32,}
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]#[non_exhaustive]pub enum Error { #[error("state file I/O failed: {0}")] Io(#[from] io::Error),
#[error("invalid state file: {0}")] Decode(#[from] de::Error),
#[error("failed to serialize state: {0}")] Encode(#[from] ser::Error),}
impl State { /// Watches this state's file without reading or modifying the snapshot. /// /// Create the monitor before the initial [`Self::try_read`] to avoid missing /// updates during that read. The parent directory must already exist. /// /// # Errors /// Returns an error if the inotify instance or directory watch cannot be created. #[cfg(feature = "monitor")] pub fn monitor(&self) -> io::Result<monitor::Monitor> { monitor::Monitor::new(self.path.as_ref()) }
#[must_use] pub fn new() -> Self { Self { path: path::PathBuf::from("/run/sessiond/state.toml").into(), ..Default::default() } }
/// Reads session state from a TOML file. /// /// # Errors /// /// Returns an error if the file cannot be read as UTF-8 or its contents /// cannot be deserialized into [`State`]. pub fn try_read(&mut self) -> Result<()> { let contents = fs::read_to_string(self.path.as_ref())?;
let mut state = toml::from_str::<Self>(&contents)?; state.path = sync::Arc::clone(&self.path);
*self = state; Ok(()) }}