Skip to content

Commit

Permalink
adopt my filedescriptor crate in the pty crate
Browse files Browse the repository at this point in the history
Refs: #27
  • Loading branch information
wez committed May 20, 2019
1 parent 7464965 commit c562f35
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 216 deletions.
1 change: 1 addition & 0 deletions pty/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ documentation = "https://docs.rs/portable-pty"
[dependencies]
failure = "0.1"
failure_derive = "0.1"
filedescriptor = "0.1"
libc = "0.2"
serde_derive = {version="1.0", optional=true}
serde = {version="1.0", optional=true}
Expand Down
83 changes: 5 additions & 78 deletions pty/src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::{Child, CommandBuilder, MasterPty, PtySize, PtySystem, SlavePty};
use failure::{bail, Error};
use filedescriptor::FileDescriptor;
use libc::{self, winsize};
use std::io;
use std::mem;
Expand Down Expand Up @@ -40,10 +41,10 @@ impl PtySystem for UnixPtySystem {
}

let master = UnixMasterPty {
fd: OwnedFd { fd: master },
fd: unsafe { FileDescriptor::from_raw_fd(master) },
};
let slave = UnixSlavePty {
fd: OwnedFd { fd: slave },
fd: unsafe { FileDescriptor::from_raw_fd(slave) },
};

// Ensure that these descriptors will get closed when we execute
Expand All @@ -57,90 +58,16 @@ impl PtySystem for UnixPtySystem {
}
}

#[derive(Debug)]
pub struct OwnedFd {
fd: RawFd,
}

impl OwnedFd {
fn try_clone(&self) -> Result<Self, Error> {
// Note that linux has a variant of the dup syscall that can set
// the CLOEXEC flag at dup time. We could use that here but the
// additional code complexity isn't worth it: it's just a couple
// of syscalls at startup to do it the portable way below.
let new_fd = unsafe { libc::dup(self.fd) };
if new_fd == -1 {
bail!("dup of pty fd failed: {:?}", io::Error::last_os_error())
}
let new_fd = OwnedFd { fd: new_fd };
cloexec(new_fd.as_raw_fd())?;
Ok(new_fd)
}
}

impl Drop for OwnedFd {
fn drop(&mut self) {
unsafe {
libc::close(self.fd);
}
}
}

impl AsRawFd for OwnedFd {
fn as_raw_fd(&self) -> RawFd {
self.fd
}
}

impl IntoRawFd for OwnedFd {
fn into_raw_fd(self) -> RawFd {
let fd = self.fd;
mem::forget(self);
fd
}
}

impl FromRawFd for OwnedFd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self { fd }
}
}

impl io::Read for OwnedFd {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
let size = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut _, buf.len()) };
if size == -1 {
Err(io::Error::last_os_error())
} else {
Ok(size as usize)
}
}
}

impl io::Write for OwnedFd {
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
let size = unsafe { libc::write(self.fd, buf.as_ptr() as *const _, buf.len()) };
if size == -1 {
Err(io::Error::last_os_error())
} else {
Ok(size as usize)
}
}
fn flush(&mut self) -> Result<(), io::Error> {
Ok(())
}
}

/// Represents the master end of a pty.
/// The file descriptor will be closed when the Pty is dropped.
pub struct UnixMasterPty {
fd: OwnedFd,
fd: FileDescriptor,
}

/// Represents the slave end of a pty.
/// The file descriptor will be closed when the Pty is dropped.
pub struct UnixSlavePty {
fd: OwnedFd,
fd: FileDescriptor,
}

/// Helper function to set the close-on-exec flag for a raw descriptor
Expand Down
46 changes: 22 additions & 24 deletions pty/src/win/conpty.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
use super::ownedhandle::OwnedHandle;
use super::WinChild;
use crate::cmdbuilder::CommandBuilder;
use crate::{Child, MasterPty, PtySize, PtySystem, SlavePty};
use failure::{bail, ensure, Error};
use filedescriptor::{FileDescriptor, OwnedHandle, Pipe};
use lazy_static::lazy_static;
use shared_library::shared_library;
use std::ffi::OsString;
use std::io::{self, Error as IoError};
use std::mem;
use std::os::windows::ffi::OsStringExt;
use std::os::windows::io::{AsRawHandle, FromRawHandle};
use std::os::windows::raw::HANDLE;
use std::path::Path;
use std::ptr;
use std::sync::{Arc, Mutex};
use winapi::shared::minwindef::DWORD;
use winapi::shared::winerror::{HRESULT, S_OK};
use winapi::um::handleapi::*;
use winapi::um::namedpipeapi::CreatePipe;
use winapi::um::processthreadsapi::*;
use winapi::um::winbase::EXTENDED_STARTUPINFO_PRESENT;
use winapi::um::winbase::STARTUPINFOEXW;
Expand All @@ -27,23 +27,23 @@ const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: usize = 0x00020016;
pub struct ConPtySystem {}
impl PtySystem for ConPtySystem {
fn openpty(&self, size: PtySize) -> Result<(Box<MasterPty>, Box<SlavePty>), Error> {
let (stdin_read, stdin_write) = pipe()?;
let (stdout_read, stdout_write) = pipe()?;
let stdin = Pipe::new()?;
let stdout = Pipe::new()?;

let con = PsuedoCon::new(
COORD {
X: size.cols as i16,
Y: size.rows as i16,
},
&stdin_read,
&stdout_write,
&stdin.read,
&stdout.write,
)?;

let master = ConPtyMasterPty {
inner: Arc::new(Mutex::new(Inner {
con,
readable: stdout_read,
writable: stdin_write,
readable: stdout.read,
writable: stdin.write,
size,
})),
};
Expand Down Expand Up @@ -151,10 +151,17 @@ impl Drop for PsuedoCon {
}
}
impl PsuedoCon {
fn new(size: COORD, input: &OwnedHandle, output: &OwnedHandle) -> Result<Self, Error> {
fn new(size: COORD, input: &FileDescriptor, output: &FileDescriptor) -> Result<Self, Error> {
let mut con: HPCON = INVALID_HANDLE_VALUE;
let result =
unsafe { (CONPTY.CreatePseudoConsole)(size, input.handle, output.handle, 0, &mut con) };
let result = unsafe {
(CONPTY.CreatePseudoConsole)(
size,
input.as_raw_handle(),
output.as_raw_handle(),
0,
&mut con,
)
};
ensure!(
result == S_OK,
"failed to create psuedo console: HRESULT {}",
Expand All @@ -177,8 +184,8 @@ impl PsuedoCon {

struct Inner {
con: PsuedoCon,
readable: OwnedHandle,
writable: OwnedHandle,
readable: FileDescriptor,
writable: FileDescriptor,
size: PtySize,
}

Expand Down Expand Up @@ -279,18 +286,9 @@ impl SlavePty for ConPtySlavePty {

// Make sure we close out the thread handle so we don't leak it;
// we do this simply by making it owned
let _main_thread = OwnedHandle::new(pi.hThread);
let proc = OwnedHandle::new(pi.hProcess);
let _main_thread = unsafe { OwnedHandle::from_raw_handle(pi.hThread) };
let proc = unsafe { OwnedHandle::from_raw_handle(pi.hProcess) };

Ok(Box::new(WinChild { proc }))
}
}

fn pipe() -> Result<(OwnedHandle, OwnedHandle), Error> {
let mut read: HANDLE = INVALID_HANDLE_VALUE;
let mut write: HANDLE = INVALID_HANDLE_VALUE;
if unsafe { CreatePipe(&mut read, &mut write, ptr::null_mut(), 0) } == 0 {
bail!("CreatePipe failed: {}", IoError::last_os_error());
}
Ok((OwnedHandle { handle: read }, OwnedHandle { handle: write }))
}
13 changes: 6 additions & 7 deletions pty/src/win/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{Child, ExitStatus};
use std::io::{Error as IoError, Result as IoResult};
use std::os::windows::io::AsRawHandle;
use winapi::shared::minwindef::DWORD;
use winapi::um::minwinbase::STILL_ACTIVE;
use winapi::um::processthreadsapi::*;
Expand All @@ -9,9 +10,7 @@ use winapi::um::winbase::INFINITE;
pub mod conpty;
pub mod winpty;

pub mod ownedhandle;

use ownedhandle::OwnedHandle;
use filedescriptor::OwnedHandle;

#[derive(Debug)]
pub struct WinChild {
Expand All @@ -21,7 +20,7 @@ pub struct WinChild {
impl Child for WinChild {
fn try_wait(&mut self) -> IoResult<Option<ExitStatus>> {
let mut status: DWORD = 0;
let res = unsafe { GetExitCodeProcess(self.proc.handle, &mut status) };
let res = unsafe { GetExitCodeProcess(self.proc.as_raw_handle(), &mut status) };
if res != 0 {
if status == STILL_ACTIVE {
Ok(None)
Expand All @@ -35,7 +34,7 @@ impl Child for WinChild {

fn kill(&mut self) -> IoResult<()> {
unsafe {
TerminateProcess(self.proc.handle, 1);
TerminateProcess(self.proc.as_raw_handle(), 1);
}
self.wait()?;
Ok(())
Expand All @@ -46,10 +45,10 @@ impl Child for WinChild {
return Ok(status);
}
unsafe {
WaitForSingleObject(self.proc.handle, INFINITE);
WaitForSingleObject(self.proc.as_raw_handle(), INFINITE);
}
let mut status: DWORD = 0;
let res = unsafe { GetExitCodeProcess(self.proc.handle, &mut status) };
let res = unsafe { GetExitCodeProcess(self.proc.as_raw_handle(), &mut status) };
if res != 0 {
Ok(ExitStatus::with_exit_code(status))
} else {
Expand Down
96 changes: 0 additions & 96 deletions pty/src/win/ownedhandle.rs

This file was deleted.

6 changes: 3 additions & 3 deletions pty/src/win/winpty/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use super::ownedhandle::OwnedHandle;
use super::WinChild;
use crate::cmdbuilder::CommandBuilder;
use crate::win::winpty::safe::{
AgentFlags, MouseMode, SpawnConfig, SpawnFlags, Timeout, WinPty, WinPtyConfig,
};
use crate::{Child, MasterPty, PtySize, PtySystem, SlavePty};
use failure::{bail, Error};
use filedescriptor::{FileDescriptor};
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use std::path::Path;
Expand All @@ -17,8 +17,8 @@ mod sys;
struct Inner {
pty: WinPty,
size: PtySize,
reader: OwnedHandle,
writer: OwnedHandle,
reader: FileDescriptor,
writer: FileDescriptor,
}

#[derive(Clone)]
Expand Down
Loading

0 comments on commit c562f35

Please sign in to comment.