Use termios crate (WIP)
This commit is contained in:
+20
-369
@@ -1,327 +1,22 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate redox_termios;
|
||||
extern crate syscall;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::str;
|
||||
|
||||
use syscall::data::{Packet, Stat};
|
||||
use syscall::error::{Error, Result, EBADF, EINVAL, ENOENT, EPIPE, EWOULDBLOCK};
|
||||
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK, MODE_CHR};
|
||||
use syscall::data::Packet;
|
||||
use syscall::error::EWOULDBLOCK;
|
||||
use syscall::scheme::SchemeMut;
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Handle {
|
||||
Master(PtyMaster),
|
||||
Slave(PtySlave),
|
||||
}
|
||||
mod master;
|
||||
mod pty;
|
||||
mod resource;
|
||||
mod scheme;
|
||||
mod slave;
|
||||
|
||||
pub struct PtyScheme {
|
||||
next_id: usize,
|
||||
handles: BTreeMap<usize, Handle>,
|
||||
}
|
||||
|
||||
impl PtyScheme {
|
||||
fn new() -> Self {
|
||||
PtyScheme {
|
||||
next_id: 0,
|
||||
handles: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_handle(&self, id: usize) -> Option<Handle> {
|
||||
self.handles.get(&id).map(|handle| handle.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeMut for PtyScheme {
|
||||
fn open(&mut self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path = str::from_utf8(path).or(Err(Error::new(EINVAL)))?.trim_matches('/');
|
||||
|
||||
if path.is_empty() {
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
|
||||
self.handles.insert(id, Handle::Master(PtyMaster::new(id, flags)));
|
||||
|
||||
Ok(id)
|
||||
} else {
|
||||
let master_id = path.parse::<usize>().or(Err(Error::new(EINVAL)))?;
|
||||
let handle = self.get_handle(master_id).ok_or(Error::new(ENOENT))?;
|
||||
if let Handle::Master(master) = handle {
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
|
||||
self.handles.insert(id, Handle::Slave(PtySlave::new(&master, flags)));
|
||||
|
||||
Ok(id)
|
||||
} else {
|
||||
Err(Error::new(ENOENT))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result<usize> {
|
||||
if ! buf.is_empty() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
let handle = self.get_handle(old_id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
self.handles.insert(id, handle);
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let handle = self.get_handle(id).ok_or(Error::new(EBADF))?;
|
||||
match handle {
|
||||
Handle::Master(master) => master.read(buf),
|
||||
Handle::Slave(slave) => slave.read(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
|
||||
let handle = self.get_handle(id).ok_or(Error::new(EBADF))?;
|
||||
match handle {
|
||||
Handle::Master(master) => master.write(buf),
|
||||
Handle::Slave(slave) => slave.write(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
match self.handles.get_mut(&id) {
|
||||
Some(mut handle) => match *handle {
|
||||
Handle::Master(ref mut master) => master.fcntl(cmd, arg),
|
||||
Handle::Slave(ref mut slave) => slave.fcntl(cmd, arg),
|
||||
},
|
||||
None => Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
|
||||
fn fevent(&mut self, id: usize, _flags: usize) -> Result<usize> {
|
||||
let handle = self.get_handle(id).ok_or(Error::new(EBADF))?;
|
||||
match handle {
|
||||
Handle::Master(_master) => Ok(id),
|
||||
Handle::Slave(_slave) => Ok(id),
|
||||
}
|
||||
}
|
||||
|
||||
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let handle = self.get_handle(id).ok_or(Error::new(EBADF))?;
|
||||
match handle {
|
||||
Handle::Master(master) => master.path(buf),
|
||||
Handle::Slave(slave) => slave.path(buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<usize> {
|
||||
let _handle = self.get_handle(id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
*stat = Stat {
|
||||
st_mode: MODE_CHR | 0o666,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn fsync(&mut self, id: usize) -> Result<usize> {
|
||||
let handle = self.get_handle(id).ok_or(Error::new(EBADF))?;
|
||||
match handle {
|
||||
Handle::Master(_master) => Ok(0),
|
||||
Handle::Slave(slave) => slave.sync(),
|
||||
}
|
||||
}
|
||||
|
||||
fn close(&mut self, id: usize) -> Result<usize> {
|
||||
drop(self.handles.remove(&id));
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pty {
|
||||
id: usize,
|
||||
miso: VecDeque<Vec<u8>>,
|
||||
mosi: VecDeque<u8>,
|
||||
}
|
||||
|
||||
impl Pty {
|
||||
pub fn new(id: usize) -> Self {
|
||||
Pty {
|
||||
id: id,
|
||||
miso: VecDeque::new(),
|
||||
mosi: VecDeque::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let path_str = format!("pty:{}", self.id);
|
||||
let path = path_str.as_bytes();
|
||||
|
||||
let mut i = 0;
|
||||
while i < buf.len() && i < path.len() {
|
||||
buf[i] = path[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read side of a pipe
|
||||
#[derive(Clone)]
|
||||
pub struct PtyMaster {
|
||||
pty: Rc<RefCell<Pty>>,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PtyMaster {
|
||||
pub fn new(id: usize, flags: usize) -> Self {
|
||||
PtyMaster {
|
||||
pty: Rc::new(RefCell::new(Pty::new(id))),
|
||||
flags: flags,
|
||||
}
|
||||
}
|
||||
|
||||
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
self.pty.borrow_mut().path(buf)
|
||||
}
|
||||
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut pty = self.pty.borrow_mut();
|
||||
|
||||
if let Some(packet) = pty.miso.pop_front() {
|
||||
let mut i = 0;
|
||||
|
||||
while i < buf.len() && i < packet.len() {
|
||||
buf[i] = packet[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Ok(i)
|
||||
} else if self.flags & O_NONBLOCK == O_NONBLOCK || Rc::weak_count(&self.pty) == 0 {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let mut pty = self.pty.borrow_mut();
|
||||
|
||||
let mut i = 0;
|
||||
while i < buf.len() {
|
||||
pty.mosi.push_back(buf[i]);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
|
||||
match cmd {
|
||||
F_GETFL => Ok(self.flags),
|
||||
F_SETFL => {
|
||||
self.flags = (self.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
|
||||
Ok(0)
|
||||
},
|
||||
_ => Err(Error::new(EINVAL))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read side of a pipe
|
||||
#[derive(Clone)]
|
||||
pub struct PtySlave {
|
||||
pty: Weak<RefCell<Pty>>,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PtySlave {
|
||||
pub fn new(master: &PtyMaster, flags: usize) -> Self {
|
||||
PtySlave {
|
||||
pty: Rc::downgrade(&master.pty),
|
||||
flags: flags,
|
||||
}
|
||||
}
|
||||
|
||||
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
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<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let mut pty = pty_lock.borrow_mut();
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while i < buf.len() && ! pty.mosi.is_empty() {
|
||||
buf[i] = pty.mosi.pop_front().unwrap();
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if i > 0 || self.flags & O_NONBLOCK == O_NONBLOCK {
|
||||
Ok(i)
|
||||
} else {
|
||||
Err(Error::new(EWOULDBLOCK))
|
||||
}
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let mut vec = Vec::new();
|
||||
vec.push(0);
|
||||
vec.extend_from_slice(buf);
|
||||
|
||||
let mut pty = pty_lock.borrow_mut();
|
||||
pty.miso.push_back(vec);
|
||||
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
Err(Error::new(EPIPE))
|
||||
}
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let mut vec = Vec::new();
|
||||
vec.push(1);
|
||||
|
||||
let mut pty = pty_lock.borrow_mut();
|
||||
pty.miso.push_back(vec);
|
||||
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EPIPE))
|
||||
}
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
|
||||
match cmd {
|
||||
F_GETFL => Ok(self.flags),
|
||||
F_SETFL => {
|
||||
self.flags = (self.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
|
||||
Ok(0)
|
||||
},
|
||||
_ => Err(Error::new(EINVAL))
|
||||
}
|
||||
}
|
||||
}
|
||||
use scheme::PtyScheme;
|
||||
|
||||
fn main(){
|
||||
// Daemonize
|
||||
@@ -356,61 +51,17 @@ fn main(){
|
||||
}
|
||||
|
||||
for (id, handle) in scheme.handles.iter() {
|
||||
match *handle {
|
||||
Handle::Master(ref master) => {
|
||||
let pty = master.pty.borrow();
|
||||
if let Some(data) = pty.miso.front() {
|
||||
socket.write(&Packet {
|
||||
id: 0,
|
||||
pid: 0,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
a: syscall::number::SYS_FEVENT,
|
||||
b: *id,
|
||||
c: syscall::flag::EVENT_READ,
|
||||
d: data.len()
|
||||
}).expect("pty: failed to write event");
|
||||
} else if Rc::weak_count(&master.pty) == 0 {
|
||||
socket.write(&Packet {
|
||||
id: 0,
|
||||
pid: 0,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
a: syscall::number::SYS_FEVENT,
|
||||
b: *id,
|
||||
c: syscall::flag::EVENT_READ,
|
||||
d: 0
|
||||
}).expect("pty: failed to write event");
|
||||
}
|
||||
},
|
||||
Handle::Slave(ref slave) => {
|
||||
if let Some(pty_lock) = slave.pty.upgrade() {
|
||||
let pty = pty_lock.borrow();
|
||||
if ! pty.mosi.is_empty() {
|
||||
socket.write(&Packet {
|
||||
id: 0,
|
||||
pid: 0,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
a: syscall::number::SYS_FEVENT,
|
||||
b: *id,
|
||||
c: syscall::flag::EVENT_READ,
|
||||
d: pty.mosi.len()
|
||||
}).expect("pty: failed to write event");
|
||||
}
|
||||
} else {
|
||||
socket.write(&Packet {
|
||||
id: 0,
|
||||
pid: 0,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
a: syscall::number::SYS_FEVENT,
|
||||
b: *id,
|
||||
c: syscall::flag::EVENT_READ,
|
||||
d: 0
|
||||
}).expect("pty: failed to write event");
|
||||
}
|
||||
}
|
||||
if let Some(count) = handle.fevent_count() {
|
||||
socket.write(&Packet {
|
||||
id: 0,
|
||||
pid: 0,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
a: syscall::number::SYS_FEVENT,
|
||||
b: *id,
|
||||
c: syscall::flag::EVENT_READ,
|
||||
d: count
|
||||
}).expect("pty: failed to write event");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
use syscall::error::{Error, Result, EINVAL, EWOULDBLOCK};
|
||||
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
|
||||
|
||||
use pty::Pty;
|
||||
use resource::Resource;
|
||||
|
||||
/// Read side of a pipe
|
||||
#[derive(Clone)]
|
||||
pub struct PtyMaster {
|
||||
pty: Rc<RefCell<Pty>>,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PtyMaster {
|
||||
pub fn new(pty: Rc<RefCell<Pty>>, flags: usize) -> Self {
|
||||
PtyMaster {
|
||||
pty: pty,
|
||||
flags: flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource for PtyMaster {
|
||||
fn boxed_clone(&self) -> Box<Resource> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn pty(&self) -> Weak<RefCell<Pty>> {
|
||||
Rc::downgrade(&self.pty)
|
||||
}
|
||||
|
||||
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
self.pty.borrow_mut().path(buf)
|
||||
}
|
||||
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut pty = self.pty.borrow_mut();
|
||||
|
||||
if let Some(packet) = pty.miso.pop_front() {
|
||||
let mut i = 0;
|
||||
|
||||
while i < buf.len() && i < packet.len() {
|
||||
buf[i] = packet[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Ok(i)
|
||||
} else if self.flags & O_NONBLOCK == O_NONBLOCK || Rc::weak_count(&self.pty) == 0 {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EWOULDBLOCK))
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let mut pty = self.pty.borrow_mut();
|
||||
|
||||
let mut i = 0;
|
||||
while i < buf.len() {
|
||||
pty.mosi.push_back(buf[i]);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
|
||||
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<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fevent_count(&self) -> Option<usize> {
|
||||
{
|
||||
let pty = self.pty.borrow();
|
||||
if let Some(data) = pty.miso.front() {
|
||||
return Some(data.len());
|
||||
}
|
||||
}
|
||||
|
||||
if Rc::weak_count(&self.pty) == 0 {
|
||||
Some(0)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use redox_termios::*;
|
||||
use syscall::error::Result;
|
||||
|
||||
pub struct Pty {
|
||||
pub id: usize,
|
||||
pub termios: Termios,
|
||||
pub miso: VecDeque<Vec<u8>>,
|
||||
pub mosi: VecDeque<u8>,
|
||||
}
|
||||
|
||||
impl Pty {
|
||||
pub fn new(id: usize) -> Self {
|
||||
let mut pty = Pty {
|
||||
id: id,
|
||||
termios: Termios::default(),
|
||||
miso: VecDeque::new(),
|
||||
mosi: VecDeque::new()
|
||||
};
|
||||
|
||||
pty.termios.c_iflag = ICRNL | IXON;
|
||||
pty.termios.c_oflag = OPOST | ONLCR;
|
||||
pty.termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;
|
||||
pty.termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | IEXTEN;
|
||||
|
||||
{
|
||||
let mut cc = |i: usize, b: cc_t| {
|
||||
pty.termios.c_cc[i] = b;
|
||||
};
|
||||
|
||||
cc(VEOF, 0o004); // CTRL-D
|
||||
cc(VEOL, 0o000); // NUL
|
||||
cc(VEOL2, 0o000); // NUL
|
||||
cc(VERASE, 0o177); // DEL
|
||||
cc(VWERASE, 0o027); // CTRL-W
|
||||
cc(VKILL, 0o025); // CTRL-U
|
||||
cc(VREPRINT, 0o022);// CTRL-R
|
||||
cc(VSWTC, 0o000); // NUL
|
||||
cc(VINTR, 0o003); // CTRL-C
|
||||
cc(VQUIT, 0o034); // CTRL-\
|
||||
cc(VSUSP, 0o032); // CTRL-Z
|
||||
cc(VSTART, 0o021); // CTRL-Q
|
||||
cc(VSTOP, 0o023); // CTRL-S
|
||||
cc(VLNEXT, 0o026); // CTRL-V
|
||||
cc(VDISCARD, 0o017);// CTRL-U
|
||||
cc(VMIN, 1);
|
||||
cc(VTIME, 0);
|
||||
}
|
||||
|
||||
pty
|
||||
}
|
||||
|
||||
pub fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let path_str = format!("pty:{}", self.id);
|
||||
let path = path_str.as_bytes();
|
||||
|
||||
let mut i = 0;
|
||||
while i < buf.len() && i < path.len() {
|
||||
buf[i] = path[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Ok(i)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Weak;
|
||||
|
||||
use syscall::error::Result;
|
||||
|
||||
use pty::Pty;
|
||||
|
||||
pub trait Resource {
|
||||
fn boxed_clone(&self) -> Box<Resource>;
|
||||
fn pty(&self) -> Weak<RefCell<Pty>>;
|
||||
fn path(&self, buf: &mut [u8]) -> Result<usize>;
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize>;
|
||||
fn write(&self, buf: &[u8]) -> Result<usize>;
|
||||
fn sync(&self) -> Result<usize>;
|
||||
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize>;
|
||||
fn fevent(&self) -> Result<()>;
|
||||
fn fevent_count(&self) -> Option<usize>;
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
|
||||
use syscall::data::Stat;
|
||||
use syscall::error::{Error, Result, EBADF, EINVAL, ENOENT};
|
||||
use syscall::flag::MODE_CHR;
|
||||
use syscall::scheme::SchemeMut;
|
||||
|
||||
use master::PtyMaster;
|
||||
use pty::Pty;
|
||||
use resource::Resource;
|
||||
use slave::PtySlave;
|
||||
|
||||
pub struct PtyScheme {
|
||||
next_id: usize,
|
||||
pub handles: BTreeMap<usize, Box<Resource>>,
|
||||
}
|
||||
|
||||
impl PtyScheme {
|
||||
pub fn new() -> Self {
|
||||
PtyScheme {
|
||||
next_id: 0,
|
||||
handles: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeMut for PtyScheme {
|
||||
fn open(&mut self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
|
||||
let path = str::from_utf8(path).or(Err(Error::new(EINVAL)))?.trim_matches('/');
|
||||
|
||||
if path.is_empty() {
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
|
||||
let pty = Rc::new(RefCell::new(Pty::new(id)));
|
||||
self.handles.insert(id, Box::new(PtyMaster::new(pty, flags)));
|
||||
|
||||
Ok(id)
|
||||
} else {
|
||||
let master_id = path.parse::<usize>().or(Err(Error::new(EINVAL)))?;
|
||||
let pty = {
|
||||
let handle = self.handles.get(&master_id).ok_or(Error::new(ENOENT))?;
|
||||
handle.pty()
|
||||
};
|
||||
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
|
||||
self.handles.insert(id, Box::new(PtySlave::new(pty, flags)));
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result<usize> {
|
||||
if ! buf.is_empty() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
let handle = {
|
||||
let old_handle = self.handles.get(&old_id).ok_or(Error::new(EBADF))?;
|
||||
old_handle.boxed_clone()
|
||||
};
|
||||
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
self.handles.insert(id, handle);
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
handle.read(buf)
|
||||
}
|
||||
|
||||
fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
handle.write(buf)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let mut handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
handle.fcntl(cmd, arg)
|
||||
}
|
||||
|
||||
fn fevent(&mut self, id: usize, _flags: usize) -> Result<usize> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
handle.fevent().and(Ok(id))
|
||||
}
|
||||
|
||||
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
handle.path(buf)
|
||||
}
|
||||
|
||||
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<usize> {
|
||||
let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
*stat = Stat {
|
||||
st_mode: MODE_CHR | 0o666,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn fsync(&mut self, id: usize) -> Result<usize> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
handle.sync()
|
||||
}
|
||||
|
||||
fn close(&mut self, id: usize) -> Result<usize> {
|
||||
drop(self.handles.remove(&id));
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Weak;
|
||||
|
||||
use syscall::error::{Error, Result, EINVAL, EPIPE, EWOULDBLOCK};
|
||||
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK};
|
||||
|
||||
use pty::Pty;
|
||||
use resource::Resource;
|
||||
|
||||
/// Read side of a pipe
|
||||
#[derive(Clone)]
|
||||
pub struct PtySlave {
|
||||
pty: Weak<RefCell<Pty>>,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PtySlave {
|
||||
pub fn new(pty: Weak<RefCell<Pty>>, flags: usize) -> Self {
|
||||
PtySlave {
|
||||
pty: pty,
|
||||
flags: flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource for PtySlave {
|
||||
fn boxed_clone(&self) -> Box<Resource> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn pty(&self) -> Weak<RefCell<Pty>> {
|
||||
self.pty.clone()
|
||||
}
|
||||
|
||||
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
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<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let mut pty = pty_lock.borrow_mut();
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while i < buf.len() && ! pty.mosi.is_empty() {
|
||||
buf[i] = pty.mosi.pop_front().unwrap();
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if i > 0 || self.flags & O_NONBLOCK == O_NONBLOCK {
|
||||
Ok(i)
|
||||
} else {
|
||||
Err(Error::new(EWOULDBLOCK))
|
||||
}
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let mut vec = Vec::new();
|
||||
vec.push(0);
|
||||
vec.extend_from_slice(buf);
|
||||
|
||||
let mut pty = pty_lock.borrow_mut();
|
||||
pty.miso.push_back(vec);
|
||||
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
Err(Error::new(EPIPE))
|
||||
}
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let mut vec = Vec::new();
|
||||
vec.push(1);
|
||||
|
||||
let mut pty = pty_lock.borrow_mut();
|
||||
pty.miso.push_back(vec);
|
||||
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EPIPE))
|
||||
}
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
|
||||
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<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fevent_count(&self) -> Option<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let pty = pty_lock.borrow();
|
||||
if ! pty.mosi.is_empty() {
|
||||
Some(pty.mosi.len())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
Some(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user