1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
extern crate libc;

use libc::c_int;
use std::fs::File;
use std::io;
use std::os::unix::io::FromRawFd;
use std::os::unix::io::AsRawFd;

/// Dup represents a RW Pipe
pub struct Dup;

impl Dup {
    /// `new` returns a tuple of Files representing a Read Write Pipe
    ///
    /// # Arguments
    ///
    /// * `fd` - A file descriptor
    ///
    /// # Example
    ///
    ///  // Proxy stdio, logging to your preferred logger and then re-write to the original stdio stream.
    ///
    /// `let mut rw = dup::Dup::new(1);
    ///
    ///     thread::spawn(|| {
    ///         println!("Hello World");
    ///     });
    ///
    /// let mut reader = BufReader::new(rw.0);
    /// let mut s = String::new();
    /// reader.read_to_string(&mut s);
    /// rw.1.write(s.as_bytes());`
    ///
    pub fn new(fd: c_int) -> (File, File) {
        let pipe = Pipe::new().unwrap();
        unsafe {
            let fd = libc::dup(fd);
            let writer: File = File::from_raw_fd(fd as c_int);
            libc::dup2(writer.as_raw_fd(), fd);
            (pipe.reader, writer)
        }
    }
}


// Copyright (C) 2015 Mickaël Salaün
// For License check https://github.com/stemjail/fd-rs/tree/master/src
mod raw {
    use libc::c_int;
    // From asm-generic/fcntl.h
    pub const O_CLOEXEC: c_int = 0o2000000;

    #[repr(C)]
    pub struct PipeFds {
        pub reader: c_int,
        pub writer: c_int,
    }

    extern {
        pub fn pipe2(fds: *mut PipeFds, flags: c_int) -> c_int;
    }
}

/// A thread-safe `pipe(2)` interface.
///
/// Create a reader and a writer `File` for each part of the pipe.
pub struct Pipe {
    pub reader: File,
    pub writer: File,
}

impl Pipe {
    pub fn new() -> io::Result<Pipe> {
        let mut fds = raw::PipeFds {
            reader: -1,
            writer: -1
        };
        if unsafe { raw::pipe2(&mut fds, raw::O_CLOEXEC) } != 0 {
            return Err(io::Error::last_os_error());
        }
        Ok(Pipe {
            reader: unsafe { File::from_raw_fd(fds.reader) },
            writer: unsafe { File::from_raw_fd(fds.writer) },
        })
    }
}