1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
use crate::cmdbuilder::CommandBuilder; use crate::win::psuedocon::PsuedoCon; use crate::{Child, MasterPty, PtyPair, PtySize, PtySystem, SlavePty}; use anyhow::Error; use filedescriptor::{FileDescriptor, Pipe}; use std::io; use std::sync::{Arc, Mutex}; use winapi::um::wincon::COORD; #[derive(Default)] pub struct ConPtySystem {} impl PtySystem for ConPtySystem { fn openpty(&self, size: PtySize) -> anyhow::Result<PtyPair> { 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, )?; let master = ConPtyMasterPty { inner: Arc::new(Mutex::new(Inner { con, readable: stdout.read, writable: stdin.write, size, })), }; let slave = ConPtySlavePty { inner: master.inner.clone(), }; Ok(PtyPair { master: Box::new(master), slave: Box::new(slave), }) } } struct Inner { con: PsuedoCon, readable: FileDescriptor, writable: FileDescriptor, size: PtySize, } impl Inner { pub fn resize( &mut self, num_rows: u16, num_cols: u16, pixel_width: u16, pixel_height: u16, ) -> Result<(), Error> { self.con.resize(COORD { X: num_cols as i16, Y: num_rows as i16, })?; self.size = PtySize { rows: num_rows, cols: num_cols, pixel_width, pixel_height, }; Ok(()) } } #[derive(Clone)] pub struct ConPtyMasterPty { inner: Arc<Mutex<Inner>>, } pub struct ConPtySlavePty { inner: Arc<Mutex<Inner>>, } impl MasterPty for ConPtyMasterPty { fn resize(&self, size: PtySize) -> anyhow::Result<()> { let mut inner = self.inner.lock().unwrap(); inner.resize(size.rows, size.cols, size.pixel_width, size.pixel_height) } fn get_size(&self) -> Result<PtySize, Error> { let inner = self.inner.lock().unwrap(); Ok(inner.size.clone()) } fn try_clone_reader(&self) -> anyhow::Result<Box<dyn std::io::Read + Send>> { Ok(Box::new(self.inner.lock().unwrap().readable.try_clone()?)) } fn try_clone_writer(&self) -> anyhow::Result<Box<dyn std::io::Write + Send>> { Ok(Box::new(self.inner.lock().unwrap().writable.try_clone()?)) } } impl io::Write for ConPtyMasterPty { fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> { self.inner.lock().unwrap().writable.write(buf) } fn flush(&mut self) -> Result<(), io::Error> { Ok(()) } } impl SlavePty for ConPtySlavePty { fn spawn_command(&self, cmd: CommandBuilder) -> anyhow::Result<Box<dyn Child + Send>> { let inner = self.inner.lock().unwrap(); let child = inner.con.spawn_command(cmd)?; Ok(Box::new(child)) } }