diff --git a/nix/sessiond-backlight/finix.nix b/nix/sessiond-backlight/finix.nix index 8a47886..338743f 100644 --- a/nix/sessiond-backlight/finix.nix +++ b/nix/sessiond-backlight/finix.nix @@ -20,15 +20,10 @@ in "--log-target" "syslog" ]; - environment = - if cfg.debug then - { - LOG_LEVEL = "debug"; - } - else - { - LOG_LEVEL = lib.mkDefault "info"; - }; + environment = { + SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + LOG_LEVEL = if cfg.debug then "debug" else lib.mkDefault "info"; + }; }; }; } diff --git a/nix/sessiond-backlight/nixos.nix b/nix/sessiond-backlight/nixos.nix index 4798561..1a5a6a1 100644 --- a/nix/sessiond-backlight/nixos.nix +++ b/nix/sessiond-backlight/nixos.nix @@ -15,6 +15,8 @@ in after = [ "sessiond.service" ]; wantedBy = [ "default.target" ]; + environment.SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + serviceConfig = { ExecStart = "${lib.getExe cfg.package}"; Environment = if cfg.debug then "LOG_LEVEL=debug" else "LOG_LEVEL=info"; diff --git a/nix/sessiond-hooks/finix.nix b/nix/sessiond-hooks/finix.nix index 9cbb514..4ee0ed6 100644 --- a/nix/sessiond-hooks/finix.nix +++ b/nix/sessiond-hooks/finix.nix @@ -29,15 +29,10 @@ in "--config" "${configFile}" ]; - environment = - if cfg.debug then - { - LOG_LEVEL = "debug"; - } - else - { - LOG_LEVEL = lib.mkDefault "info"; - }; + environment = { + SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + LOG_LEVEL = if cfg.debug then "debug" else lib.mkDefault "info"; + }; } ) cfg.hooks; } diff --git a/nix/sessiond-hooks/nixos.nix b/nix/sessiond-hooks/nixos.nix index e18895d..b8db316 100644 --- a/nix/sessiond-hooks/nixos.nix +++ b/nix/sessiond-hooks/nixos.nix @@ -22,6 +22,8 @@ in after = [ "sessiond.service" ]; wantedBy = [ "default.target" ]; + environment.SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + serviceConfig = { ExecStart = "${lib.getExe cfg.package} --config ${configFile}"; Environment = if cfg.debug then "LOG_LEVEL=debug" else "LOG_LEVEL=info"; diff --git a/nix/sessiond-power/finix.nix b/nix/sessiond-power/finix.nix index 8d6a351..9b70a07 100644 --- a/nix/sessiond-power/finix.nix +++ b/nix/sessiond-power/finix.nix @@ -19,15 +19,10 @@ in "service/sessiond/ready" ]; command = "${lib.getExe cfg.package} --config ${configFile} --log-target syslog"; - environment = - if cfg.debug then - { - LOG_LEVEL = "debug"; - } - else - { - LOG_LEVEL = lib.mkDefault "info"; - }; + environment = { + SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + LOG_LEVEL = if cfg.debug then "debug" else lib.mkDefault "info"; + }; }; }; } diff --git a/nix/sessiond-power/nixos.nix b/nix/sessiond-power/nixos.nix index a6d5bd0..313164e 100644 --- a/nix/sessiond-power/nixos.nix +++ b/nix/sessiond-power/nixos.nix @@ -18,6 +18,8 @@ in after = [ "sessiond.service" ]; wantedBy = [ "default.target" ]; + environment.SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + serviceConfig = { ExecStart = "${lib.getExe cfg.package} --config ${configFile}"; Environment = if cfg.debug then "LOG_LEVEL=debug" else "LOG_LEVEL=info"; diff --git a/nix/sessiond-uaccess/finix.nix b/nix/sessiond-uaccess/finix.nix index 830bc14..003aa87 100644 --- a/nix/sessiond-uaccess/finix.nix +++ b/nix/sessiond-uaccess/finix.nix @@ -36,15 +36,10 @@ in command = "${lib.getExe cfg.package} --log-target syslog --rules-dirs ${cfg.package}/share/sessiond-uaccess/rules " + lib.optionalString (cfg.extraConfig != "") "--rules-dirs ${configFile}"; - environment = - if cfg.debug then - { - LOG_LEVEL = "debug"; - } - else - { - LOG_LEVEL = lib.mkDefault "info"; - }; + environment = { + SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + LOG_LEVEL = if cfg.debug then "debug" else lib.mkDefault "info"; + }; }; }; } diff --git a/nix/sessiond-uaccess/nixos.nix b/nix/sessiond-uaccess/nixos.nix index a9646a7..598ed7b 100644 --- a/nix/sessiond-uaccess/nixos.nix +++ b/nix/sessiond-uaccess/nixos.nix @@ -18,6 +18,8 @@ in after = [ "sessiond.service" ]; wantedBy = [ "default.target" ]; + environment.SESSIOND_RUNTIME_DIR = config.services.sessiond.runtimeDir; + serviceConfig = { ExecStart = "${lib.getExe cfg.package} --rules-dirs ${cfg.package}/share/sessiond-uaccess/rules " diff --git a/nix/sessiond/common.nix b/nix/sessiond/common.nix index 5d397ac..b715939 100644 --- a/nix/sessiond/common.nix +++ b/nix/sessiond/common.nix @@ -26,6 +26,15 @@ in ''; }; + runtimeDir = lib.mkOption { + type = types.strMatching "/.*"; + default = "/run/sessiond"; + description = '' + Absolute path to the sessiond runtime directory containing its socket and state. + Passed to companion services as `SESSIOND_RUNTIME_DIR`. + ''; + }; + debug = lib.mkOption { type = types.bool; default = false; diff --git a/nix/sessiond/finix.nix b/nix/sessiond/finix.nix index ce04f1a..239f82f 100644 --- a/nix/sessiond/finix.nix +++ b/nix/sessiond/finix.nix @@ -36,7 +36,7 @@ in finit.services.sessiond = { description = "daemon for power management"; conditions = "service/dbus/ready"; - command = "${lib.getExe' cfg.package "sessiond"} --config ${configFile} --log-target syslog"; + command = "${lib.getExe' cfg.package "sessiond"} --config ${configFile} --runtime-dir ${lib.escapeShellArg cfg.runtimeDir} --log-target syslog"; notify = "systemd"; cgroup.delegate = true; environment = diff --git a/nix/sessiond/nixos.nix b/nix/sessiond/nixos.nix index 68c6970..ba00eb8 100644 --- a/nix/sessiond/nixos.nix +++ b/nix/sessiond/nixos.nix @@ -1,6 +1,7 @@ { lib, pkgs, + utils, config, ... }: @@ -21,7 +22,9 @@ in wantedBy = [ "default.target" ]; serviceConfig = { - ExecStart = "${cfg.package}/bin/sessiond --config ${sessiondConfig}"; + ExecStart = "${cfg.package}/bin/sessiond --config ${sessiondConfig} --runtime-dir ${ + utils.escapeSystemdExecArgs [ cfg.runtimeDir ] + }"; Environment = if cfg.debug then "LOG_LEVEL=debug" else "LOG_LEVEL=info"; Type = "notify"; Delegate = true; diff --git a/sessionctl/src/main.rs b/sessionctl/src/main.rs index fc8e131..3a7e8f4 100644 --- a/sessionctl/src/main.rs +++ b/sessionctl/src/main.rs @@ -4,6 +4,7 @@ mod seat_core_v1 { pub use spec::*; } +use anyhow::Context; use clap::{CommandFactory, FromArgMatches, Parser, Subcommand, ValueEnum}; use comfy_table::presets; use hyprwire::client; @@ -1238,7 +1239,11 @@ fn acquire_inhibitor( mode: InhibitMode, ) -> anyhow::Result<()> { let mut state = InhibitState::default(); - let mut socket = client::Client::connect("/run/sessiond/sessiond.sock")?; + let sessiond_runtime_dir: path::PathBuf = env::var_os("SESSIOND_RUNTIME_DIR") + .map(path::PathBuf::from) + .unwrap_or_else(|| path::PathBuf::from("/run/sessiond")); + let mut socket = client::Client::connect(sessiond_runtime_dir.join("sessiond.sock")) + .context("failed to connect to /run/sessiond/sessiond.sock")?; let queue = socket.new_event_queue(); socket.add_implementation::(); @@ -1298,7 +1303,11 @@ fn main() -> anyhow::Result<()> { } let mut state = State::default(); - let mut socket = client::Client::connect("/run/sessiond/sessiond.sock")?; + let sessiond_runtime_dir: path::PathBuf = env::var_os("SESSIOND_RUNTIME_DIR") + .map(path::PathBuf::from) + .unwrap_or_else(|| path::PathBuf::from("/run/sessiond")); + let mut socket = client::Client::connect(sessiond_runtime_dir.join("sessiond.sock")) + .context("failed to connect to /run/sessiond/sessiond.sock")?; let queue = socket.new_event_queue(); socket.add_implementation::(); diff --git a/sessiond-backlight/src/main.rs b/sessiond-backlight/src/main.rs index dfce8f0..79b7715 100644 --- a/sessiond-backlight/src/main.rs +++ b/sessiond-backlight/src/main.rs @@ -380,16 +380,20 @@ fn main() -> anyhow::Result<()> { devices: Vec::new(), }; - let socket_path = path::Path::new("/run/sessiond-backlight.sock"); - let mut server = server::Server::bind(&socket_path)?; - fs::set_permissions(socket_path, fs::Permissions::from_mode(0o666))?; + let sessiond_runtime_dir: path::PathBuf = env::var_os("SESSIOND_RUNTIME_DIR") + .map(path::PathBuf::from) + .unwrap_or_else(|| path::PathBuf::from("/run/sessiond")); + let backlight_socket_path = sessiond_runtime_dir.join("backlight.sock"); + + let mut server = server::Server::bind(&backlight_socket_path)?; + fs::set_permissions(backlight_socket_path, fs::Permissions::from_mode(0o666))?; server.add_implementation::( &mut sessiond_backlight, 1, ); - let mut client = client::Client::connect("/run/sessiond/sessiond.sock")?; + let mut client = client::Client::connect(sessiond_runtime_dir.join("sessiond.sock"))?; let eq = client.new_event_queue(); client.add_implementation::(); diff --git a/sessiond-hooks/src/main.rs b/sessiond-hooks/src/main.rs index 1727b93..55601a6 100644 --- a/sessiond-hooks/src/main.rs +++ b/sessiond-hooks/src/main.rs @@ -16,7 +16,7 @@ use hyprwire_protocols_sessiond::client::session_management::v2::session_managem use std::collections::BTreeMap; use std::os::fd::AsRawFd; use std::os::unix::process::CommandExt; -use std::{env, ops, path, process, time}; +use std::{env, fs, io, ops, path, process, time}; use uzers::os::unix::UserExt; #[derive(Parser)] @@ -543,7 +543,7 @@ fn main() -> anyhow::Result<()> { }; let normal_uids = normal_uid_range( - &std::fs::read_to_string("/etc/login.defs").context("reading /etc/login.defs")?, + &fs::read_to_string("/etc/login.defs").context("reading /etc/login.defs")?, )?; let log_level = match env::var("LOG_LEVEL") { Ok(log) if log == "trace" => log::LevelFilter::Trace, @@ -566,7 +566,11 @@ fn main() -> anyhow::Result<()> { } let mut event_loop = calloop::EventLoop::try_new()?; - let mut socket = client::Client::connect("/run/sessiond/sessiond.sock")?; + + let sessiond_runtime_dir: path::PathBuf = env::var_os("SESSIOND_RUNTIME_DIR") + .map(path::PathBuf::from) + .unwrap_or_else(|| path::PathBuf::from("/run/sessiond")); + let mut socket = client::Client::connect(sessiond_runtime_dir.join("sessiond.sock"))?; let eq = socket.new_event_queue(); let mut sessiond_hooks = SessiondHooks { @@ -603,8 +607,7 @@ fn main() -> anyhow::Result<()> { event_loop .handle() .insert_source(source, move |_, _, state| { - eq.dispatch_events(state, false) - .map_err(std::io::Error::other)?; + eq.dispatch_events(state, false).map_err(io::Error::other)?; Ok(calloop::PostAction::Continue) })?; diff --git a/sessiond-power/daemon/src/main.rs b/sessiond-power/daemon/src/main.rs index 68b6123..6c3db2c 100644 --- a/sessiond-power/daemon/src/main.rs +++ b/sessiond-power/daemon/src/main.rs @@ -15,9 +15,6 @@ use session_power_v1::session_power_manager; use std::os::unix::fs::PermissionsExt; use std::{env, fs, path, process}; -const SESSIOND_SOCKET_PATH: &str = "/run/sessiond/sessiond.sock"; -const POWER_SOCKET_PATH: &str = "/run/sessiond/power.sock"; - #[derive(Parser)] struct Args { #[arg(short, long, help = "Path to configuration file")] @@ -438,8 +435,13 @@ fn main() -> anyhow::Result<()> { error: None, }; - let mut session_socket = client::Client::connect(SESSIOND_SOCKET_PATH) - .with_context(|| format!("failed to connect to {SESSIOND_SOCKET_PATH}"))?; + let sessiond_runtime_dir: path::PathBuf = env::var_os("SESSIOND_RUNTIME_DIR") + .map(path::PathBuf::from) + .unwrap_or_else(|| path::PathBuf::from("/run/sessiond")); + let sessiond_socket_path = sessiond_runtime_dir.join("sessiond.sock"); + + let mut session_socket = client::Client::connect(&sessiond_socket_path) + .with_context(|| format!("failed to connect to {}", sessiond_socket_path.display()))?; let session_queue = session_socket.new_event_queue(); session_socket.add_implementation::(); session_queue.wait_for_handshake(&mut sessiond_power)?; @@ -459,8 +461,9 @@ fn main() -> anyhow::Result<()> { anyhow::bail!(message); } - let mut power_socket = server::Server::bind(&POWER_SOCKET_PATH)?; - fs::set_permissions(POWER_SOCKET_PATH, fs::Permissions::from_mode(0o666))?; + let power_socket_path = sessiond_runtime_dir.join("power.sock"); + let mut power_socket = server::Server::bind(&power_socket_path)?; + fs::set_permissions(power_socket_path, fs::Permissions::from_mode(0o666))?; power_socket.add_implementation::(&mut sessiond_power, 1); let mut event_loop = calloop::EventLoop::::try_new()?; diff --git a/sessiond-uaccess/src/main.rs b/sessiond-uaccess/src/main.rs index 3859ccd..836c953 100644 --- a/sessiond-uaccess/src/main.rs +++ b/sessiond-uaccess/src/main.rs @@ -396,7 +396,10 @@ fn main() -> anyhow::Result<()> { loop_signal.wakeup(); })?; - let mut socket = client::Client::connect("/run/sessiond/sessiond.sock") + let sessiond_runtime_dir: path::PathBuf = env::var_os("SESSIOND_RUNTIME_DIR") + .map(path::PathBuf::from) + .unwrap_or_else(|| path::PathBuf::from("/run/sessiond")); + let mut socket = client::Client::connect(sessiond_runtime_dir.join("sessiond.sock")) .context("failed to connect to /run/sessiond/sessiond.sock")?; let eq = socket.new_event_queue(); diff --git a/sessiond/src/config.rs b/sessiond/src/config.rs index d46c381..c32123d 100644 --- a/sessiond/src/config.rs +++ b/sessiond/src/config.rs @@ -36,6 +36,7 @@ impl UserConfig { gid: u32, session_id: u32, term: Option>, + sessiond_runtime_dir: sync::Arc, ) -> BTreeMap, sync::Arc> { let runtime_dir = self.runtime_dir(uid, gid); let mut env: BTreeMap, sync::Arc> = BTreeMap::from([ @@ -48,6 +49,10 @@ impl UserConfig { sync::Arc::from("TERM"), term.unwrap_or_else(|| "linux".into()), ), + ( + sync::Arc::from("SESSIOND_RUNTIME_DIR"), + sessiond_runtime_dir, + ), ]); if let Some(user) = uzers::get_user_by_uid(uid) { diff --git a/sessiond/src/main.rs b/sessiond/src/main.rs index 52f0af7..a867fef 100644 --- a/sessiond/src/main.rs +++ b/sessiond/src/main.rs @@ -25,7 +25,10 @@ use rustix::net; use std::os::fd::AsRawFd; use std::os::unix::ffi::OsStrExt; use std::os::unix::fs::PermissionsExt; -use std::{env, fs, path}; +use std::{env, fs, path, sync}; + +#[derive(Resource)] +pub struct SessiondRuntimeDir(sync::Arc); #[derive(Parser)] struct Args { @@ -58,7 +61,7 @@ struct ShutdownRequested; struct Sessiond { world: World, - notify_schedule: Schedule, + schedule: Schedule, } fn notify(message: &[u8]) -> rustix::io::Result<()> { @@ -93,7 +96,7 @@ fn handle_shutdown( loop_signal.0.stop(); } -fn run(runtime_dir: &path::Path, config: config::Config) -> anyhow::Result<()> { +fn run(runtime_dir: path::PathBuf, config: config::Config) -> anyhow::Result<()> { let mut event_loop = calloop::EventLoop::try_new()?; let signals = signals::Signals::new(&[ signals::Signal::SIGUSR1, @@ -116,6 +119,7 @@ fn run(runtime_dir: &path::Path, config: config::Config) -> anyhow::Result<()> { world.insert_resource(inhibit::NextInhibitorId(inhibit::InhibitorId::from_raw(1))); world.init_resource::(); world.init_resource::(); + world.insert_resource(SessiondRuntimeDir(runtime_dir.to_string_lossy().into())); world.init_resource::(); world.init_resource::(); world.init_resource::(); @@ -172,10 +176,7 @@ fn run(runtime_dir: &path::Path, config: config::Config) -> anyhow::Result<()> { schedule.add_systems(state::write_state.after(reconcile::send_done)); schedule.add_systems(message::message_update_system.after(reconcile::send_done)); - let mut sessiond = Sessiond { - world, - notify_schedule: schedule, - }; + let mut sessiond = Sessiond { world, schedule }; let mut startup = Schedule::default(); startup.add_systems((user::initialize_lingering_users, state::load_state)); @@ -190,8 +191,8 @@ fn run(runtime_dir: &path::Path, config: config::Config) -> anyhow::Result<()> { sessiond.world.clear_trackers(); - fs::create_dir_all(runtime_dir)?; - fs::set_permissions(runtime_dir, fs::Permissions::from_mode(0o755))?; + fs::create_dir_all(&runtime_dir)?; + fs::set_permissions(&runtime_dir, fs::Permissions::from_mode(0o755))?; let socket_path = runtime_dir.join("sessiond.sock"); let mut socket = server::Server::bind(&socket_path)?; @@ -274,7 +275,7 @@ fn run(runtime_dir: &path::Path, config: config::Config) -> anyhow::Result<()> { } event_loop.run(None, &mut sessiond, |state| { - state.notify_schedule.run(&mut state.world); + state.schedule.run(&mut state.world); })?; terminal::Terminal::open(0) @@ -310,5 +311,5 @@ fn main() -> anyhow::Result<()> { log::info!("sessiond daemon starting"); - run(&args.runtime_dir, config::Config::load(args.config)?) + run(args.runtime_dir, config::Config::load(args.config)?) } diff --git a/sessiond/src/session.rs b/sessiond/src/session.rs index 02f9a06..d427db4 100644 --- a/sessiond/src/session.rs +++ b/sessiond/src/session.rs @@ -754,6 +754,7 @@ pub fn handle_session_management_action( sessions: Query<(&SessionEnv, &Uid), With>, config: Res, loop_handle: NonSend<'_, calloop::LoopHandle<'static, crate::Sessiond>>, + sessiond_runtime_dir: Res, ) { for action in actions.read() { if let SessionManagementAction::ManagerDestroy { management_object } = &action.action { @@ -912,6 +913,7 @@ pub fn handle_session_management_action( pending_session.gid, session_id.as_raw(), term, + sync::Arc::clone(&sessiond_runtime_dir.0), ); for (session_env, _) in sessions .iter()