diff --git a/Cargo.lock b/Cargo.lock index edfdddc..cd2c477 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -279,6 +279,7 @@ dependencies = [ "color-eyre", "cosmic-notifications-util", "futures-util", + "itertools", "launch-pad", "libc", "log-panics", @@ -344,6 +345,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "enumflags2" version = "0.7.7" @@ -563,6 +570,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.8" diff --git a/Cargo.toml b/Cargo.toml index 210e445..267d3cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ async-signals = "0.4" color-eyre = "0.6" futures-util = "0.3" launch-pad = { git = "https://github.com/pop-os/launch-pad" } +itertools = "0.12" # launch-pad = { path = "../launch-pad" } libc = "0.2" log-panics = { version = "2", features = ["with-backtrace"] } diff --git a/src/main.rs b/src/main.rs index 4035db4..ee19f51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,13 +8,16 @@ mod process; mod service; mod systemd; -use std::{os::fd::AsRawFd, sync::Arc}; +use std::{ + os::fd::{AsRawFd, OwnedFd}, + sync::Arc, +}; use async_signals::Signals; use color_eyre::{eyre::WrapErr, Result}; use comp::create_privileged_socket; use cosmic_notifications_util::{DAEMON_NOTIFICATIONS_FD, PANEL_NOTIFICATIONS_FD}; -use futures_util::StreamExt; +use futures_util::{SinkExt, StreamExt}; use launch_pad::{process::Process, ProcessManager}; use service::SessionRequest; use tokio::{ @@ -53,10 +56,9 @@ async fn main() -> Result<()> { let session_tx_clone = session_tx.clone(); let _conn = ConnectionBuilder::session()? .name("com.system76.CosmicSession")? - .serve_at( - "/com/system76/CosmicSession", - service::SessionService { session_tx }, - )? + .serve_at("/com/system76/CosmicSession", service::SessionService { + session_tx, + })? .build() .await?; @@ -191,6 +193,7 @@ async fn start( &process_manager, &env_vars, &socket_tx, + Vec::new(), ) .await; @@ -201,6 +204,7 @@ async fn start( &process_manager, &env_vars, &socket_tx, + Vec::new(), ) .await; @@ -211,22 +215,50 @@ async fn start( &process_manager, &env_vars, &socket_tx, + Vec::new(), ) .await; let span = info_span!(parent: None, "cosmic-osd"); - start_component("cosmic-osd", span, &process_manager, &env_vars, &socket_tx).await; + start_component( + "cosmic-osd", + span, + &process_manager, + &env_vars, + &socket_tx, + Vec::new(), + ) + .await; let span = info_span!(parent: None, "cosmic-bg"); - start_component("cosmic-bg", span, &process_manager, &env_vars, &socket_tx).await; + start_component( + "cosmic-bg", + span, + &process_manager, + &env_vars, + &socket_tx, + Vec::new(), + ) + .await; let span = info_span!(parent: None, "xdg-desktop-portal-cosmic"); + let mut sockets = Vec::with_capacity(1); + let extra_env = Vec::with_capacity(1); + let portal_extras = + if let Ok((mut env, fd)) = create_privileged_socket(&mut sockets, &extra_env) { + let mut env = env.remove(0); + env.0 = "PORTAL_WAYLAND_SOCKET".to_string(); + vec![(fd, env, sockets.remove(0))] + } else { + Vec::new() + }; start_component( XDP_COSMIC.unwrap_or("/usr/libexec/xdg-desktop-portal-cosmic"), span, &process_manager, &env_vars, &socket_tx, + portal_extras, ) .await; @@ -279,16 +311,27 @@ async fn start_component( process_manager: &ProcessManager, env_vars: &[(String, String)], socket_tx: &mpsc::UnboundedSender>, + extra_fds: Vec<(OwnedFd, (String, String), UnixStream)>, ) { - let mut sockets = Vec::with_capacity(1); - let (env_vars, fd) = create_privileged_socket(&mut sockets, env_vars).unwrap(); - if let Err(why) = socket_tx.send(sockets) { - error!(?why, "Failed to send the privileged socket"); - } + let mut sockets = Vec::with_capacity(2); + let (mut env_vars, fd) = create_privileged_socket(&mut sockets, &env_vars).unwrap(); + let socket_tx_clone = socket_tx.clone(); let stdout_span = span.clone(); let stderr_span = span.clone(); let cmd_clone = cmd.to_string(); + let (mut fds, extra_fd_env, mut streams): (Vec<_>, Vec<_>, Vec<_>) = + itertools::multiunzip(extra_fds); + for kv in &extra_fd_env { + env_vars.push(kv.clone()); + } + + sockets.append(&mut streams); + if let Err(why) = socket_tx.send(sockets) { + error!(?why, "Failed to send the privileged socket"); + } + let (extra_fd_env, _): (Vec<_>, Vec<_>) = extra_fd_env.into_iter().unzip(); + fds.push(fd); process_manager .start( Process::new() @@ -312,16 +355,25 @@ async fn start_component( if let Some(err) = err_code { error!("{cmd_clone} exited with error {}", err.to_string()); } - + let extra_fd_env = extra_fd_env.clone(); let socket_tx_clone = socket_tx_clone.clone(); async move { if !will_restart { return; } - let mut sockets = Vec::with_capacity(1); - let env_vars = Vec::with_capacity(1); - let (env_vars, new_fd) = - create_privileged_socket(&mut sockets, &env_vars).unwrap(); + + let mut sockets = Vec::with_capacity(1 + extra_fd_env.len()); + let mut fds = Vec::with_capacity(1 + extra_fd_env.len()); + let (mut env_vars, fd) = + create_privileged_socket(&mut sockets, &[]).unwrap(); + fds.push(fd); + for k in extra_fd_env { + let (mut fd_env_vars, fd) = + create_privileged_socket(&mut sockets, &[]).unwrap(); + fd_env_vars.last_mut().unwrap().0 = k; + env_vars.append(&mut fd_env_vars); + fds.push(fd) + } if let Err(why) = socket_tx_clone.send(sockets) { error!(?why, "Failed to send the privileged socket"); @@ -329,13 +381,12 @@ async fn start_component( if let Err(why) = pman.update_process_env(&key, env_vars).await { error!(?why, "Failed to update environment variables"); } - if let Err(why) = pman.update_process_fds(&key, move || vec![new_fd]).await - { + if let Err(why) = pman.update_process_fds(&key, move || fds).await { error!(?why, "Failed to update fds"); } } }) - .with_fds(move || vec![fd]), + .with_fds(move || fds), ) .await .unwrap_or_else(|_| panic!("failed to start {}", cmd)); diff --git a/src/notifications.rs b/src/notifications.rs index e2baf0d..3052a15 100644 --- a/src/notifications.rs +++ b/src/notifications.rs @@ -1,12 +1,11 @@ -use color_eyre::eyre::Context; -use color_eyre::Result; +use color_eyre::{eyre::Context, Result}; use cosmic_notifications_util::{DAEMON_NOTIFICATIONS_FD, PANEL_NOTIFICATIONS_FD}; -use launch_pad::process::Process; -use launch_pad::ProcessKey; +use launch_pad::{process::Process, ProcessKey}; use rustix::fd::AsRawFd; -use std::os::fd::OwnedFd; -use std::os::unix::net::UnixStream; -use std::sync::Arc; +use std::{ + os::{fd::OwnedFd, unix::net::UnixStream}, + sync::Arc, +}; use tokio::sync::{mpsc, Mutex}; use tracing::Instrument;