mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
Move fields from PTY master to slave
This commit is contained in:
parent
89e8cd5936
commit
6f20cfbe69
@ -43,6 +43,6 @@ pub fn init() -> Result<()> {
|
|||||||
pub fn new_pty_pair(index: u32, ptmx: Arc<dyn Inode>) -> Result<(Arc<PtyMaster>, Arc<PtySlave>)> {
|
pub fn new_pty_pair(index: u32, ptmx: Arc<dyn Inode>) -> Result<(Arc<PtyMaster>, Arc<PtySlave>)> {
|
||||||
debug!("pty index = {}", index);
|
debug!("pty index = {}", index);
|
||||||
let master = PtyMaster::new(ptmx, index);
|
let master = PtyMaster::new(ptmx, index);
|
||||||
let slave = PtySlave::new(&master);
|
let slave = master.slave().clone();
|
||||||
Ok((master, slave))
|
Ok((master, slave))
|
||||||
}
|
}
|
||||||
|
@ -34,25 +34,30 @@ const BUFFER_CAPACITY: usize = 4096;
|
|||||||
pub struct PtyMaster {
|
pub struct PtyMaster {
|
||||||
ptmx: Arc<dyn Inode>,
|
ptmx: Arc<dyn Inode>,
|
||||||
index: u32,
|
index: u32,
|
||||||
output: Arc<LineDiscipline>,
|
slave: Arc<PtySlave>,
|
||||||
input: SpinLock<RingBuffer<u8>>,
|
input: SpinLock<RingBuffer<u8>>,
|
||||||
job_control: Arc<JobControl>,
|
|
||||||
/// The state of input buffer
|
/// The state of input buffer
|
||||||
pollee: Pollee,
|
pollee: Pollee,
|
||||||
weak_self: Weak<Self>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PtyMaster {
|
impl PtyMaster {
|
||||||
pub fn new(ptmx: Arc<dyn Inode>, index: u32) -> Arc<Self> {
|
pub fn new(ptmx: Arc<dyn Inode>, index: u32) -> Arc<Self> {
|
||||||
|
Arc::new_cyclic(move |master| {
|
||||||
let (job_control, ldisc) = new_job_control_and_ldisc();
|
let (job_control, ldisc) = new_job_control_and_ldisc();
|
||||||
Arc::new_cyclic(move |weak_ref| PtyMaster {
|
let slave = Arc::new_cyclic(move |weak_self| PtySlave {
|
||||||
|
ldisc,
|
||||||
|
job_control,
|
||||||
|
master: master.clone(),
|
||||||
|
weak_self: weak_self.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
PtyMaster {
|
||||||
ptmx,
|
ptmx,
|
||||||
index,
|
index,
|
||||||
output: ldisc,
|
slave,
|
||||||
input: SpinLock::new(RingBuffer::new(BUFFER_CAPACITY)),
|
input: SpinLock::new(RingBuffer::new(BUFFER_CAPACITY)),
|
||||||
job_control,
|
|
||||||
pollee: Pollee::new(),
|
pollee: Pollee::new(),
|
||||||
weak_self: weak_ref.clone(),
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +69,10 @@ impl PtyMaster {
|
|||||||
&self.ptmx
|
&self.ptmx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn slave(&self) -> &Arc<PtySlave> {
|
||||||
|
&self.slave
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn slave_push_char(&self, ch: u8) {
|
pub(super) fn slave_push_char(&self, ch: u8) {
|
||||||
let mut input = self.input.disable_irq().lock();
|
let mut input = self.input.disable_irq().lock();
|
||||||
input.push_overwrite(ch);
|
input.push_overwrite(ch);
|
||||||
@ -79,7 +88,7 @@ impl PtyMaster {
|
|||||||
|
|
||||||
let poll_in_mask = mask & IoEvents::IN;
|
let poll_in_mask = mask & IoEvents::IN;
|
||||||
if !poll_in_mask.is_empty() {
|
if !poll_in_mask.is_empty() {
|
||||||
let poll_in_status = self.output.poll(poll_in_mask, poller.as_deref_mut());
|
let poll_in_status = self.slave.ldisc.poll(poll_in_mask, poller.as_deref_mut());
|
||||||
poll_status |= poll_in_status;
|
poll_status |= poll_in_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,10 +103,6 @@ impl PtyMaster {
|
|||||||
poll_status
|
poll_status
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn slave_buf_len(&self) -> usize {
|
|
||||||
self.output.buffer_len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_read(&self, writer: &mut VmWriter) -> Result<usize> {
|
fn try_read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||||
let mut input = self.input.disable_irq().lock();
|
let mut input = self.input.disable_irq().lock();
|
||||||
|
|
||||||
@ -138,7 +143,7 @@ impl Pollable for PtyMaster {
|
|||||||
|
|
||||||
let poll_out_mask = mask & IoEvents::OUT;
|
let poll_out_mask = mask & IoEvents::OUT;
|
||||||
if !poll_out_mask.is_empty() {
|
if !poll_out_mask.is_empty() {
|
||||||
let poll_out_status = self.output.poll(poll_out_mask, poller);
|
let poll_out_status = self.slave.ldisc.poll(poll_out_mask, poller);
|
||||||
poll_status |= poll_out_status;
|
poll_status |= poll_out_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +166,7 @@ impl FileIo for PtyMaster {
|
|||||||
let write_len = buf.len();
|
let write_len = buf.len();
|
||||||
let mut input = self.input.lock();
|
let mut input = self.input.lock();
|
||||||
for character in buf {
|
for character in buf {
|
||||||
self.output.push_char(character, |content| {
|
self.slave.ldisc.push_char(character, |content| {
|
||||||
for byte in content.as_bytes() {
|
for byte in content.as_bytes() {
|
||||||
input.push_overwrite(*byte);
|
input.push_overwrite(*byte);
|
||||||
}
|
}
|
||||||
@ -174,25 +179,15 @@ impl FileIo for PtyMaster {
|
|||||||
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
match cmd {
|
match cmd {
|
||||||
IoctlCmd::TCGETS => {
|
IoctlCmd::TCGETS
|
||||||
let termios = self.output.termios();
|
| IoctlCmd::TCSETS
|
||||||
current_userspace!().write_val(arg, &termios)?;
|
| IoctlCmd::TIOCGPTN
|
||||||
Ok(0)
|
| IoctlCmd::TIOCGWINSZ
|
||||||
}
|
| IoctlCmd::TIOCSWINSZ => self.slave.ioctl(cmd, arg),
|
||||||
IoctlCmd::TCSETS => {
|
|
||||||
let termios = current_userspace!().read_val(arg)?;
|
|
||||||
self.output.set_termios(termios);
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
IoctlCmd::TIOCSPTLCK => {
|
IoctlCmd::TIOCSPTLCK => {
|
||||||
// TODO: lock/unlock pty
|
// TODO: lock/unlock pty
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
IoctlCmd::TIOCGPTN => {
|
|
||||||
let idx = self.index();
|
|
||||||
current_userspace!().write_val(arg, &idx)?;
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
IoctlCmd::TIOCGPTPEER => {
|
IoctlCmd::TIOCGPTPEER => {
|
||||||
let current_task = Task::current().unwrap();
|
let current_task = Task::current().unwrap();
|
||||||
let posix_thread = current_task.as_posix_thread().unwrap();
|
let posix_thread = current_task.as_posix_thread().unwrap();
|
||||||
@ -224,18 +219,8 @@ impl FileIo for PtyMaster {
|
|||||||
};
|
};
|
||||||
Ok(fd)
|
Ok(fd)
|
||||||
}
|
}
|
||||||
IoctlCmd::TIOCGWINSZ => {
|
|
||||||
let winsize = self.output.window_size();
|
|
||||||
current_userspace!().write_val(arg, &winsize)?;
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
IoctlCmd::TIOCSWINSZ => {
|
|
||||||
let winsize = current_userspace!().read_val(arg)?;
|
|
||||||
self.output.set_window_size(winsize);
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
IoctlCmd::TIOCGPGRP => {
|
IoctlCmd::TIOCGPGRP => {
|
||||||
let Some(foreground) = self.foreground() else {
|
let Some(foreground) = self.slave.foreground() else {
|
||||||
return_errno_with_message!(
|
return_errno_with_message!(
|
||||||
Errno::ESRCH,
|
Errno::ESRCH,
|
||||||
"the foreground process group does not exist"
|
"the foreground process group does not exist"
|
||||||
@ -254,15 +239,15 @@ impl FileIo for PtyMaster {
|
|||||||
pgid as u32
|
pgid as u32
|
||||||
};
|
};
|
||||||
|
|
||||||
self.set_foreground(&pgid)?;
|
self.slave.set_foreground(&pgid)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
IoctlCmd::TIOCSCTTY => {
|
IoctlCmd::TIOCSCTTY => {
|
||||||
self.set_current_session()?;
|
self.slave.set_current_session()?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
IoctlCmd::TIOCNOTTY => {
|
IoctlCmd::TIOCNOTTY => {
|
||||||
self.release_current_session()?;
|
self.slave.release_current_session()?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
IoctlCmd::FIONREAD => {
|
IoctlCmd::FIONREAD => {
|
||||||
@ -275,16 +260,6 @@ impl FileIo for PtyMaster {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Terminal for PtyMaster {
|
|
||||||
fn arc_self(&self) -> Arc<dyn Terminal> {
|
|
||||||
self.weak_self.upgrade().unwrap() as _
|
|
||||||
}
|
|
||||||
|
|
||||||
fn job_control(&self) -> &JobControl {
|
|
||||||
&self.job_control
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for PtyMaster {
|
impl Drop for PtyMaster {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let fs = self.ptmx.fs();
|
let fs = self.ptmx.fs();
|
||||||
@ -296,20 +271,13 @@ impl Drop for PtyMaster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct PtySlave {
|
pub struct PtySlave {
|
||||||
|
ldisc: Arc<LineDiscipline>,
|
||||||
|
job_control: Arc<JobControl>,
|
||||||
master: Weak<PtyMaster>,
|
master: Weak<PtyMaster>,
|
||||||
job_control: JobControl,
|
|
||||||
weak_self: Weak<Self>,
|
weak_self: Weak<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PtySlave {
|
impl PtySlave {
|
||||||
pub fn new(master: &Arc<PtyMaster>) -> Arc<Self> {
|
|
||||||
Arc::new_cyclic(|weak_ref| PtySlave {
|
|
||||||
master: Arc::downgrade(master),
|
|
||||||
job_control: JobControl::new(),
|
|
||||||
weak_self: weak_ref.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn index(&self) -> u32 {
|
pub fn index(&self) -> u32 {
|
||||||
self.master().index()
|
self.master().index()
|
||||||
}
|
}
|
||||||
@ -349,7 +317,7 @@ impl FileIo for PtySlave {
|
|||||||
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||||
let mut buf = vec![0u8; writer.avail()];
|
let mut buf = vec![0u8; writer.avail()];
|
||||||
self.job_control.wait_until_in_foreground()?;
|
self.job_control.wait_until_in_foreground()?;
|
||||||
let read_len = self.master().output.read(&mut buf)?;
|
let read_len = self.ldisc.read(&mut buf)?;
|
||||||
writer.write_fallible(&mut buf.as_slice().into())?;
|
writer.write_fallible(&mut buf.as_slice().into())?;
|
||||||
Ok(read_len)
|
Ok(read_len)
|
||||||
}
|
}
|
||||||
@ -372,11 +340,31 @@ impl FileIo for PtySlave {
|
|||||||
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
match cmd {
|
match cmd {
|
||||||
IoctlCmd::TCGETS
|
IoctlCmd::TCGETS => {
|
||||||
| IoctlCmd::TCSETS
|
let termios = self.ldisc.termios();
|
||||||
| IoctlCmd::TIOCGPTN
|
current_userspace!().write_val(arg, &termios)?;
|
||||||
| IoctlCmd::TIOCGWINSZ
|
Ok(0)
|
||||||
| IoctlCmd::TIOCSWINSZ => self.master().ioctl(cmd, arg),
|
}
|
||||||
|
IoctlCmd::TCSETS => {
|
||||||
|
let termios = current_userspace!().read_val(arg)?;
|
||||||
|
self.ldisc.set_termios(termios);
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
IoctlCmd::TIOCGPTN => {
|
||||||
|
let idx = self.index();
|
||||||
|
current_userspace!().write_val(arg, &idx)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
IoctlCmd::TIOCGWINSZ => {
|
||||||
|
let winsize = self.ldisc.window_size();
|
||||||
|
current_userspace!().write_val(arg, &winsize)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
IoctlCmd::TIOCSWINSZ => {
|
||||||
|
let winsize = current_userspace!().read_val(arg)?;
|
||||||
|
self.ldisc.set_window_size(winsize);
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
IoctlCmd::TIOCGPGRP => {
|
IoctlCmd::TIOCGPGRP => {
|
||||||
if !self.is_controlling_terminal() {
|
if !self.is_controlling_terminal() {
|
||||||
return_errno_with_message!(Errno::ENOTTY, "slave is not controlling terminal");
|
return_errno_with_message!(Errno::ENOTTY, "slave is not controlling terminal");
|
||||||
@ -414,7 +402,7 @@ impl FileIo for PtySlave {
|
|||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
IoctlCmd::FIONREAD => {
|
IoctlCmd::FIONREAD => {
|
||||||
let buffer_len = self.master().slave_buf_len() as i32;
|
let buffer_len = self.ldisc.buffer_len() as i32;
|
||||||
current_userspace!().write_val(arg, &buffer_len)?;
|
current_userspace!().write_val(arg, &buffer_len)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user