diff --git a/pty/examples/whoami.rs b/pty/examples/whoami.rs index 0981c16a7..f98f703b7 100644 --- a/pty/examples/whoami.rs +++ b/pty/examples/whoami.rs @@ -2,7 +2,7 @@ //! to print your username. It is made more complex because there are multiple //! pipes involved and it is easy to get blocked/deadlocked if care and attention //! is not paid to those pipes! -use portable_pty::{CommandBuilder, PtySize, PtySystemSelection}; +use portable_pty::{CommandBuilder, NativePtySystem, PtySize, PtySystem}; // Read all available data until we reach EOF or encounter an error // condition. Only returns an error if we didn't receive any data. @@ -22,7 +22,7 @@ fn read_until_eof_or_error(mut r: R) -> std::io::Result Box { + Box::new(NativePtySystem::default()) } -impl PtySystemSelection { - /// Construct an instance of PtySystem described by the enum value. - /// Windows specific enum variants result in an error. - #[cfg(unix)] - pub fn get(self) -> anyhow::Result> { - match self { - PtySystemSelection::Unix => Ok(Box::new(unix::UnixPtySystem {})), - _ => bail!("{:?} not available on unix", self), - } - } - - /// Construct an instance of PtySystem described by the enum value. - /// Unix specific enum variants result in an error. - #[cfg(windows)] - pub fn get(&self) -> anyhow::Result> { - match self { - PtySystemSelection::ConPty => Ok(Box::new(win::conpty::ConPtySystem {})), - PtySystemSelection::WinPty => Ok(Box::new(win::winpty::WinPtySystem {})), - _ => bail!("{:?} not available on Windows", self), - } - } - - /// Returns a list of the variant names. - /// This can be useful for example to specify the list of allowable - /// options in a clap argument specification. - pub fn variants() -> Vec<&'static str> { - vec!["Unix", "ConPty", "WinPty"] - } -} - -/// Parse a string into a `PtySystemSelection` value. -/// This is useful when parsing arguments or configuration files. -impl std::str::FromStr for PtySystemSelection { - type Err = Error; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_ref() { - "unix" => Ok(PtySystemSelection::Unix), - "winpty" => Ok(PtySystemSelection::WinPty), - "conpty" => Ok(PtySystemSelection::ConPty), - _ => Err(anyhow!( - "{} is not a valid PtySystemSelection variant, possible values are {:?}", - s, - PtySystemSelection::variants() - )), - } - } -} - -impl Default for PtySystemSelection { - /// Returns the default, system native PtySystemSelection - fn default() -> PtySystemSelection { - #[cfg(unix)] - return PtySystemSelection::Unix; - #[cfg(windows)] - return PtySystemSelection::ConPty; - } -} +#[cfg(unix)] +pub type NativePtySystem = unix::UnixPtySystem; +#[cfg(windows)] +pub type NativePtySystem = win::conpty::UnixPtySystem; diff --git a/pty/src/unix.rs b/pty/src/unix.rs index 8b5baae86..857ccd1c9 100644 --- a/pty/src/unix.rs +++ b/pty/src/unix.rs @@ -11,7 +11,9 @@ use std::os::unix::process::CommandExt; use std::process::Stdio; use std::ptr; +#[derive(Default)] pub struct UnixPtySystem {} + impl PtySystem for UnixPtySystem { fn openpty(&self, size: PtySize) -> anyhow::Result { let mut master: RawFd = -1; diff --git a/pty/src/win/conpty.rs b/pty/src/win/conpty.rs index 089c4bd87..8c45ed33a 100644 --- a/pty/src/win/conpty.rs +++ b/pty/src/win/conpty.rs @@ -24,7 +24,9 @@ use winapi::um::wincon::COORD; const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: usize = 0x00020016; +#[derive(Default)] pub struct ConPtySystem {} + impl PtySystem for ConPtySystem { fn openpty(&self, size: PtySize) -> anyhow::Result { let stdin = Pipe::new()?; diff --git a/pty/src/win/mod.rs b/pty/src/win/mod.rs index 06f40f319..6bd859a08 100644 --- a/pty/src/win/mod.rs +++ b/pty/src/win/mod.rs @@ -8,7 +8,6 @@ use winapi::um::synchapi::WaitForSingleObject; use winapi::um::winbase::INFINITE; pub mod conpty; -pub mod winpty; use filedescriptor::OwnedHandle; diff --git a/pty/src/win/winpty/mod.rs b/pty/src/win/winpty/mod.rs deleted file mode 100644 index 2b95cf2e5..000000000 --- a/pty/src/win/winpty/mod.rs +++ /dev/null @@ -1,123 +0,0 @@ -use super::WinChild; -use crate::cmdbuilder::CommandBuilder; -use crate::win::winpty::safe::{ - AgentFlags, MouseMode, SpawnConfig, SpawnFlags, Timeout, WinPty, WinPtyConfig, -}; -use crate::{Child, MasterPty, PtyPair, PtySize, PtySystem, SlavePty}; -use anyhow::bail; -use filedescriptor::FileDescriptor; -use log::debug; -use std::ffi::OsString; -use std::os::windows::ffi::OsStringExt; -use std::path::Path; -use std::sync::{Arc, Mutex}; - -mod safe; -mod sys; - -struct Inner { - pty: WinPty, - size: PtySize, - reader: FileDescriptor, - writer: FileDescriptor, -} - -#[derive(Clone)] -pub struct WinPtyMasterPty { - inner: Arc>, -} - -pub struct WinPtySlavePty { - inner: Arc>, -} - -impl MasterPty for WinPtyMasterPty { - fn resize(&self, size: PtySize) -> anyhow::Result<()> { - let mut inner = self.inner.lock().unwrap(); - if inner.pty.set_size(size.cols as i32, size.rows as i32)? { - inner.size = size; - Ok(()) - } else { - bail!("WinPtyMasterPty::resize returned false"); - } - } - - fn get_size(&self) -> anyhow::Result { - Ok(self.inner.lock().unwrap().size) - } - - fn try_clone_reader(&self) -> anyhow::Result> { - Ok(Box::new(self.inner.lock().unwrap().reader.try_clone()?)) - } -} - -impl std::io::Write for WinPtyMasterPty { - fn write(&mut self, buf: &[u8]) -> Result { - self.inner.lock().unwrap().writer.write(buf) - } - fn flush(&mut self) -> Result<(), std::io::Error> { - Ok(()) - } -} - -impl SlavePty for WinPtySlavePty { - fn spawn_command(&self, cmd: CommandBuilder) -> anyhow::Result> { - let (exe, cmdline) = cmd.cmdline()?; - let cmd_os = OsString::from_wide(&cmdline); - debug!( - "Running: module: {} {:?}", - Path::new(&OsString::from_wide(&exe)).display(), - cmd_os - ); - - let spawn_config = SpawnConfig::new( - SpawnFlags::AUTO_SHUTDOWN | SpawnFlags::EXIT_AFTER_SHUTDOWN, - Some(exe), - Some(cmdline), - None, // cwd - None, // env - )?; - - let mut inner = self.inner.lock().unwrap(); - let spawned = inner.pty.spawn(&spawn_config)?; - - let child = WinChild { - proc: spawned.process_handle, - }; - - Ok(Box::new(child)) - } -} - -pub struct WinPtySystem {} -impl PtySystem for WinPtySystem { - fn openpty(&self, size: PtySize) -> anyhow::Result { - let mut config = WinPtyConfig::new(AgentFlags::empty())?; - - config.set_initial_size(size.cols as i32, size.rows as i32); - config.set_mouse_mode(MouseMode::Auto); - config.set_agent_timeout(Timeout::Milliseconds(10_000)); - - let pty = config.open()?; - - let reader = pty.conout()?; - let writer = pty.conin()?; - - let inner = Arc::new(Mutex::new(Inner { - pty, - reader, - writer, - size, - })); - - let master = WinPtyMasterPty { - inner: Arc::clone(&inner), - }; - let slave = WinPtySlavePty { inner }; - - Ok(PtyPair { - master: Box::new(master), - slave: Box::new(slave), - }) - } -} diff --git a/pty/src/win/winpty/safe.rs b/pty/src/win/winpty/safe.rs deleted file mode 100644 index d620738b9..000000000 --- a/pty/src/win/winpty/safe.rs +++ /dev/null @@ -1,280 +0,0 @@ -//! A type-safe wrapper around the sys module, which in turn exposes -//! the API exported by winpty.dll. -//! https://github.com/rprichard/winpty/blob/master/src/include/winpty.h -#![allow(dead_code)] -use super::sys::*; -use anyhow::{anyhow, bail, ensure, Error}; -use bitflags::bitflags; -use filedescriptor::{FileDescriptor, OwnedHandle}; -use std::ffi::{OsStr, OsString}; -use std::os::windows::ffi::{OsStrExt, OsStringExt}; -use std::os::windows::io::FromRawHandle; -use std::ptr; -use winapi::shared::minwindef::DWORD; -use winapi::shared::ntdef::LPCWSTR; -use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING}; -use winapi::um::handleapi::INVALID_HANDLE_VALUE; -use winapi::um::winbase::INFINITE; -use winapi::um::winnt::HANDLE; -use winapi::um::winnt::{GENERIC_READ, GENERIC_WRITE}; - -bitflags! { - pub struct AgentFlags : u64 { - const CONERR = WINPTY_FLAG_CONERR; - const PLAIN_OUTPUT = WINPTY_FLAG_PLAIN_OUTPUT; - const COLOR_ESCAPES = WINPTY_FLAG_COLOR_ESCAPES; - const ALLOW_DESKTOP_CREATE = WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION; - } -} -bitflags! { - pub struct SpawnFlags : u64 { - const AUTO_SHUTDOWN = WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN; - const EXIT_AFTER_SHUTDOWN = WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN; - } -} - -#[repr(u32)] -pub enum MouseMode { - None = WINPTY_MOUSE_MODE_NONE, - Auto = WINPTY_MOUSE_MODE_AUTO, - Force = WINPTY_MOUSE_MODE_FORCE, -} - -pub enum Timeout { - Infinite, - Milliseconds(DWORD), -} - -pub struct WinPtyConfig { - config: *mut winpty_config_t, -} - -fn wstr_to_osstr(wstr: LPCWSTR) -> Result { - ensure!(!wstr.is_null(), "LPCWSTR is null"); - let slice = unsafe { std::slice::from_raw_parts(wstr, libc::wcslen(wstr)) }; - Ok(OsString::from_wide(slice)) -} - -fn wstr_to_string(wstr: LPCWSTR) -> Result { - ensure!(!wstr.is_null(), "LPCWSTR is null"); - let slice = unsafe { std::slice::from_raw_parts(wstr, libc::wcslen(wstr)) }; - String::from_utf16(slice).map_err(|e| anyhow!("String::from_utf16: {}", e)) -} - -fn check_err(err: winpty_error_ptr_t, value: T) -> Result { - if err.is_null() { - return Ok(value); - } - unsafe { - let code = (WINPTY.winpty_error_code)(err); - if code == WINPTY_ERROR_SUCCESS { - return Ok(value); - } - - let converted = wstr_to_string((WINPTY.winpty_error_msg)(err))?; - (WINPTY.winpty_error_free)(err); - bail!("winpty error code {}: {}", code, converted) - } -} - -impl WinPtyConfig { - pub fn new(flags: AgentFlags) -> Result { - let mut err: winpty_error_ptr_t = ptr::null_mut(); - let config = unsafe { (WINPTY.winpty_config_new)(flags.bits(), &mut err) }; - let config = check_err(err, config)?; - ensure!( - !config.is_null(), - "winpty_config_new returned nullptr but no error" - ); - Ok(Self { config }) - } - - pub fn set_initial_size(&mut self, cols: c_int, rows: c_int) { - unsafe { (WINPTY.winpty_config_set_initial_size)(self.config, cols, rows) } - } - - pub fn set_mouse_mode(&mut self, mode: MouseMode) { - unsafe { (WINPTY.winpty_config_set_mouse_mode)(self.config, mode as c_int) } - } - - pub fn set_agent_timeout(&mut self, timeout: Timeout) { - let duration = match timeout { - Timeout::Infinite => INFINITE, - Timeout::Milliseconds(n) => n, - }; - unsafe { (WINPTY.winpty_config_set_agent_timeout)(self.config, duration) } - } - - pub fn open(&self) -> Result { - let mut err: winpty_error_ptr_t = ptr::null_mut(); - let pty = unsafe { (WINPTY.winpty_open)(self.config, &mut err) }; - let pty = check_err(err, pty)?; - ensure!(!pty.is_null(), "winpty_open returned nullptr but no error"); - Ok(WinPty { pty }) - } -} - -impl Drop for WinPtyConfig { - fn drop(&mut self) { - unsafe { (WINPTY.winpty_config_free)(self.config) } - } -} - -pub struct WinPty { - pty: *mut winpty_t, -} - -impl Drop for WinPty { - fn drop(&mut self) { - unsafe { (WINPTY.winpty_free)(self.pty) } - } -} - -fn pipe_client(name: LPCWSTR, for_read: bool) -> Result { - let handle = unsafe { - CreateFileW( - name, - if for_read { - GENERIC_READ - } else { - GENERIC_WRITE - }, - 0, - ptr::null_mut(), - OPEN_EXISTING, - 0, - ptr::null_mut(), - ) - }; - if handle == INVALID_HANDLE_VALUE { - let err = std::io::Error::last_os_error(); - bail!("failed to open {:?}: {}", wstr_to_string(name), err); - } else { - Ok(unsafe { FileDescriptor::from_raw_handle(handle) }) - } -} - -impl WinPty { - pub fn agent_process(&self) -> HANDLE { - unsafe { (WINPTY.winpty_agent_process)(self.pty) } - } - - pub fn conin(&self) -> Result { - pipe_client(unsafe { (WINPTY.winpty_conin_name)(self.pty) }, false) - } - - pub fn conout(&self) -> Result { - pipe_client(unsafe { (WINPTY.winpty_conout_name)(self.pty) }, true) - } - - pub fn conerr(&self) -> Result { - pipe_client(unsafe { (WINPTY.winpty_conerr_name)(self.pty) }, true) - } - - pub fn set_size(&mut self, cols: c_int, rows: c_int) -> Result { - let mut err: winpty_error_ptr_t = ptr::null_mut(); - let result = unsafe { (WINPTY.winpty_set_size)(self.pty, cols, rows, &mut err) }; - Ok(result != 0) - } - - pub fn spawn(&mut self, config: &SpawnConfig) -> Result { - let mut err: winpty_error_ptr_t = ptr::null_mut(); - let mut create_process_error: DWORD = 0; - let mut process_handle: HANDLE = ptr::null_mut(); - let mut thread_handle: HANDLE = ptr::null_mut(); - - let result = unsafe { - (WINPTY.winpty_spawn)( - self.pty, - config.spawn_config, - &mut process_handle, - &mut thread_handle, - &mut create_process_error, - &mut err, - ) - }; - let thread_handle = unsafe { OwnedHandle::from_raw_handle(thread_handle) }; - let process_handle = unsafe { OwnedHandle::from_raw_handle(process_handle) }; - let result = check_err(err, result)?; - if result == 0 { - let err = std::io::Error::from_raw_os_error(create_process_error as _); - bail!("winpty_spawn failed: {}", err); - } - Ok(SpawnedProcess { - thread_handle, - process_handle, - }) - } -} - -pub struct SpawnedProcess { - pub process_handle: OwnedHandle, - pub thread_handle: OwnedHandle, -} - -pub struct SpawnConfig { - spawn_config: *mut winpty_spawn_config_t, -} - -/// Construct a null terminated wide string from an OsStr -fn str_to_wide(s: &OsStr) -> Vec { - let mut wide: Vec = s.encode_wide().collect(); - wide.push(0); - wide -} - -fn str_ptr(s: &Option>) -> LPCWSTR { - match s { - None => ptr::null(), - Some(v) => v.as_ptr(), - } -} - -impl SpawnConfig { - pub fn with_os_str_args( - flags: SpawnFlags, - appname: Option<&OsStr>, - cmdline: Option<&OsStr>, - cwd: Option<&OsStr>, - env: Option<&OsStr>, - ) -> Result { - let appname = appname.map(str_to_wide); - let cmdline = cmdline.map(str_to_wide); - let cwd = cwd.map(str_to_wide); - let env = env.map(str_to_wide); - Self::new(flags, appname, cmdline, cwd, env) - } - - pub fn new( - flags: SpawnFlags, - appname: Option>, - cmdline: Option>, - cwd: Option>, - env: Option>, - ) -> Result { - let mut err: winpty_error_ptr_t = ptr::null_mut(); - - let spawn_config = unsafe { - (WINPTY.winpty_spawn_config_new)( - flags.bits(), - str_ptr(&appname), - str_ptr(&cmdline), - str_ptr(&cwd), - str_ptr(&env), - &mut err, - ) - }; - let spawn_config = check_err(err, spawn_config)?; - ensure!( - !spawn_config.is_null(), - "winpty_spawn_config_new returned nullptr but no error" - ); - Ok(Self { spawn_config }) - } -} - -impl Drop for SpawnConfig { - fn drop(&mut self) { - unsafe { (WINPTY.winpty_spawn_config_free)(self.spawn_config) } - } -} diff --git a/pty/src/win/winpty/sys.rs b/pty/src/win/winpty/sys.rs deleted file mode 100644 index ce63a4cbd..000000000 --- a/pty/src/win/winpty/sys.rs +++ /dev/null @@ -1,110 +0,0 @@ -//! A rust wrapper around winpty.dll -//! https://github.com/rprichard/winpty/blob/master/src/include/winpty.h -//! This was partially generated by bindgen and then tweaked to work -//! with the shared_library macro. -#![allow(dead_code)] -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] - -use lazy_static::lazy_static; -use shared_library::shared_library; -use std::path::Path; -use winapi::shared::minwindef::{BOOL, DWORD}; -use winapi::shared::ntdef::LPCWSTR; -use winapi::um::winnt::HANDLE; - -pub use ::std::os::raw::c_int; - -pub const WINPTY_ERROR_SUCCESS: u32 = 0; -pub const WINPTY_ERROR_OUT_OF_MEMORY: u32 = 1; -pub const WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED: u32 = 2; -pub const WINPTY_ERROR_LOST_CONNECTION: u32 = 3; -pub const WINPTY_ERROR_AGENT_EXE_MISSING: u32 = 4; -pub const WINPTY_ERROR_UNSPECIFIED: u32 = 5; -pub const WINPTY_ERROR_AGENT_DIED: u32 = 6; -pub const WINPTY_ERROR_AGENT_TIMEOUT: u32 = 7; -pub const WINPTY_ERROR_AGENT_CREATION_FAILED: u32 = 8; -pub const WINPTY_FLAG_CONERR: u64 = 1; -pub const WINPTY_FLAG_PLAIN_OUTPUT: u64 = 2; -pub const WINPTY_FLAG_COLOR_ESCAPES: u64 = 4; -pub const WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION: u64 = 8; -pub const WINPTY_MOUSE_MODE_NONE: u32 = 0; -pub const WINPTY_MOUSE_MODE_AUTO: u32 = 1; -pub const WINPTY_MOUSE_MODE_FORCE: u32 = 2; -pub const WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN: u64 = 1; -pub const WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN: u64 = 2; - -pub struct winpty_error_t {} -pub struct winpty_t {} -pub struct winpty_spawn_config_t {} -pub struct winpty_config_t {} - -pub type winpty_error_ptr_t = *mut winpty_error_t; -pub type winpty_result_t = DWORD; - -shared_library!(WinPtyFuncs, - pub fn winpty_error_code(err: winpty_error_ptr_t) -> winpty_result_t, - pub fn winpty_error_msg(err: winpty_error_ptr_t) -> LPCWSTR, - pub fn winpty_error_free(err: winpty_error_ptr_t), - pub fn winpty_config_new( - agentFlags: u64, - err: *mut winpty_error_ptr_t - ) -> *mut winpty_config_t, - pub fn winpty_config_free(cfg: *mut winpty_config_t), - pub fn winpty_config_set_initial_size( - cfg: *mut winpty_config_t, - cols: c_int, - rows: c_int - ), - pub fn winpty_config_set_mouse_mode( - cfg: *mut winpty_config_t, - mouseMode: c_int - ), - pub fn winpty_config_set_agent_timeout( - cfg: *mut winpty_config_t, - timeoutMs: DWORD - ), - pub fn winpty_open(cfg: *const winpty_config_t, err: *mut winpty_error_ptr_t) -> *mut winpty_t, - pub fn winpty_agent_process(wp: *mut winpty_t) -> HANDLE, - pub fn winpty_conin_name(wp: *mut winpty_t) -> LPCWSTR, - pub fn winpty_conout_name(wp: *mut winpty_t) -> LPCWSTR, - pub fn winpty_conerr_name(wp: *mut winpty_t) -> LPCWSTR, - pub fn winpty_spawn_config_new( - spawnFlags: u64, - appname: LPCWSTR, - cmdline: LPCWSTR, - cwd: LPCWSTR, - env: LPCWSTR, - err: *mut winpty_error_ptr_t - ) -> *mut winpty_spawn_config_t, - pub fn winpty_spawn_config_free(cfg: *mut winpty_spawn_config_t), - pub fn winpty_spawn( - wp: *mut winpty_t, - cfg: *const winpty_spawn_config_t, - process_handle: *mut HANDLE, - thread_handle: *mut HANDLE, - create_process_error: *mut DWORD, - err: *mut winpty_error_ptr_t - ) -> BOOL, - pub fn winpty_set_size( - wp: *mut winpty_t, - cols: c_int, - rows: c_int, - err: *mut winpty_error_ptr_t - ) -> BOOL, - /* - pub fn winpty_get_console_process_list( - wp: *mut winpty_t, - processList: *mut c_int, - processCount: c_int, - err: *mut winpty_error_ptr_t - ) -> c_int, - */ - pub fn winpty_free(wp: *mut winpty_t), -); - -lazy_static! { - pub static ref WINPTY: WinPtyFuncs = - WinPtyFuncs::open(Path::new("winpty.dll")).expect("winpty.dll is required"); -} diff --git a/src/config/mod.rs b/src/config/mod.rs index bfa3e39ca..6b83ef7f5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -8,7 +8,7 @@ use crate::frontend::FrontEndSelection; use crate::keyassignment::KeyAssignment; use anyhow::{anyhow, bail, Context, Error}; use lazy_static::lazy_static; -use portable_pty::{CommandBuilder, PtySystemSelection}; +use portable_pty::CommandBuilder; use serde::Deserialize; use std; use std::collections::HashMap; @@ -357,9 +357,6 @@ pub struct Config { #[serde(default)] pub front_end: FrontEndSelection, - #[serde(default)] - pub pty: PtySystemSelection, - /// The set of unix domains #[serde(default = "UnixDomain::default_unix_domains")] pub unix_domains: Vec, diff --git a/src/mux/domain.rs b/src/mux/domain.rs index f014975a4..bdaac5a6a 100644 --- a/src/mux/domain.rs +++ b/src/mux/domain.rs @@ -14,8 +14,7 @@ use anyhow::{bail, Error}; use async_trait::async_trait; use downcast_rs::{impl_downcast, Downcast}; use log::info; -use portable_pty::cmdbuilder::CommandBuilder; -use portable_pty::{PtySize, PtySystem}; +use portable_pty::{native_pty_system, CommandBuilder, PtySize, PtySystem}; use std::rc::Rc; static DOMAIN_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0); @@ -68,8 +67,7 @@ pub struct LocalDomain { impl LocalDomain { pub fn new(name: &str) -> Result { - let pty_system = configuration().pty.get()?; - Ok(Self::with_pty_system(name, pty_system)) + Ok(Self::with_pty_system(name, native_pty_system())) } pub fn with_pty_system(name: &str, pty_system: Box) -> Self { diff --git a/src/server/client.rs b/src/server/client.rs index d16d6e013..7c83a038a 100644 --- a/src/server/client.rs +++ b/src/server/client.rs @@ -12,6 +12,7 @@ use anyhow::{anyhow, bail, Context, Error}; use crossbeam_channel::TryRecvError; use filedescriptor::{pollfd, AsRawSocketDescriptor}; use log::info; +use portable_pty::{CommandBuilder, NativePtySystem, PtySystem}; use promise::{Future, Promise}; use std::collections::HashMap; use std::io::{Read, Write}; @@ -371,9 +372,9 @@ impl Reconnectable { // conhost.exe, `wsl.exe` will fail to start up correctly. // This also has a nice side effect of not flashing up a // console window when we first spin up the wsl instance. - let pty_system = portable_pty::PtySystemSelection::default().get()?; + let pty_system = NativePtySystem::default(); let pair = pty_system.openpty(Default::default())?; - let mut cmd = portable_pty::CommandBuilder::new(&argv[0]); + let mut cmd = CommandBuilder::new(&argv[0]); cmd.args(&argv[1..]); let mut child = pair.slave.spawn_command(cmd)?; let status = child.wait()?;