-
Notifications
You must be signed in to change notification settings - Fork 677
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
91 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
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, | ||
} | ||
|
||
/// 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<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> { | ||
use std::ptr; | ||
|
||
let mut slave: libc::c_int = -1; | ||
let mut master: libc::c_int = -1; | ||
let c_termios = match termios.into() { | ||
Some(termios) => termios as *const Termios, | ||
None => ptr::null() as *const Termios, | ||
}; | ||
let c_winsize = match winsize.into() { | ||
Some(ws) => ws as *const Winsize, | ||
None => ptr::null() as *const Winsize, | ||
}; | ||
let ret = unsafe { | ||
libc::openpty( | ||
&mut master as *mut libc::c_int, | ||
&mut slave as *mut libc::c_int, | ||
ptr::null_mut(), | ||
c_termios as *mut libc::termios, | ||
c_winsize as *mut Winsize) | ||
}; | ||
|
||
let _ = try!(Errno::result(ret)); | ||
|
||
Ok(OpenptyResult { | ||
master: master, | ||
slave: slave, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} |