From f03eaa8c24d86b686c7f655bb408cd0cc8fc5ba4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 23 Jul 2017 11:10:34 -0600 Subject: [PATCH] Add window size --- src/main.rs | 1 + src/pty.rs | 2 + src/scheme.rs | 5 ++- src/winsize.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 src/winsize.rs diff --git a/src/main.rs b/src/main.rs index d31023ccd8..8ded1a783c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ mod resource; mod scheme; mod slave; mod termios; +mod winsize; use scheme::PtyScheme; diff --git a/src/pty.rs b/src/pty.rs index 13a8ddbe56..46dd0c9ff9 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -6,6 +6,7 @@ use syscall::error::Result; pub struct Pty { pub id: usize, pub termios: Termios, + pub winsize: Winsize, pub miso: VecDeque>, pub mosi: VecDeque, } @@ -15,6 +16,7 @@ impl Pty { let mut pty = Pty { id: id, termios: Termios::default(), + winsize: Winsize::default(), miso: VecDeque::new(), mosi: VecDeque::new() }; diff --git a/src/scheme.rs b/src/scheme.rs index 8d5dee1fbb..4c9a022db1 100644 --- a/src/scheme.rs +++ b/src/scheme.rs @@ -13,6 +13,7 @@ use pty::Pty; use resource::Resource; use slave::PtySlave; use termios::PtyTermios; +use winsize::PtyWinsize; pub struct PtyScheme { next_id: usize, @@ -57,13 +58,15 @@ impl SchemeMut for PtyScheme { } fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result { - let handle = { + let handle: Box = { let old_handle = self.handles.get(&old_id).ok_or(Error::new(EBADF))?; if buf.is_empty() { old_handle.boxed_clone() } else if buf == b"termios" { Box::new(PtyTermios::new(old_handle.pty(), old_handle.flags())) + } else if buf == b"winsize" { + Box::new(PtyWinsize::new(old_handle.pty(), old_handle.flags())) } else { return Err(Error::new(EINVAL)); } diff --git a/src/winsize.rs b/src/winsize.rs new file mode 100644 index 0000000000..a44a07ce50 --- /dev/null +++ b/src/winsize.rs @@ -0,0 +1,102 @@ +use std::cell::RefCell; +use std::ops::{Deref, DerefMut}; +use std::rc::Weak; + +use syscall::error::{Error, Result, EBADF, EINVAL, EPIPE}; +use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE}; + +use pty::Pty; +use resource::Resource; + +/// Read side of a pipe +#[derive(Clone)] +pub struct PtyWinsize { + pty: Weak>, + flags: usize, +} + +impl PtyWinsize { + pub fn new(pty: Weak>, flags: usize) -> Self { + PtyWinsize { + pty: pty, + flags: flags, + } + } +} + +impl Resource for PtyWinsize { + fn boxed_clone(&self) -> Box { + Box::new(self.clone()) + } + + fn pty(&self) -> Weak> { + self.pty.clone() + } + + fn flags(&self) -> usize { + self.flags + } + + fn path(&self, buf: &mut [u8]) -> Result { + if let Some(pty_lock) = self.pty.upgrade() { + pty_lock.borrow_mut().path(buf) + } else { + Err(Error::new(EPIPE)) + } + } + + fn read(&self, buf: &mut [u8]) -> Result { + if let Some(pty_lock) = self.pty.upgrade() { + let pty = pty_lock.borrow(); + let winsize: &[u8] = pty.winsize.deref(); + + let mut i = 0; + while i < buf.len() && i < winsize.len() { + buf[i] = winsize[i]; + i += 1; + } + Ok(i) + } else { + Ok(0) + } + } + + fn write(&self, buf: &[u8]) -> Result { + if let Some(pty_lock) = self.pty.upgrade() { + let mut pty = pty_lock.borrow_mut(); + let winsize: &mut [u8] = pty.winsize.deref_mut(); + + let mut i = 0; + while i < buf.len() && i < winsize.len() { + winsize[i] = buf[i]; + i += 1; + } + Ok(i) + } else { + Err(Error::new(EPIPE)) + } + } + + fn sync(&self) -> Result { + Ok(0) + } + + fn fcntl(&mut self, cmd: usize, arg: usize) -> Result { + match cmd { + F_GETFL => Ok(self.flags), + F_SETFL => { + self.flags = (self.flags & O_ACCMODE) | (arg & ! O_ACCMODE); + Ok(0) + }, + _ => Err(Error::new(EINVAL)) + } + } + + fn fevent(&self) -> Result<()> { + Err(Error::new(EBADF)) + } + + fn fevent_count(&self) -> Option { + None + } +}