ddd6c4f3ac
This functionality is needed according to POSIX. Additionally, some logic had to be changed in order for the ptsname to be correct for the manager terminal (ptmx). If you want to obtain a pty, you must go through the `posix_openpt`-`grantpt`-`unlockpt`-`ptsname`-`open` process. Alternatively, relibc as a function called `openpty`. This is part of my ptyd series. This can be safely merged once the MRs for relibc/ and userutils/ are merged at the same time.
94 lines
2.3 KiB
Rust
94 lines
2.3 KiB
Rust
use std::cell::RefCell;
|
|
use std::rc::Weak;
|
|
|
|
use syscall::error::{Error, Result, EBADF, EINVAL, EPIPE};
|
|
use syscall::flag::{EventFlags, F_GETFL, F_SETFL, O_ACCMODE};
|
|
|
|
use crate::pty::Pty;
|
|
use crate::resource::Resource;
|
|
|
|
/// Read side of a pipe
|
|
pub struct PtyLock {
|
|
pty: Weak<RefCell<Pty>>,
|
|
flags: usize,
|
|
}
|
|
|
|
impl PtyLock {
|
|
pub fn new(pty: Weak<RefCell<Pty>>, flags: usize) -> Self {
|
|
PtyLock { pty, flags }
|
|
}
|
|
}
|
|
|
|
impl Resource for PtyLock {
|
|
fn pty(&self) -> Weak<RefCell<Pty>> {
|
|
self.pty.clone()
|
|
}
|
|
|
|
fn flags(&self) -> usize {
|
|
self.flags
|
|
}
|
|
|
|
fn path(&mut 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))
|
|
}
|
|
}
|
|
|
|
// FIXME assuming c_int has same size as u32
|
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
|
if let Some(pty_lock) = self.pty.upgrade() {
|
|
let pty = pty_lock.borrow();
|
|
|
|
let lock_buf = buf
|
|
.get_mut(..4)
|
|
.and_then(|b| <&mut [u8; 4]>::try_from(b).ok())
|
|
.ok_or(Error::new(EBADF))?;
|
|
*lock_buf = (pty.locked as u32).to_ne_bytes();
|
|
Ok(4)
|
|
} else {
|
|
Ok(0)
|
|
}
|
|
}
|
|
|
|
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
|
if let Some(pty_lock) = self.pty.upgrade() {
|
|
let mut pty = pty_lock.borrow_mut();
|
|
|
|
let lock_val = u32::from_ne_bytes(
|
|
buf.get(..4)
|
|
.and_then(|b| <[u8; 4]>::try_from(b).ok())
|
|
.ok_or(Error::new(EBADF))?,
|
|
);
|
|
pty.locked = lock_val != 0;
|
|
Ok(4)
|
|
} else {
|
|
Ok(0)
|
|
}
|
|
}
|
|
|
|
fn sync(&mut self) -> Result<()> {
|
|
Ok(())
|
|
}
|
|
|
|
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(&mut self) -> Result<EventFlags> {
|
|
Err(Error::new(EBADF))
|
|
}
|
|
|
|
fn events(&mut self) -> EventFlags {
|
|
EventFlags::empty()
|
|
}
|
|
}
|