ashpd/flatpak/development.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
//! The Development interface lets any client, possibly in a sandbox if it has
//! access to the session helper, spawn a process on the host, outside any
//! sandbox.
use std::{collections::HashMap, os::fd::AsFd, path::Path};
use enumflags2::{bitflags, BitFlags};
use futures_util::Stream;
use serde_repr::{Deserialize_repr, Serialize_repr};
use zbus::zvariant::{Fd, Type};
use crate::{proxy::Proxy, Error, FilePath, Pid};
#[bitflags]
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Eq, Copy, Clone, Debug, Type)]
#[repr(u32)]
/// Flags affecting the running of commands on the host
pub enum HostCommandFlags {
#[doc(alias = "FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV")]
/// Clear the environment.
ClearEnv,
#[doc(alias = "FLATPAK_HOST_COMMAND_FLAGS_WATCH_BUS")]
/// Kill the sandbox when the caller disappears from the session bus.
WatchBus,
}
/// The Development interface lets any client, possibly in a sandbox if it has
/// access to the session helper, spawn a process on the host, outside any
/// sandbox.
///
/// Wrapper of the DBus interface: [`org.freedesktop.Flatpak.Development`](https://docs.flatpak.org/en/latest/libflatpak-api-reference.html#gdbus-org.freedesktop.Flatpak.Development)
#[derive(Debug)]
#[doc(alias = "org.freedesktop.Flatpak.Development")]
pub struct Development<'a>(Proxy<'a>);
impl<'a> Development<'a> {
/// Create a new instance of [`Development`]
pub async fn new() -> Result<Development<'a>, Error> {
let proxy = Proxy::new_flatpak_development("org.freedesktop.Flatpak.Development").await?;
Ok(Self(proxy))
}
/// Emitted when a process started by
/// [`host_command()`][`Development::host_command`] exits.
///
/// # Specifications
///
/// See also [`HostCommandExited`](https://docs.flatpak.org/en/latest/libflatpak-api-reference.html#gdbus-signal-org-freedesktop-Flatpak-Development.HostCommandExited).
#[doc(alias = "HostCommandExited")]
pub async fn receive_spawn_exited(&self) -> Result<impl Stream<Item = (u32, u32)>, Error> {
self.0.signal("HostCommandExited").await
}
/// This method lets trusted applications (insider or outside a sandbox) run
/// arbitrary commands in the user's session, outside any sandbox.
///
/// # Arguments
///
/// * `cwd_path` - The working directory for the new process.
/// * `argv` - The argv for the new process, starting with the executable to
/// launch.
/// * `fds` - Array of file descriptors to pass to the new process.
/// * `envs` - Array of variable/value pairs for the environment of the new
/// process.
/// * `flags`
///
/// # Returns
///
/// The PID of the new process.
///
/// # Specifications
///
/// See also [`HostCommand`](https://docs.flatpak.org/en/latest/libflatpak-api-reference.html#gdbus-method-org-freedesktop-Flatpak-Development.HostCommand).
pub async fn host_command(
&self,
cwd_path: impl AsRef<Path>,
argv: &[impl AsRef<Path>],
fds: HashMap<u32, impl AsFd>,
envs: HashMap<&str, &str>,
flags: BitFlags<HostCommandFlags>,
) -> Result<u32, Error> {
let cwd_path = FilePath::new(cwd_path)?;
let argv = argv
.iter()
.map(FilePath::new)
.collect::<Result<Vec<FilePath>, _>>()?;
let fds: HashMap<u32, Fd> = fds.iter().map(|(k, val)| (*k, Fd::from(val))).collect();
self.0
.call("HostCommand", &(cwd_path, argv, fds, envs, flags))
.await
}
/// This methods let you send a Unix signal to a process that was started
/// [`host_command()`][`Development::host_command`].
///
/// # Arguments
///
/// * `pid` - The PID of the process to send the signal to.
/// * `signal` - The signal to send.
/// * `to_process_group` - Whether to send the signal to the process group.
///
/// # Specifications
///
/// See also [`HostCommandSignal`](https://docs.flatpak.org/en/latest/libflatpak-api-reference.html#gdbus-method-org-freedesktop-Flatpak-Development.HostCommandSignal).
#[doc(alias = "SpawnSignal")]
#[doc(alias = "xdp_portal_spawn_signal")]
pub async fn host_command_signal(
&self,
pid: Pid,
signal: u32,
to_process_group: bool,
) -> Result<(), Error> {
self.0
.call("HostCommandSignal", &(pid, signal, to_process_group))
.await
}
}
impl<'a> std::ops::Deref for Development<'a> {
type Target = zbus::Proxy<'a>;
fn deref(&self) -> &Self::Target {
&self.0
}
}