summaryrefslogtreecommitdiff
path: root/src/pty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pty.rs')
-rw-r--r--src/pty.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/pty.rs b/src/pty.rs
index b7171885..41bd51b6 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -10,6 +10,7 @@ use std::mem;
use std::os::unix::prelude::*;
use sys::termios::Termios;
+use unistd::ForkResult;
use {Result, Error, fcntl};
use errno::Errno;
@@ -26,6 +27,18 @@ pub struct OpenptyResult {
pub slave: RawFd,
}
+/// Representation of a master with a forked pty
+///
+/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user
+/// must manually close the file descriptors.
+#[derive(Clone, Copy, Debug)]
+pub struct ForkptyResult {
+ /// The master port in a virtual pty pair
+ pub master: RawFd,
+ /// Metadata about forked process
+ pub fork_result: ForkResult,
+}
+
/// Representation of the Master device in a master/slave pty pair
///
@@ -266,3 +279,49 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
slave: slave,
})
}
+
+/// Create a new pseudoterminal, returning the master file descriptor and forked pid.
+/// in `ForkptyResult`
+/// (see [`forkpty`](http://man7.org/linux/man-pages/man3/forkpty.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`.
+pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(
+ winsize: T,
+ termios: U,
+) -> Result<ForkptyResult> {
+ use std::ptr;
+ use unistd::Pid;
+ use unistd::ForkResult::*;
+
+ let mut master: libc::c_int = unsafe { mem::uninitialized() };
+
+ let term = match termios.into() {
+ Some(termios) => {
+ let inner_termios = termios.get_libc_termios();
+ &*inner_termios as *const libc::termios as *mut _
+ },
+ None => ptr::null_mut(),
+ };
+
+ let win = winsize
+ .into()
+ .map(|ws| ws as *const Winsize as *mut _)
+ .unwrap_or(ptr::null_mut());
+
+ let res = unsafe {
+ libc::forkpty(&mut master, ptr::null_mut(), term, win)
+ };
+
+ let fork_result = Errno::result(res).map(|res| match res {
+ 0 => Child,
+ res => Parent { child: Pid::from_raw(res) },
+ })?;
+
+ Ok(ForkptyResult {
+ master: master,
+ fork_result: fork_result,
+ })
+}
+