diff --git a/Cargo.toml b/Cargo.toml index a78eef8..640a900 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,4 @@ keywords = ["termios", "tty", "terminal", "posix"] [dependencies] libc = "0.2" +ioctl-rs = "0.1.5" diff --git a/src/lib.rs b/src/lib.rs index 8967b7c..f26643d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,6 +105,8 @@ //! ``` extern crate libc; +extern crate ioctl_rs as ioctl; + use std::io; use std::mem; @@ -171,6 +173,7 @@ impl Termios { /// Creates a `Termios` structure based on the current settings of a file descriptor. /// /// `fd` must be an open file descriptor for a terminal device. + #[cfg(not(target_os = "linux"))] pub fn from_fd(fd: RawFd) -> io::Result { let mut termios = unsafe { mem::uninitialized() }; @@ -180,6 +183,25 @@ impl Termios { } } + /// Creates a `Termios` structure based on the current settings of a file descriptor. + /// + /// `fd` must be an open file descriptor for a terminal device. + #[cfg(target_os = "linux")] + pub fn from_fd(fd: RawFd) -> io::Result { + let mut termios: Termios = unsafe { mem::uninitialized() }; + + // on Linux, we use an ioctl to get the correct data structure + let err = unsafe { ioctl::ioctl(fd, os::linux::TCGETS2, + &mut termios.inner) }; + + if err != 0 { + return Err(io::Error::last_os_error()) + } + + Ok(termios) + } + + fn inner(&self) -> &::os::target::termios { &self.inner } diff --git a/src/os/linux.rs b/src/os/linux.rs index 5e535b2..7f9af6f 100644 --- a/src/os/linux.rs +++ b/src/os/linux.rs @@ -17,8 +17,8 @@ pub struct termios { pub c_lflag: tcflag_t, c_line: cc_t, pub c_cc: [cc_t; NCCS], - c_ispeed: speed_t, - c_ospeed: speed_t + pub c_ispeed: speed_t, + pub c_ospeed: speed_t, } pub const NCCS: usize = 32; @@ -178,3 +178,7 @@ pub const TCIOFLUSH: c_int = 2; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; + +// ioctls should be a c_uint, not a c_int. the warning cause by this should +// be ignore until the bug in ioctl-rs is fixed. +pub const TCGETS2: c_int = (0x802c_542a as c_int);