From 286c3d95f514b59b4c14b6e7c2e35632192f0e24 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Wed, 2 Nov 2016 09:26:29 -0400 Subject: [PATCH 1/3] Add openpty() --- src/lib.rs | 2 ++ src/pty.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ test/test.rs | 1 + test/test_pty.rs | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 src/pty.rs create mode 100644 test/test_pty.rs diff --git a/src/lib.rs b/src/lib.rs index ab8339efc1..7722a451fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,8 @@ pub mod mount; #[cfg(target_os = "linux")] pub mod mqueue; +pub mod pty; + #[cfg(any(target_os = "linux", target_os = "macos"))] pub mod poll; diff --git a/src/pty.rs b/src/pty.rs new file mode 100644 index 0000000000..04fd05b1df --- /dev/null +++ b/src/pty.rs @@ -0,0 +1,43 @@ +use libc; + +use {Errno, Result}; +use std::os::unix::io::RawFd; + +use sys::termios::Termios; + +pub use libc::pid_t as SessionId; +pub use libc::winsize as Winsize; + +pub struct OpenptyResult { + pub master: RawFd, + pub slave: RawFd, +} + +#[inline] +pub fn openpty(winsize: Option, termios: Option) -> Result { + let mut slave: libc::c_int = -1; + let mut master: libc::c_int = -1; + let c_termios = match &termios { + &Some(ref termios) => termios as *const Termios, + &None => 0 as *const Termios, + }; + let c_winsize = match &winsize { + &Some(ref ws) => ws as *const Winsize, + &None => 0 as *const Winsize, + }; + let ret = unsafe { + libc::openpty( + &mut master as *mut libc::c_int, + &mut slave as *mut libc::c_int, + 0 as *mut libc::c_char, + c_termios as *const libc::termios, + c_winsize) + }; + + let _ = try!(Errno::result(ret)); + + Ok(OpenptyResult { + master: master, + slave: slave, + }) +} diff --git a/test/test.rs b/test/test.rs index 045f8f1837..5063ee00b2 100644 --- a/test/test.rs +++ b/test/test.rs @@ -11,6 +11,7 @@ mod sys; mod test_fcntl; mod test_net; mod test_nix_path; +mod test_pty; #[cfg(any(target_os = "linux", target_os = "android"))] mod test_sendfile; mod test_stat; diff --git a/test/test_pty.rs b/test/test_pty.rs new file mode 100644 index 0000000000..1fcd4a891b --- /dev/null +++ b/test/test_pty.rs @@ -0,0 +1,36 @@ +use nix::pty::openpty; +use nix::unistd::{read, write, close}; + +#[test] +fn test_openpty() { + // TODO: figure out the right termios settings to pass in here + let pty = openpty(None, None).unwrap(); + assert!(pty.master > 0); // must be valid file descriptors + assert!(pty.slave > 0); + + // writing to one should be readable on the other one + let string = "foofoofoo\n"; + let mut buf = [0u8; 16]; + write(pty.master, string.as_bytes()).unwrap(); + let len = read(pty.slave, &mut buf).unwrap(); + + assert_eq!(len, string.len()); + assert_eq!(&buf[0..len], string.as_bytes()); + + // read the echo as well + let echoed_string = "foofoofoo\r\n"; + let len = read(pty.master, &mut buf).unwrap(); + assert_eq!(len, echoed_string.len()); + assert_eq!(&buf[0..len], echoed_string.as_bytes()); + + let string2 = "barbarbarbar\n"; + let echoed_string2 = "barbarbarbar\r\n"; + write(pty.slave, string2.as_bytes()).unwrap(); + let len = read(pty.master, &mut buf).unwrap(); + + assert_eq!(len, echoed_string2.len()); + assert_eq!(&buf[0..len], echoed_string2.as_bytes()); + + close(pty.master).unwrap(); + close(pty.slave).unwrap(); +} From e1974793cadce05c98b04b9143017026eb76a5fe Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Wed, 2 Nov 2016 09:39:29 -0400 Subject: [PATCH 2/3] Add documentation for openpty --- src/pty.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pty.rs b/src/pty.rs index 04fd05b1df..343323b5b5 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -13,6 +13,13 @@ pub struct OpenptyResult { pub slave: RawFd, } +/// Create a new pseudoterminal, returning the slave and master file descriptors +/// in `OpenptyResult` +/// (see [openpty](http://man7.org/linux/man-pages/man3/openpty.3.html)). +/// +/// If `winsize` is not `None`, the window size of the slave will be set to +/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's +/// terminal settings of the slave will be set to the values in `termios`. #[inline] pub fn openpty(winsize: Option, termios: Option) -> Result { let mut slave: libc::c_int = -1; From bc019895099cad79b2f2e9c79cae39f822dc3285 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Wed, 2 Nov 2016 10:04:56 -0400 Subject: [PATCH 3/3] Fix mutability problem with openpty FFI --- src/pty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pty.rs b/src/pty.rs index 343323b5b5..535444357d 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -37,8 +37,8 @@ pub fn openpty(winsize: Option, termios: Option) -> Result