@ -18,9 +18,10 @@ use std::{
fn proc_file < F : ? Sized + AsRawFd > ( file : & F ) -> PathBuf
fn proc_file < F : ? Sized + AsRawFd > ( file : & F ) -> PathBuf
{
{
let fd = file . as_raw_fd ( ) ;
let fd = file . as_raw_fd ( ) ;
//let pid = process::id();
let pid = process ::id ( ) ;
//format!("/proc/{pid}/fd/{fd}").into()
//process::Command::new("/bin/ls").arg("-l").arg(format!("/proc/{pid}/fd/")).spawn().unwrap().wait().unwrap();
format! ( "/dev/fd/{fd}" ) . into ( )
format! ( "/proc/{pid}/fd/{fd}" ) . into ( )
//format!("/dev/fd/{fd}").into()
}
}
/// Attempt to `dup()` a file descriptor into a `RawFile`.
/// Attempt to `dup()` a file descriptor into a `RawFile`.
@ -40,10 +41,10 @@ fn dup_file<F: ?Sized + AsRawFd>(file: &F) -> io::Result<memfile::RawFile>
Ok ( memfile ::RawFile ::take_ownership_of_unchecked ( fd ) )
Ok ( memfile ::RawFile ::take_ownership_of_unchecked ( fd ) )
}
}
fn run_stdin < I > ( file : Option < impl Into < fs ::File > > , filename : impl AsRef < OsStr > , args : I ) -> io ::Result < process ::Child >
fn run_stdin < I > ( file : Option < impl Into < fs ::File > > , filename : impl AsRef < OsStr > , args : I ) -> io ::Result < ( process ::Child , Option < fs ::File > ) >
where I : IntoIterator < Item = OsString > ,
where I : IntoIterator < Item = OsString > ,
{
{
let file = {
let mut file = {
let file : Option < fs ::File > = file . map ( Into ::into ) ;
let file : Option < fs ::File > = file . map ( Into ::into ) ;
//TODO: Do we need to fcntl() this to make it (the fd) RW?
//TODO: Do we need to fcntl() this to make it (the fd) RW?
match file {
match file {
@ -65,7 +66,8 @@ where I: IntoIterator<Item = OsString>,
. stdout ( process ::Stdio ::inherit ( ) )
. stdout ( process ::Stdio ::inherit ( ) )
. stderr ( process ::Stdio ::inherit ( ) )
. stderr ( process ::Stdio ::inherit ( ) )
. spawn ( ) ? ;
. 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 )
io ::copy ( & mut input , & mut output )
/* .wrap_err("Failed to pipe file into stdin for child") */ ? ;
/* .wrap_err("Failed to pipe file into stdin for child") */ ? ;
}
}
@ -75,23 +77,23 @@ where I: IntoIterator<Item = OsString>,
. code ( )
. code ( )
. unwrap_or ( - 1 ) ) //XXX: What should we do if the process terminates without a code (i.e. by a signal?)
. 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.
/// 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.
/// The caller must wait for all child processes to exit before the parent does.
#[ inline ]
#[ inline ]
pub fn run_single < F : ? Sized + AsRawFd > ( file : & F , opt : args ::ExecMode ) -> io ::Result < process ::Child >
pub fn run_single < F : ? Sized + AsRawFd > ( file : & F , opt : args ::ExecMode ) -> io ::Result < ( process ::Child , Option < fs ::File > ) >
{
{
let input = dup_file( file ) ? ;
let input : std ::mem ::ManuallyDrop < memfile ::RawFile > = std::mem ::ManuallyDrop ::new ( dup_file( file ) ? ) ;
match opt {
match opt {
args ::ExecMode ::Positional { command , args } = > {
args ::ExecMode ::Positional { command , args } = > {
run_stdin ( None ::< fs ::File > , command , args . into_iter ( ) . map ( move | x | x . unwrap_or_else ( | | proc_file ( & input ) . into ( ) ) ) )
run_stdin ( None ::< fs ::File > , command , args . into_iter ( ) . map ( | x | x . unwrap_or_else ( | | proc_file ( & * input ) . into ( ) ) ) )
} ,
} ,
args ::ExecMode ::Stdin { command , args } = > {
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<F: ?Sized + AsRawFd>(file: &F, opt: args::ExecMode) -> io::Res
///
///
/// # Returns
/// # 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`.
/// 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 < Item = io ::Result < process ::Child > > + ' a
pub fn spawn_from < ' a , F : ? Sized + AsRawFd > ( file : & ' a F , opt : Options ) -> impl IntoIterator < Item = io ::Result < ( process ::Child , Option < fs ::File > ) > > + ' a
{
{
opt . into_opt_exec ( ) . map ( | x | run_single ( file , x ) )
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")
//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 ( "" ) ;
let idx = move | | idx . to_string ( ) . header ( "" ) ;
match child {
match child {
Ok ( mut child ) = > {
Ok ( mut child ) = > {
Ok ( child . wait ( )
Ok ( child . 0. wait ( )
. wrap_err ( "Failed to wait on child" )
. wrap_err ( "Failed to wait on child" )
. with_note ( | | "The child may have detached itself" )
. with_note ( | | "The child may have detached itself" )
. with_section ( idx ) ?
. with_section ( idx ) ?