Skip to content

Commit

Permalink
Add openpty()
Browse files Browse the repository at this point in the history
Add documentation for openpty

Fix mutability problem with openpty FFI
  • Loading branch information
cactorium committed Apr 17, 2017
1 parent 7b5dd78 commit 38cb514
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,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;

Expand Down
50 changes: 50 additions & 0 deletions src/pty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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(winsize: Option<Winsize>, termios: Option<Termios>) -> Result<OpenptyResult> {
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 *mut libc::termios,
c_winsize as *mut Winsize)
};

let _ = try!(Errno::result(ret));

Ok(OpenptyResult {
master: master,
slave: slave,
})
}
1 change: 1 addition & 0 deletions test/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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;
Expand Down
36 changes: 36 additions & 0 deletions test/test_pty.rs
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();
}

0 comments on commit 38cb514

Please sign in to comment.