Skip to content

Commit

Permalink
config: allow attaching file descriptors to commands
Browse files Browse the repository at this point in the history
  • Loading branch information
mahkoh committed Mar 6, 2024
1 parent a1ba476 commit 2037a37
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 29 deletions.
26 changes: 10 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ panic = "abort"
panic = "abort"

[dependencies]
uapi = "0.2.10"
uapi = "0.2.12"
thiserror = "1.0.56"
ahash = "0.8.7"
log = { version = "0.4.20", features = ["std"] }
Expand Down
2 changes: 1 addition & 1 deletion jay-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ bincode = "1.3.3"
serde = { version = "1.0.196", features = ["derive"] }
log = "0.4.14"
futures-util = { version = "0.3.30", features = ["io"] }
uapi = "0.2.10"
uapi = "0.2.12"
thiserror = "1.0.57"
backtrace = "0.3.69"
26 changes: 21 additions & 5 deletions jay-config/src/_private/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use {
future::Future,
mem,
ops::Deref,
os::fd::IntoRawFd,
panic::{catch_unwind, AssertUnwindSafe},
pin::Pin,
ptr,
Expand Down Expand Up @@ -264,11 +265,26 @@ impl Client {
.iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
self.send(&ClientMessage::Run {
prog: &command.prog,
args: command.args.clone(),
env,
});
let fds: Vec<_> = command
.fds
.borrow_mut()
.drain()
.map(|(a, b)| (a, b.into_raw_fd()))
.collect();
if fds.is_empty() {
self.send(&ClientMessage::Run {
prog: &command.prog,
args: command.args.clone(),
env,
});
} else {
self.send(&ClientMessage::Run2 {
prog: &command.prog,
args: command.args.clone(),
env,
fds,
});
}
}

pub fn grab(&self, kb: InputDevice, grab: bool) {
Expand Down
6 changes: 6 additions & 0 deletions jay-config/src/_private/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,12 @@ pub enum ClientMessage<'a> {
pollable: PollableId,
writable: bool,
},
Run2 {
prog: &'a str,
args: Vec<String>,
env: Vec<(String, String)>,
fds: Vec<(i32, i32)>,
},
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down
36 changes: 35 additions & 1 deletion jay-config/src/exec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Tools for spawning programs.
use std::collections::HashMap;
use std::{cell::RefCell, collections::HashMap, os::fd::OwnedFd};

/// Sets an environment variable.
///
Expand All @@ -14,6 +14,7 @@ pub struct Command {
pub(crate) prog: String,
pub(crate) args: Vec<String>,
pub(crate) env: HashMap<String, String>,
pub(crate) fds: RefCell<HashMap<i32, OwnedFd>>,
}

impl Command {
Expand All @@ -28,6 +29,7 @@ impl Command {
prog: prog.to_string(),
args: vec![],
env: Default::default(),
fds: Default::default(),
}
}

Expand All @@ -43,7 +45,39 @@ impl Command {
self
}

/// Sets a file descriptor of the process.
///
/// By default, the process starts with exactly stdin, stdout, and stderr open and all
/// pointing to `/dev/null`.
pub fn fd<F: Into<OwnedFd>>(&mut self, idx: i32, fd: F) -> &mut Self {
self.fds.borrow_mut().insert(idx, fd.into());
self
}

/// Sets the stdin of the process.
///
/// This is equivalent to `fd(0, fd)`.
pub fn stdin<F: Into<OwnedFd>>(&mut self, fd: F) -> &mut Self {
self.fd(0, fd)
}

/// Sets the stdout of the process.
///
/// This is equivalent to `fd(1, fd)`.
pub fn stdout<F: Into<OwnedFd>>(&mut self, fd: F) -> &mut Self {
self.fd(1, fd)
}

/// Sets the stderr of the process.
///
/// This is equivalent to `fd(2, fd)`.
pub fn stderr<F: Into<OwnedFd>>(&mut self, fd: F) -> &mut Self {
self.fd(2, fd)
}

/// Executes the command.
///
/// This consumes all attached file descriptors.
pub fn spawn(&self) {
get!().spawn(self);
}
Expand Down
17 changes: 14 additions & 3 deletions src/config/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use {
log::Level,
std::{cell::Cell, ops::Deref, rc::Rc, time::Duration},
thiserror::Error,
uapi::{c, fcntl_dupfd_cloexec},
uapi::{c, fcntl_dupfd_cloexec, OwnedFd},
};

pub(super) struct ConfigProxyHandler {
Expand Down Expand Up @@ -999,12 +999,17 @@ impl ConfigProxyHandler {
prog: &str,
args: Vec<String>,
env: Vec<(String, String)>,
fds: Vec<(i32, i32)>,
) -> Result<(), CphError> {
let fds: Vec<_> = fds
.into_iter()
.map(|(a, b)| (a, Rc::new(OwnedFd::new(b))))
.collect();
let forker = match self.state.forker.get() {
Some(f) => f,
_ => return Err(CphError::NoForker),
};
forker.spawn(prog.to_string(), args, env);
forker.spawn(prog.to_string(), args, env, fds);
Ok(())
}

Expand Down Expand Up @@ -1305,7 +1310,7 @@ impl ConfigProxyHandler {
ClientMessage::GetSeats => self.handle_get_seats(),
ClientMessage::RemoveSeat { .. } => {}
ClientMessage::Run { prog, args, env } => {
self.handle_run(prog, args, env).wrn("run")?
self.handle_run(prog, args, env, vec![]).wrn("run")?
}
ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab).wrn("grab")?,
ClientMessage::SetColor { colorable, color } => {
Expand Down Expand Up @@ -1505,6 +1510,12 @@ impl ConfigProxyHandler {
ClientMessage::AddInterest { pollable, writable } => self
.handle_add_interest(pollable, writable)
.wrn("add_interest")?,
ClientMessage::Run2 {
prog,
args,
env,
fds,
} => self.handle_run(prog, args, env, fds).wrn("run")?,
}
Ok(())
}
Expand Down
10 changes: 8 additions & 2 deletions src/forker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,14 @@ impl ForkerProxy {
self.pidfd(pidfd_id).await
}

pub fn spawn(&self, prog: String, args: Vec<String>, env: Vec<(String, String)>) {
self.spawn_(prog, args, env, vec![], None)
pub fn spawn(
&self,
prog: String,
args: Vec<String>,
env: Vec<(String, String)>,
fds: Vec<(i32, Rc<OwnedFd>)>,
) {
self.spawn_(prog, args, env, fds, None)
}

fn spawn_(
Expand Down

0 comments on commit 2037a37

Please sign in to comment.