diff --git a/src/exec.rs b/src/exec.rs index f0d54b5..0509ef1 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -18,9 +18,10 @@ use std::{ fn proc_file(file: &F) -> PathBuf { let fd = file.as_raw_fd(); - //let pid = process::id(); - //format!("/proc/{pid}/fd/{fd}").into() - format!("/dev/fd/{fd}").into() + let pid = process::id(); + //process::Command::new("/bin/ls").arg("-l").arg(format!("/proc/{pid}/fd/")).spawn().unwrap().wait().unwrap(); + format!("/proc/{pid}/fd/{fd}").into() + //format!("/dev/fd/{fd}").into() } /// Attempt to `dup()` a file descriptor into a `RawFile`. @@ -40,10 +41,10 @@ fn dup_file(file: &F) -> io::Result Ok(memfile::RawFile::take_ownership_of_unchecked(fd)) } -fn run_stdin(file: Option>, filename: impl AsRef, args: I) -> io::Result +fn run_stdin(file: Option>, filename: impl AsRef, args: I) -> io::Result<(process::Child, Option)> where I: IntoIterator, { - let file = { + let mut file = { let file: Option = file.map(Into::into); //TODO: Do we need to fcntl() this to make it (the fd) RW? match file { @@ -65,7 +66,8 @@ where I: IntoIterator, .stdout(process::Stdio::inherit()) .stderr(process::Stdio::inherit()) .spawn()?; - if let Some((mut input, mut output)) = file.zip(child.stdin.take()) { + //TODO: XXX: Why does `/proc/{pid}/fd/{fd}` **and** `/dev/fd/{fd}` not work for -exec{}, and why foes `Stdio::from(file)` not work for stdin even *afer* re-seeking the file??? + if let Some((mut input, mut output)) = file.as_mut().zip(child.stdin.take()) { io::copy(&mut input, &mut output) /*.wrap_err("Failed to pipe file into stdin for child")*/?; } @@ -75,23 +77,23 @@ where I: IntoIterator, .code() .unwrap_or(-1)) //XXX: What should we do if the process terminates without a code (i.e. by a signal?) */ - Ok(child) + Ok((child, file)) } /// Run a single `-exec` / `-exec{}` and return the (possibly still running) child process if succeeded in spawning. /// /// The caller must wait for all child processes to exit before the parent does. #[inline] -pub fn run_single(file: &F, opt: args::ExecMode) -> io::Result +pub fn run_single(file: &F, opt: args::ExecMode) -> io::Result<(process::Child, Option)> { - let input = dup_file(file)?; + let input: std::mem::ManuallyDrop = std::mem::ManuallyDrop::new(dup_file(file)?); match opt { args::ExecMode::Positional { command, args } => { - run_stdin(None::, command, args.into_iter().map(move |x| x.unwrap_or_else(|| proc_file(&input).into()))) + run_stdin(None::, command, args.into_iter().map(|x| x.unwrap_or_else(|| proc_file(&*input).into()))) }, args::ExecMode::Stdin { command, args } => { - run_stdin(Some(input), command, args) + run_stdin(Some(std::mem::ManuallyDrop::into_inner(input)), command, args) } } } @@ -100,7 +102,7 @@ pub fn run_single(file: &F, opt: args::ExecMode) -> io::Res /// /// # Returns /// An iterator of each (possibly running) spawned child, or the error that occoured when trying to spawn that child from the `exec` option in `opt`. -pub fn spawn_from<'a, F: ?Sized + AsRawFd>(file: &'a F, opt: Options) -> impl IntoIterator> + 'a +pub fn spawn_from<'a, F: ?Sized + AsRawFd>(file: &'a F, opt: Options) -> impl IntoIterator)>> + 'a { opt.into_opt_exec().map(|x| run_single(file, x)) //todo!("Loop through `opt.into_exec()`, map the call to `|x| run_single(file, x)`, and return that iterator") @@ -120,7 +122,7 @@ pub fn spawn_from_sync<'a, F: ?Sized + AsRawFd>(file: &'a F, opt: Options) -> im let idx = move || idx.to_string().header(""); match child { Ok(mut child) => { - Ok(child.wait() + Ok(child.0.wait() .wrap_err("Failed to wait on child") .with_note(|| "The child may have detached itself") .with_section(idx)?