diff --git a/src/main.rs b/src/main.rs index 8ded1a783c..bc35fa2830 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ use syscall::error::EWOULDBLOCK; use syscall::scheme::SchemeMut; mod master; +mod pgrp; mod pty; mod resource; mod scheme; diff --git a/src/pgrp.rs b/src/pgrp.rs new file mode 100644 index 0000000000..56eb16ef9c --- /dev/null +++ b/src/pgrp.rs @@ -0,0 +1,112 @@ +use std::{mem, slice}; +use std::cell::RefCell; +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 PtyPgrp { + pty: Weak>, + flags: usize, +} + +impl PtyPgrp { + pub fn new(pty: Weak>, flags: usize) -> Self { + PtyPgrp { + pty: pty, + flags: flags, + } + } +} + +impl Resource for PtyPgrp { + 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 pgrp: &[u8] = unsafe { + slice::from_raw_parts( + &pty.pgrp as *const usize as *const u8, + mem::size_of::() + ) + }; + + let mut i = 0; + while i < buf.len() && i < pgrp.len() { + buf[i] = pgrp[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 pgrp: &mut [u8] = unsafe { + slice::from_raw_parts_mut( + &mut pty.pgrp as *mut usize as *mut u8, + mem::size_of::() + ) + }; + + let mut i = 0; + while i < buf.len() && i < pgrp.len() { + pgrp[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 + } +} diff --git a/src/pty.rs b/src/pty.rs index 46dd0c9ff9..0d6920baf0 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -5,6 +5,7 @@ use syscall::error::Result; pub struct Pty { pub id: usize, + pub pgrp: usize, pub termios: Termios, pub winsize: Winsize, pub miso: VecDeque>, @@ -15,6 +16,7 @@ impl Pty { pub fn new(id: usize) -> Self { let mut pty = Pty { id: id, + pgrp: 0, termios: Termios::default(), winsize: Winsize::default(), miso: VecDeque::new(), diff --git a/src/scheme.rs b/src/scheme.rs index 4c9a022db1..3609667cbe 100644 --- a/src/scheme.rs +++ b/src/scheme.rs @@ -9,6 +9,7 @@ use syscall::flag::MODE_CHR; use syscall::scheme::SchemeMut; use master::PtyMaster; +use pgrp::PtyPgrp; use pty::Pty; use resource::Resource; use slave::PtySlave; @@ -63,6 +64,8 @@ impl SchemeMut for PtyScheme { if buf.is_empty() { old_handle.boxed_clone() + } else if buf == b"pgrp" { + Box::new(PtyPgrp::new(old_handle.pty(), old_handle.flags())) } else if buf == b"termios" { Box::new(PtyTermios::new(old_handle.pty(), old_handle.flags())) } else if buf == b"winsize" {