oconnor663 / duct.rs

a Rust library for running child processes
MIT License
795 stars 34 forks source link

Using process substitution in duct.rs #67

Closed maexrakete closed 5 years ago

maexrakete commented 5 years ago

Hey mate,

thanks for this great lib and your hard work. I wanted to now if I could use duct for a process substitution like this:

pub fn verify(content: String, signature: String) {
    match cmd!("gpg", "--verify", &format!("<(echo {})", signature), &format!("<(echo {})", content)).read() {
        Ok(res) => println!("{}", res),
        _ => println!("not okay")
    };
}

I basically want to pass a string and a signature to gpg so verify the signature without creating files.

oconnor663 commented 5 years ago

Duct doesn't currently support process substitution directly, but you could do the same thing the shell does:

  1. Create a couple of FIFOs on the filesystem somewhere. (You could use nix::unistd::mkfifo.)
  2. Start two echo processes with duct::Expression::start writing to the FIFOs. Or really, you could just use a couple of standard Rust background threads. But make sure to use something other than your main thread, because writing to a pipe/FIFO blocks when the write is longer than the pipe buffer, and in this case blocking your main thread would cause a deadlock.
  3. Pass the paths to the FIFOs as command line arguments to gpg.
  4. Once gpg exits, await any writer child processes you spawned.

If you don't want to touch the filesystem at all, even to lay out FIFOs, then you have a harder problem. I don't know if there's a way to convince GPG to read from any descriptor other than stdin. Or of course you could use combined signatures that include the input file.

maexrakete commented 5 years ago

Hey!

Thanks for your response. I temporarily use mktemp currently, but your proposal looks like a better idea!

Thanks for your help, I'll close this issue.