diff --git a/Cargo.lock b/Cargo.lock index ccb2bfb..bc112d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + [[package]] name = "anyhow" version = "1.0.82" @@ -250,6 +256,44 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.59", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + [[package]] name = "concurrent-queue" version = "2.4.0" @@ -486,6 +530,12 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -886,6 +936,7 @@ name = "steamos-manager" version = "24.4.1" dependencies = [ "anyhow", + "clap", "inotify", "nix", "tempfile", diff --git a/Cargo.toml b/Cargo.toml index 8b892d1..f16357e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ strip="symbols" [dependencies] anyhow = "1" +clap = { version = "4.5", default-features = false, features = ["derive", "help", "std", "usage"] } inotify = { version = "0.10", default-features = false, features = ["stream"] } nix = { version = "0.28", default-features = false, features = ["fs"] } tokio = { version = "1", default-features = false, features = ["fs", "io-util", "macros", "rt-multi-thread", "signal", "sync"] } diff --git a/data/com.steampowered.SteamOSManager1.service b/data/com.steampowered.SteamOSManager1.service index c0683ca..792ea8d 100644 --- a/data/com.steampowered.SteamOSManager1.service +++ b/data/com.steampowered.SteamOSManager1.service @@ -1,5 +1,5 @@ [D-BUS Service] Name=com.steampowered.SteamOSManager1 -Exec=/usr/lib/steamos-manager +Exec=/usr/lib/steamos-manager -r User=root SystemdService=steamos-manager.service diff --git a/data/steamos-manager.service b/data/steamos-manager.service index 1675fc8..1e21630 100644 --- a/data/steamos-manager.service +++ b/data/steamos-manager.service @@ -7,7 +7,7 @@ After=steamos-log-submitter.service Type=dbus BusName=com.steampowered.SteamOSManager1 Environment=RUST_LOG='INFO' -ExecStart=/usr/lib/steamos-manager +ExecStart=/usr/lib/steamos-manager -r Restart=on-failure RestartSec=1 diff --git a/src/main.rs b/src/main.rs index 6b76e56..5e489f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,28 +5,21 @@ * SPDX-License-Identifier: MIT */ -use anyhow::{anyhow, bail, Result}; +use anyhow::{anyhow, Result}; +use clap::Parser; use std::path::{Path, PathBuf}; use tokio::fs::File; use tokio::io::AsyncWriteExt; use tokio::signal::unix::{signal, SignalKind}; -use tokio::task::JoinSet; use tokio_util::sync::CancellationToken; -use tracing::{error, info, warn}; -use tracing_subscriber::prelude::*; -use tracing_subscriber::{fmt, Registry}; -use zbus::connection::Connection; -use zbus::ConnectionBuilder; - -use crate::ds_inhibit::Inhibitor; -use crate::sls::ftrace::Ftrace; -use crate::sls::{LogLayer, LogReceiver}; +use tracing::{info, warn}; mod ds_inhibit; mod hardware; mod manager; mod power; mod process; +mod root; mod sls; mod systemd; mod wifi; @@ -65,6 +58,13 @@ where } } +#[derive(Parser)] +struct Args { + /// Run the root manager daemon + #[arg(short, long)] + root: bool +} + #[cfg(not(test))] pub fn path>(path: S) -> PathBuf { PathBuf::from(path.as_ref()) @@ -147,79 +147,14 @@ pub fn zbus_to_zbus_fdo(error: zbus::Error) -> zbus::fdo::Error { } } -async fn create_connection() -> Result { - let connection = ConnectionBuilder::system()? - .name("com.steampowered.SteamOSManager1")? - .build() - .await?; - let manager = manager::SteamOSManager::new(connection.clone()).await?; - connection - .object_server() - .at("/com/steampowered/SteamOSManager1", manager) - .await?; - Ok(connection) -} - #[tokio::main] -async fn main() -> Result<()> { - // This daemon is responsible for creating a dbus api that steam client can use to do various OS - // level things. It implements com.steampowered.SteamOSManager1.Manager interface - - let stdout_log = fmt::layer(); - let subscriber = Registry::default().with(stdout_log); - - let connection = match create_connection().await { - Ok(c) => c, - Err(e) => { - let _guard = tracing::subscriber::set_default(subscriber); - error!("Error connecting to DBus: {}", e); - bail!(e); - } - }; - - let mut services = JoinSet::new(); - let token = CancellationToken::new(); - - let mut log_receiver = LogReceiver::new(connection.clone()).await?; - let remote_logger = LogLayer::new(&log_receiver).await; - let subscriber = subscriber.with(remote_logger); - tracing::subscriber::set_global_default(subscriber)?; - - let mut sigterm = signal(SignalKind::terminate())?; - let mut sigquit = signal(SignalKind::quit())?; - - let ftrace = Ftrace::init(connection.clone()).await?; - services.spawn(ftrace.start(token.clone())); - - let inhibitor = Inhibitor::init().await?; - services.spawn(inhibitor.start(token.clone())); - - let mut res = tokio::select! { - e = log_receiver.run() => e, - e = services.join_next() => match e.unwrap() { - Ok(Ok(())) => Ok(()), - Ok(Err(e)) => Err(e), - Err(e) => Err(e.into()) - }, - _ = tokio::signal::ctrl_c() => Ok(()), - e = sigterm.recv() => e.ok_or(anyhow!("SIGTERM machine broke")), - _ = sigquit.recv() => Err(anyhow!("Got SIGQUIT")), - e = reload() => e, +pub async fn main() -> Result<()> { + let args = Args::parse(); + if args.root { + root::daemon().await + } else { + todo!(); } - .inspect_err(|e| error!("Encountered error running: {e}")); - token.cancel(); - - info!("Shutting down"); - - while let Some(service_res) = services.join_next().await { - res = match service_res { - Ok(Err(e)) => Err(e), - Err(e) => Err(e.into()), - _ => continue, - }; - } - - res.inspect_err(|e| error!("Encountered error: {e}")) } #[cfg(test)] diff --git a/src/root.rs b/src/root.rs new file mode 100644 index 0000000..79bc06c --- /dev/null +++ b/src/root.rs @@ -0,0 +1,95 @@ +/* + * Copyright © 2023 Collabora Ltd. + * Copyright © 2024 Valve Software + * + * SPDX-License-Identifier: MIT + */ + +use anyhow::{anyhow, bail, Result}; +use tokio::signal::unix::{signal, SignalKind}; +use tokio::task::JoinSet; +use tokio_util::sync::CancellationToken; +use tracing::{error, info}; +use tracing_subscriber::prelude::*; +use tracing_subscriber::{fmt, Registry}; +use zbus::connection::Connection; +use zbus::ConnectionBuilder; + +use crate::ds_inhibit::Inhibitor; +use crate::{manager, reload, Service}; +use crate::sls::ftrace::Ftrace; +use crate::sls::{LogLayer, LogReceiver}; + +async fn create_connection() -> Result { + let connection = ConnectionBuilder::system()? + .name("com.steampowered.SteamOSManager1")? + .build() + .await?; + let manager = manager::SteamOSManager::new(connection.clone()).await?; + connection + .object_server() + .at("/com/steampowered/SteamOSManager1", manager) + .await?; + Ok(connection) +} + +pub async fn daemon() -> Result<()> { + // This daemon is responsible for creating a dbus api that steam client can use to do various OS + // level things. It implements com.steampowered.SteamOSManager1.Manager interface + + let stdout_log = fmt::layer(); + let subscriber = Registry::default().with(stdout_log); + + let connection = match create_connection().await { + Ok(c) => c, + Err(e) => { + let _guard = tracing::subscriber::set_default(subscriber); + error!("Error connecting to DBus: {}", e); + bail!(e); + } + }; + + let mut services = JoinSet::new(); + let token = CancellationToken::new(); + + let mut log_receiver = LogReceiver::new(connection.clone()).await?; + let remote_logger = LogLayer::new(&log_receiver).await; + let subscriber = subscriber.with(remote_logger); + tracing::subscriber::set_global_default(subscriber)?; + + let mut sigterm = signal(SignalKind::terminate())?; + let mut sigquit = signal(SignalKind::quit())?; + + let ftrace = Ftrace::init(connection.clone()).await?; + services.spawn(ftrace.start(token.clone())); + + let inhibitor = Inhibitor::init().await?; + services.spawn(inhibitor.start(token.clone())); + + let mut res = tokio::select! { + e = log_receiver.run() => e, + e = services.join_next() => match e.unwrap() { + Ok(Ok(())) => Ok(()), + Ok(Err(e)) => Err(e), + Err(e) => Err(e.into()) + }, + _ = tokio::signal::ctrl_c() => Ok(()), + e = sigterm.recv() => e.ok_or(anyhow!("SIGTERM machine broke")), + _ = sigquit.recv() => Err(anyhow!("Got SIGQUIT")), + e = reload() => e, + } + .inspect_err(|e| error!("Encountered error running: {e}")); + token.cancel(); + + info!("Shutting down"); + + while let Some(service_res) = services.join_next().await { + res = match service_res { + Ok(Err(e)) => Err(e), + Err(e) => Err(e.into()), + _ => continue, + }; + } + + res.inspect_err(|e| error!("Encountered error: {e}")) +}