1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 15:04:36 +03:00

pty: remove conpty support

It's too fiddly to setup in practice, and literally no one has
expressed an interest in using it.

Removing it simplifies some upcoming work.

Closes: https://github.com/wez/wezterm/issues/35
This commit is contained in:
Wez Furlong 2020-01-19 17:32:33 -08:00
parent ec082bec31
commit 82c824f371
11 changed files with 22 additions and 604 deletions

View File

@ -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<R: std::io::Read>(mut r: R) -> std::io::Result<Vec<u8
}
fn main() {
let pty_system = PtySystemSelection::default().get().unwrap();
let pty_system = NativePtySystem::default();
let pair = pty_system
.openpty(PtySize {

View File

@ -2,15 +2,15 @@
//! psuedo terminal (pty) interfaces provided by the system.
//! Unlike other crates in this space, this crate provides a set
//! of traits that allow selecting from different implementations
//! at runtime, which is important on Windows systems.
//! at runtime.
//! This crate is part of [wezterm](https://github.com/wez/wezterm).
//!
//! ```no_run
//! use portable_pty::{CommandBuilder, PtySize, PtySystemSelection};
//! use portable_pty::{CommandBuilder, PtySize, native_pty_system, PtySystem};
//! use anyhow::Error;
//!
//! // Use the native pty implementation for the system
//! let pty_system = PtySystemSelection::default().get()?;
//! let pty_system = native_pty_system();
//!
//! // Create a new pty
//! let mut pair = pty_system.openpty(PtySize {
@ -43,7 +43,7 @@
//! `ssh::SshSession` type that can wrap an established ssh
//! session with an implementation of `PtySystem`, allowing
//! you to use the same pty interface with remote ptys.
use anyhow::{anyhow, bail, Error};
use anyhow::Error;
#[cfg(feature = "serde_support")]
use serde_derive::*;
use std::io::Result as IoResult;
@ -186,79 +186,11 @@ impl Child for std::process::Child {
}
}
/// `PtySystemSelection` allows selecting and constructing one of the
/// pty implementations provided by this crate.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde_support", derive(Deserialize))]
pub enum PtySystemSelection {
/// The Unix style pty interface
Unix,
/// The Windows 10+ native Console Pty interface
ConPty,
/// rprichard's WinPty interface to cygwin and msys pty.
/// This requires that `winpty.dll` be resolvable by the
/// embedding application. Instructions on obtaining
/// an appropriate implementation of `winpty.dll` can be
/// found here:
/// [winpty](https://github.com/rprichard/winpty)
WinPty,
pub fn native_pty_system() -> Box<dyn PtySystem> {
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<Box<dyn PtySystem>> {
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<Box<dyn PtySystem>> {
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<Self, Self::Err> {
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;

View File

@ -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<PtyPair> {
let mut master: RawFd = -1;

View File

@ -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<PtyPair> {
let stdin = Pipe::new()?;

View File

@ -8,7 +8,6 @@ use winapi::um::synchapi::WaitForSingleObject;
use winapi::um::winbase::INFINITE;
pub mod conpty;
pub mod winpty;
use filedescriptor::OwnedHandle;

View File

@ -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<Mutex<Inner>>,
}
pub struct WinPtySlavePty {
inner: Arc<Mutex<Inner>>,
}
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<PtySize> {
Ok(self.inner.lock().unwrap().size)
}
fn try_clone_reader(&self) -> anyhow::Result<Box<dyn std::io::Read + Send>> {
Ok(Box::new(self.inner.lock().unwrap().reader.try_clone()?))
}
}
impl std::io::Write for WinPtyMasterPty {
fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
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<Box<dyn Child>> {
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<PtyPair> {
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),
})
}
}

View File

@ -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<OsString, Error> {
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<String, Error> {
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<T>(err: winpty_error_ptr_t, value: T) -> Result<T, Error> {
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<Self, Error> {
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<WinPty, Error> {
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<FileDescriptor, Error> {
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<FileDescriptor, Error> {
pipe_client(unsafe { (WINPTY.winpty_conin_name)(self.pty) }, false)
}
pub fn conout(&self) -> Result<FileDescriptor, Error> {
pipe_client(unsafe { (WINPTY.winpty_conout_name)(self.pty) }, true)
}
pub fn conerr(&self) -> Result<FileDescriptor, Error> {
pipe_client(unsafe { (WINPTY.winpty_conerr_name)(self.pty) }, true)
}
pub fn set_size(&mut self, cols: c_int, rows: c_int) -> Result<bool, Error> {
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<SpawnedProcess, Error> {
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<u16> {
let mut wide: Vec<u16> = s.encode_wide().collect();
wide.push(0);
wide
}
fn str_ptr(s: &Option<Vec<u16>>) -> 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<Self, Error> {
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<Vec<u16>>,
cmdline: Option<Vec<u16>>,
cwd: Option<Vec<u16>>,
env: Option<Vec<u16>>,
) -> Result<Self, Error> {
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) }
}
}

View File

@ -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");
}

View File

@ -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<UnixDomain>,

View File

@ -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<Self, Error> {
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<dyn PtySystem>) -> Self {

View File

@ -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()?;