Skip to content

Commit

Permalink
完善pty,目前pty能够支持ssh (#708)
Browse files Browse the repository at this point in the history
  • Loading branch information
GnoCiYeH authored Apr 10, 2024
1 parent 4b0170b commit 9365e80
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 21 deletions.
74 changes: 69 additions & 5 deletions kernel/src/driver/tty/pty/unix98pty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use system_error::SystemError;

use crate::{
driver::tty::{
termios::Termios,
termios::{ControlCharIndex, ControlMode, InputMode, LocalMode, Termios},
tty_core::{TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd, TtyPacketStatus},
tty_device::TtyFilePrivateData,
tty_driver::{TtyDriver, TtyDriverPrivateData, TtyDriverSubType, TtyOperation},
Expand Down Expand Up @@ -76,7 +76,7 @@ impl TtyOperation for Unix98PtyDriverInner {
fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
let core = tty.core();
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtyMaster {
return Err(SystemError::ENOSYS);
return Err(SystemError::ENOIOCTLCMD);
}

match cmd {
Expand Down Expand Up @@ -104,12 +104,58 @@ impl TtyOperation for Unix98PtyDriverInner {
}
}

fn set_termios(&self, tty: Arc<TtyCore>, _old_termios: Termios) -> Result<(), SystemError> {
fn set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError> {
let core = tty.core();
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
return Err(SystemError::ENOSYS);
}
todo!()

let core = tty.core();
if let Some(link) = core.link() {
let link = link.core();
if link.contorl_info_irqsave().packet {
let curr_termios = *core.termios();
let extproc = old_termios.local_mode.contains(LocalMode::EXTPROC)
| curr_termios.local_mode.contains(LocalMode::EXTPROC);

let old_flow = old_termios.input_mode.contains(InputMode::IXON)
&& old_termios.control_characters[ControlCharIndex::VSTOP] == 0o023
&& old_termios.control_characters[ControlCharIndex::VSTART] == 0o021;

let new_flow = curr_termios.input_mode.contains(InputMode::IXON)
&& curr_termios.control_characters[ControlCharIndex::VSTOP] == 0o023
&& curr_termios.control_characters[ControlCharIndex::VSTART] == 0o021;

if old_flow != new_flow || extproc {
let mut ctrl = core.contorl_info_irqsave();
if old_flow != new_flow {
ctrl.pktstatus.remove(
TtyPacketStatus::TIOCPKT_DOSTOP | TtyPacketStatus::TIOCPKT_NOSTOP,
);

if new_flow {
ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_DOSTOP);
} else {
ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_NOSTOP);
}
}

if extproc {
ctrl.pktstatus.insert(TtyPacketStatus::TIOCPKT_IOCTL);
}

link.read_wq().wakeup_all();
}
}
}
let mut termois = core.termios_write();
termois
.control_mode
.remove(ControlMode::CSIZE | ControlMode::PARENB);
termois
.control_mode
.insert(ControlMode::CS8 | ControlMode::CREAD);
Ok(())
}

fn start(&self, core: &TtyCoreData) -> Result<(), SystemError> {
Expand Down Expand Up @@ -171,15 +217,33 @@ impl TtyOperation for Unix98PtyDriverInner {
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
let driver = tty.core().driver();

driver.ttys().remove(&tty.core().index());
if tty.core().driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave {
driver.ttys().remove(&tty.core().index());
let pts_root_inode =
ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
let _ = pts_root_inode.unlink(&tty.core().index().to_string());
}

Ok(())
}

fn resize(
&self,
tty: Arc<TtyCore>,
winsize: crate::driver::tty::termios::WindowSize,
) -> Result<(), SystemError> {
let core = tty.core();
if *core.window_size() == winsize {
return Ok(());
}

// TODO:向进程发送SIGWINCH信号

*core.window_size_write() = winsize;
*core.link().unwrap().core().window_size_write() = winsize;

Ok(())
}
}

pub fn ptmx_open(
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/driver/tty/termios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::tty_ldisc::LineDisciplineType;

/// ## 窗口大小
#[repr(C)]
#[derive(Debug, Default, Clone, Copy)]
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct WindowSize {
/// 行
pub row: u16,
Expand Down
27 changes: 26 additions & 1 deletion kernel/src/driver/tty/tty_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use alloc::{
use system_error::SystemError;

use crate::{
driver::serial::serial8250::send_to_default_serial8250_port,
driver::{serial::serial8250::send_to_default_serial8250_port, tty::pty::ptm_driver},
libs::{
rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
Expand Down Expand Up @@ -42,6 +42,14 @@ pub struct TtyCore {
line_discipline: Arc<dyn TtyLineDiscipline>,
}

impl Drop for TtyCore {
fn drop(&mut self) {
if self.core.driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave {
ptm_driver().ttys().remove(&self.core().index);
}
}
}

impl TtyCore {
pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
let name = driver.tty_line_name(index);
Expand Down Expand Up @@ -232,7 +240,9 @@ impl TtyCore {
let tmp = termios.control_mode;
termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;

drop(termios);
let ret = tty.set_termios(tty.clone(), old_termios);
let mut termios = tty.core().termios_write();
if ret.is_err() {
termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL;
termios.control_mode |= old_termios.control_mode
Expand All @@ -247,6 +257,12 @@ impl TtyCore {

Ok(())
}

pub fn tty_do_resize(&self, windowsize: WindowSize) -> Result<(), SystemError> {
// TODO: 向前台进程发送信号
*self.core.window_size_write() = windowsize;
Ok(())
}
}

#[derive(Debug, Default)]
Expand Down Expand Up @@ -394,6 +410,11 @@ impl TtyCoreData {
self.window_size.read()
}

#[inline]
pub fn window_size_write(&self) -> RwLockWriteGuard<WindowSize> {
self.window_size.write()
}

#[inline]
pub fn is_closing(&self) -> bool {
self.closing.load(core::sync::atomic::Ordering::SeqCst)
Expand Down Expand Up @@ -511,6 +532,10 @@ impl TtyOperation for TtyCore {
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
self.core().tty_driver.driver_funcs().close(tty)
}

fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> {
self.core.tty_driver.driver_funcs().resize(tty, winsize)
}
}

bitflags! {
Expand Down
23 changes: 20 additions & 3 deletions kernel/src/driver/tty/tty_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,10 @@ impl IndexNode for TtyDevice {
mut data: SpinLockGuard<FilePrivateData>,
mode: &crate::filesystem::vfs::file::FileMode,
) -> Result<(), SystemError> {
if let FilePrivateData::Tty(_) = &*data {
return Ok(());
}
if self.tty_type == TtyType::Pty(PtyType::Ptm) {
if let FilePrivateData::Tty(_) = &*data {
return Ok(());
}
return ptmx_open(data, mode);
}
let dev_num = self.metadata()?.raw_dev;
Expand Down Expand Up @@ -360,6 +360,23 @@ impl IndexNode for TtyDevice {
}
return Ok(0);
}
TtyIoctlCmd::TIOCSWINSZ => {
let reader = UserBufferReader::new(
arg as *const (),
core::mem::size_of::<WindowSize>(),
true,
)?;

let user_winsize = reader.read_one_from_user::<WindowSize>(0)?;

let ret = tty.resize(tty.clone(), *user_winsize);

if ret != Err(SystemError::ENOSYS) {
return ret.map(|_| 0);
} else {
return tty.tty_do_resize(*user_winsize).map(|_| 0);
}
}
_ => match TtyJobCtrlManager::job_ctrl_ioctl(tty.clone(), cmd, arg) {
Ok(_) => {
return Ok(0);
Expand Down
6 changes: 4 additions & 2 deletions kernel/src/driver/tty/tty_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
};

use super::{
termios::Termios,
termios::{Termios, WindowSize},
tty_core::{TtyCore, TtyCoreData},
tty_ldisc::TtyLdiscManager,
tty_port::{DefaultTtyPort, TtyPort},
Expand Down Expand Up @@ -273,7 +273,7 @@ impl TtyDriver {
tty.set_port(ports[core.index()].clone());
}

TtyLdiscManager::ldisc_setup(tty.clone(), None)?;
TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?;

Ok(tty)
}
Expand Down Expand Up @@ -445,6 +445,8 @@ pub trait TtyOperation: Sync + Send + Debug {
}

fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;

fn resize(&self, _tty: Arc<TtyCore>, _winsize: WindowSize) -> Result<(), SystemError>;
}

#[allow(dead_code)]
Expand Down
8 changes: 4 additions & 4 deletions kernel/src/driver/tty/tty_ldisc/ntty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ pub struct NTtyData {
read_flags: StaticBitmap<NTTY_BUFSIZE>,
char_map: StaticBitmap<256>,

tty: Option<Weak<TtyCore>>,
tty: Weak<TtyCore>,
}

impl NTtyData {
Expand Down Expand Up @@ -151,7 +151,7 @@ impl NTtyData {
echo_buf: [0; NTTY_BUFSIZE],
read_flags: StaticBitmap::new(),
char_map: StaticBitmap::new(),
tty: None,
tty: Weak::default(),
no_room: false,
}
}
Expand Down Expand Up @@ -1168,7 +1168,7 @@ impl NTtyData {
nr: usize,
) -> Result<usize, SystemError> {
let mut nr = nr;
let tty = self.tty.clone().unwrap().upgrade().unwrap();
let tty = self.tty.upgrade().unwrap();
let space = tty.write_room(tty.core());

// 如果读取数量大于了可用空间,则取最小的为真正的写入数量
Expand Down Expand Up @@ -1541,7 +1541,7 @@ impl NTtyData {
impl TtyLineDiscipline for NTtyLinediscipline {
fn open(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
// 反向绑定tty到disc
self.disc_data().tty = Some(Arc::downgrade(&tty));
self.disc_data().tty = Arc::downgrade(&tty);
// 特定的tty设备在这里可能需要取消端口节流
return self.set_termios(tty, None);
}
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/driver/tty/virtual_terminal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,14 @@ impl TtyOperation for TtyConsoleDriverInner {
fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
Ok(())
}

fn resize(
&self,
_tty: Arc<TtyCore>,
_winsize: super::termios::WindowSize,
) -> Result<(), SystemError> {
todo!()
}
}

#[derive(Debug, Clone)]
Expand Down
5 changes: 0 additions & 5 deletions kernel/src/filesystem/vfs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,11 +634,6 @@ impl FileDescriptorVec {
///
/// - `fd` 文件描述符序号
pub fn drop_fd(&mut self, fd: i32) -> Result<(), SystemError> {
// 判断文件描述符的数字是否超过限制
if !FileDescriptorVec::validate_fd(fd) {
return Err(SystemError::EBADF);
}

self.get_file_by_fd(fd).ok_or(SystemError::EBADF)?;

// 把文件描述符数组对应位置设置为空
Expand Down
4 changes: 4 additions & 0 deletions kernel/src/filesystem/vfs/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,8 @@ impl Syscall {
.ok_or(SystemError::EBADF)?;

let new_file = old_file.try_clone().ok_or(SystemError::EBADF)?;
// dup默认非cloexec
new_file.set_close_on_exec(false);
// 申请文件描述符,并把文件对象存入其中
let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize);
return res;
Expand Down Expand Up @@ -1029,6 +1031,8 @@ impl Syscall {
.get_file_by_fd(oldfd)
.ok_or(SystemError::EBADF)?;
let new_file = old_file.try_clone().ok_or(SystemError::EBADF)?;
// dup2默认非cloexec
new_file.set_close_on_exec(false);
// 申请文件描述符,并把文件对象存入其中
let res = fd_table_guard
.alloc_fd(new_file, Some(newfd))
Expand Down

0 comments on commit 9365e80

Please sign in to comment.