4
4
5
5
use std:: ffi;
6
6
use std:: io;
7
- use std:: io:: Write ;
7
+ use std:: io:: { Read , Write } ;
8
8
use std:: path;
9
9
use std:: process;
10
10
@@ -416,7 +416,48 @@ impl Command {
416
416
/// assert!(output.status.success());
417
417
/// ```
418
418
pub fn output ( & mut self ) -> io:: Result < process:: Output > {
419
- self . spawn ( ) ?. wait_with_output ( )
419
+ let spawn = self . spawn ( ) ?;
420
+ Self :: wait_with_input_output ( spawn, self . stdin . clone ( ) )
421
+ }
422
+
423
+ /// If `input`, write it to `child`'s stdin while also reading `child`'s
424
+ /// stdout and stderr, then wait on `child` and return its status and output.
425
+ ///
426
+ /// This was lifted from `std::process::Child::wait_with_output` and modified
427
+ /// to also write to stdin.
428
+ fn wait_with_input_output (
429
+ mut child : process:: Child ,
430
+ input : Option < Vec < u8 > > ,
431
+ ) -> io:: Result < process:: Output > {
432
+ let stdin = input. and_then ( |i| {
433
+ child
434
+ . stdin
435
+ . take ( )
436
+ . map ( |mut stdin| std:: thread:: spawn ( move || stdin. write_all ( & i) ) )
437
+ } ) ;
438
+ fn read < R > ( mut input : R ) -> std:: thread:: JoinHandle < io:: Result < Vec < u8 > > >
439
+ where
440
+ R : Read + Send + ' static ,
441
+ {
442
+ std:: thread:: spawn ( move || {
443
+ let mut ret = Vec :: new ( ) ;
444
+ input. read_to_end ( & mut ret) . map ( |_| ret)
445
+ } )
446
+ }
447
+ let stdout = child. stdout . take ( ) . map ( read) ;
448
+ let stderr = child. stderr . take ( ) . map ( read) ;
449
+
450
+ // Finish writing stdin before waiting, because waiting drops stdin.
451
+ stdin. and_then ( |t| t. join ( ) . unwrap ( ) . ok ( ) ) ;
452
+ let status = child. wait ( ) ?;
453
+ let stdout = stdout. and_then ( |t| t. join ( ) . unwrap ( ) . ok ( ) ) ;
454
+ let stderr = stderr. and_then ( |t| t. join ( ) . unwrap ( ) . ok ( ) ) ;
455
+
456
+ Ok ( process:: Output {
457
+ status : status,
458
+ stdout : stdout. unwrap_or_default ( ) ,
459
+ stderr : stderr. unwrap_or_default ( ) ,
460
+ } )
420
461
}
421
462
422
463
fn spawn ( & mut self ) -> io:: Result < process:: Child > {
@@ -425,16 +466,7 @@ impl Command {
425
466
self . cmd . stdout ( process:: Stdio :: piped ( ) ) ;
426
467
self . cmd . stderr ( process:: Stdio :: piped ( ) ) ;
427
468
428
- let mut spawned = self . cmd . spawn ( ) ?;
429
-
430
- if let Some ( buffer) = self . stdin . as_ref ( ) {
431
- spawned
432
- . stdin
433
- . as_mut ( )
434
- . expect ( "Couldn't get mut ref to command stdin" )
435
- . write_all ( & buffer) ?;
436
- }
437
- Ok ( spawned)
469
+ self . cmd . spawn ( )
438
470
}
439
471
}
440
472
0 commit comments