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 87 88 89 90 91 92 93 94 95 96 97
use super::*; use libc; use std::fs::File; use std::io; use std::os::unix::io::{AsRawFd, FromRawFd}; pub struct Impl; impl Create for Impl { fn create_files() -> io::Result<(File, File)> { let mut outputs = [0; 2]; if unsafe { libc::pipe(outputs.as_mut_ptr()) } == -1 { return Err(io::Error::last_os_error()) } let read_fd = outputs[0]; let write_fd = outputs[1]; let read_file = unsafe { FromRawFd::from_raw_fd(read_fd) }; let write_file = unsafe { FromRawFd::from_raw_fd(write_fd) }; Ok((read_file, write_file)) } } impl Divert<io::Stdout> for Impl { fn divert_std_stream(write_file: &File) -> io::Result<()> { set_std_fd(libc::STDOUT_FILENO, write_file.as_raw_fd()) } fn reinstate_std_stream(original_fd: Fdandle) -> io::Result<()> { set_std_fd(libc::STDOUT_FILENO, original_fd)?; close_handle(original_fd) } } impl Divert<io::Stderr> for Impl { fn divert_std_stream(write_file: &File) -> io::Result<()> { set_std_fd(libc::STDERR_FILENO, write_file.as_raw_fd()) } fn reinstate_std_stream(original_fd: Fdandle) -> io::Result<()> { set_std_fd(libc::STDERR_FILENO, original_fd)?; close_handle(original_fd) } } impl Device for io::Stdout { fn obtain_original() -> io::Result<Fdandle> { get_std_handle(libc::STDOUT_FILENO) } } impl Device for io::Stderr { fn obtain_original() -> io::Result<Fdandle> { get_std_handle(libc::STDERR_FILENO) } } impl ShhRead for Impl { fn shh_read(mut read_file: &File, buf: &mut [u8]) -> io::Result<usize> { let mut avail = 0; let r = unsafe { libc::ioctl(read_file.as_raw_fd(), libc::FIONREAD, &mut avail) }; if r == -1 { Err(io::Error::last_os_error()) } else if avail == 0 { Ok(0) } else { read_file.read(buf) } } } fn close_handle(device: Fdandle) -> io::Result<()> { match unsafe { libc::close(device) } { 0 => Ok(()), _ => Err(io::Error::last_os_error()), } } fn get_std_handle(device: Fdandle) -> io::Result<Fdandle> { match unsafe { libc::dup(device) } { -1 => Err(io::Error::last_os_error()), handle => Ok(handle), } } fn set_std_fd(device: Fdandle, fd: Fdandle) -> io::Result<()> { match unsafe { libc::dup2(fd, device) } { -1 => Err(io::Error::last_os_error()), _ => Ok(()), } }