2018-10-16 17:02:52 +00:00
|
|
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
use std::fs::OpenOptions;
|
|
|
|
use std::os::windows::fs::OpenOptionsExt;
|
2019-03-30 16:48:36 +00:00
|
|
|
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
|
2018-11-24 21:08:02 +00:00
|
|
|
use std::u16;
|
2018-10-16 17:02:52 +00:00
|
|
|
|
|
|
|
use dunce::canonicalize;
|
2019-10-05 00:29:26 +00:00
|
|
|
use log::info;
|
2018-10-16 17:02:52 +00:00
|
|
|
use mio_named_pipes::NamedPipe;
|
2018-12-28 16:01:58 +00:00
|
|
|
use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
|
2019-10-05 00:29:26 +00:00
|
|
|
use winpty::{Config as WinptyConfig, ConfigFlags, MouseMode, SpawnConfig, SpawnFlags, Winpty};
|
2018-10-16 17:02:52 +00:00
|
|
|
|
2019-05-10 11:36:16 +00:00
|
|
|
use crate::config::{Config, Shell};
|
2019-10-05 00:29:26 +00:00
|
|
|
use crate::event::OnResize;
|
2018-12-10 17:53:56 +00:00
|
|
|
use crate::term::SizeInfo;
|
2019-11-16 21:11:56 +00:00
|
|
|
use crate::tty::windows::child::ChildExitWatcher;
|
|
|
|
use crate::tty::windows::Pty;
|
2018-10-16 17:02:52 +00:00
|
|
|
|
2019-12-14 21:32:24 +00:00
|
|
|
pub use winpty::Winpty as Agent;
|
2018-10-16 17:02:52 +00:00
|
|
|
|
2019-12-05 17:14:47 +00:00
|
|
|
pub fn new<C>(config: &Config<C>, size: &SizeInfo, _window_id: Option<usize>) -> Pty {
|
2018-10-16 17:02:52 +00:00
|
|
|
// Create config
|
|
|
|
let mut wconfig = WinptyConfig::new(ConfigFlags::empty()).unwrap();
|
|
|
|
|
|
|
|
wconfig.set_initial_size(size.cols().0 as i32, size.lines().0 as i32);
|
|
|
|
wconfig.set_mouse_mode(&MouseMode::Auto);
|
|
|
|
|
|
|
|
// Start agent
|
2019-12-14 21:32:24 +00:00
|
|
|
let mut agent = Winpty::open(&wconfig).unwrap();
|
|
|
|
let (conin, conout) = (agent.conin_name(), agent.conout_name());
|
2018-10-16 17:02:52 +00:00
|
|
|
|
|
|
|
// Get process commandline
|
2019-01-02 21:40:32 +00:00
|
|
|
let default_shell = &Shell::new("powershell");
|
2019-05-10 11:36:16 +00:00
|
|
|
let shell = config.shell.as_ref().unwrap_or(default_shell);
|
|
|
|
let mut cmdline = shell.args.clone();
|
|
|
|
cmdline.insert(0, shell.program.to_string());
|
2018-10-16 17:02:52 +00:00
|
|
|
|
|
|
|
// Warning, here be borrow hell
|
2019-05-10 11:36:16 +00:00
|
|
|
let cwd = config.working_directory().as_ref().map(|dir| canonicalize(dir).unwrap());
|
2018-10-16 17:02:52 +00:00
|
|
|
let cwd = cwd.as_ref().map(|dir| dir.to_str().unwrap());
|
|
|
|
|
|
|
|
// Spawn process
|
|
|
|
let spawnconfig = SpawnConfig::new(
|
|
|
|
SpawnFlags::AUTO_SHUTDOWN | SpawnFlags::EXIT_AFTER_SHUTDOWN,
|
|
|
|
None, // appname
|
|
|
|
Some(&cmdline.join(" ")),
|
|
|
|
cwd,
|
|
|
|
None, // Env
|
2019-03-30 16:48:36 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
2018-10-16 17:02:52 +00:00
|
|
|
|
|
|
|
let default_opts = &mut OpenOptions::new();
|
2019-03-30 16:48:36 +00:00
|
|
|
default_opts.share_mode(0).custom_flags(FILE_FLAG_OVERLAPPED);
|
2018-10-16 17:02:52 +00:00
|
|
|
|
|
|
|
let (conout_pipe, conin_pipe);
|
|
|
|
unsafe {
|
|
|
|
conout_pipe = NamedPipe::from_raw_handle(
|
2019-03-30 16:48:36 +00:00
|
|
|
default_opts.clone().read(true).open(conout).unwrap().into_raw_handle(),
|
2018-10-16 17:02:52 +00:00
|
|
|
);
|
|
|
|
conin_pipe = NamedPipe::from_raw_handle(
|
2019-03-30 16:48:36 +00:00
|
|
|
default_opts.clone().write(true).open(conin).unwrap().into_raw_handle(),
|
2018-10-16 17:02:52 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2019-12-14 21:32:24 +00:00
|
|
|
agent.spawn(&spawnconfig).unwrap();
|
2018-10-16 17:02:52 +00:00
|
|
|
|
2019-12-14 21:32:24 +00:00
|
|
|
let child_watcher = ChildExitWatcher::new(agent.raw_handle()).unwrap();
|
2018-12-28 16:01:58 +00:00
|
|
|
|
2018-10-16 17:02:52 +00:00
|
|
|
Pty {
|
2019-12-14 21:32:24 +00:00
|
|
|
backend: super::PtyBackend::Winpty(agent),
|
2018-12-28 16:01:58 +00:00
|
|
|
conout: super::EventedReadablePipe::Named(conout_pipe),
|
|
|
|
conin: super::EventedWritablePipe::Named(conin_pipe),
|
2018-10-16 17:02:52 +00:00
|
|
|
read_token: 0.into(),
|
2019-03-30 16:48:36 +00:00
|
|
|
write_token: 0.into(),
|
2019-11-16 21:11:56 +00:00
|
|
|
child_event_token: 0.into(),
|
|
|
|
child_watcher,
|
2018-10-16 17:02:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-14 21:32:24 +00:00
|
|
|
impl OnResize for Agent {
|
2018-10-16 17:02:52 +00:00
|
|
|
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
2018-11-24 21:08:02 +00:00
|
|
|
let (cols, lines) = (sizeinfo.cols().0, sizeinfo.lines().0);
|
|
|
|
if cols > 0 && cols <= u16::MAX as usize && lines > 0 && lines <= u16::MAX as usize {
|
|
|
|
self.set_size(cols as u16, lines as u16)
|
2019-12-29 22:48:27 +00:00
|
|
|
.unwrap_or_else(|_| info!("Unable to set WinPTY size, did it die?"));
|
2018-10-16 17:02:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|