Skip to content

Commit 663ff03

Browse files
committed
Add openpty()
1 parent 7b5dd78 commit 663ff03

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub mod mount;
4444
#[cfg(target_os = "linux")]
4545
pub mod mqueue;
4646

47+
pub mod pty;
48+
4749
#[cfg(any(target_os = "linux", target_os = "macos"))]
4850
pub mod poll;
4951

src/pty.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use libc;
2+
3+
use {Errno, Result};
4+
use std::os::unix::io::RawFd;
5+
6+
use sys::termios::Termios;
7+
8+
pub use libc::pid_t as SessionId;
9+
pub use libc::winsize as Winsize;
10+
11+
pub struct OpenptyResult {
12+
pub master: RawFd,
13+
pub slave: RawFd,
14+
}
15+
16+
#[inline]
17+
pub fn openpty(winsize: Option<Winsize>, termios: Option<Termios>) -> Result<OpenptyResult> {
18+
let mut slave: libc::c_int = -1;
19+
let mut master: libc::c_int = -1;
20+
let c_termios = match &termios {
21+
&Some(ref termios) => termios as *const Termios,
22+
&None => 0 as *const Termios,
23+
};
24+
let c_winsize = match &winsize {
25+
&Some(ref ws) => ws as *const Winsize,
26+
&None => 0 as *const Winsize,
27+
};
28+
let ret = unsafe {
29+
libc::openpty(
30+
&mut master as *mut libc::c_int,
31+
&mut slave as *mut libc::c_int,
32+
0 as *mut libc::c_char,
33+
c_termios as *const libc::termios,
34+
c_winsize)
35+
};
36+
37+
let _ = try!(Errno::result(ret));
38+
39+
Ok(OpenptyResult {
40+
master: master,
41+
slave: slave,
42+
})
43+
}

test/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod sys;
1313
mod test_fcntl;
1414
mod test_net;
1515
mod test_nix_path;
16+
mod test_pty;
1617
#[cfg(any(target_os = "linux", target_os = "android"))]
1718
mod test_sendfile;
1819
mod test_stat;

test/test_pty.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use nix::pty::openpty;
2+
use nix::unistd::{read, write, close};
3+
4+
#[test]
5+
fn test_openpty() {
6+
// TODO: figure out the right termios settings to pass in here
7+
let pty = openpty(None, None).unwrap();
8+
assert!(pty.master > 0); // must be valid file descriptors
9+
assert!(pty.slave > 0);
10+
11+
// writing to one should be readable on the other one
12+
let string = "foofoofoo\n";
13+
let mut buf = [0u8; 16];
14+
write(pty.master, string.as_bytes()).unwrap();
15+
let len = read(pty.slave, &mut buf).unwrap();
16+
17+
assert_eq!(len, string.len());
18+
assert_eq!(&buf[0..len], string.as_bytes());
19+
20+
// read the echo as well
21+
let echoed_string = "foofoofoo\r\n";
22+
let len = read(pty.master, &mut buf).unwrap();
23+
assert_eq!(len, echoed_string.len());
24+
assert_eq!(&buf[0..len], echoed_string.as_bytes());
25+
26+
let string2 = "barbarbarbar\n";
27+
let echoed_string2 = "barbarbarbar\r\n";
28+
write(pty.slave, string2.as_bytes()).unwrap();
29+
let len = read(pty.master, &mut buf).unwrap();
30+
31+
assert_eq!(len, echoed_string2.len());
32+
assert_eq!(&buf[0..len], echoed_string2.as_bytes());
33+
34+
close(pty.master).unwrap();
35+
close(pty.slave).unwrap();
36+
}

0 commit comments

Comments
 (0)