mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
完善pty,目前pty能够支持ssh (#708)
This commit is contained in:
parent
4b0170bd6b
commit
9365e8017b
@ -3,7 +3,7 @@ use system_error::SystemError;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::tty::{
|
driver::tty::{
|
||||||
termios::Termios,
|
termios::{ControlCharIndex, ControlMode, InputMode, LocalMode, Termios},
|
||||||
tty_core::{TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd, TtyPacketStatus},
|
tty_core::{TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd, TtyPacketStatus},
|
||||||
tty_device::TtyFilePrivateData,
|
tty_device::TtyFilePrivateData,
|
||||||
tty_driver::{TtyDriver, TtyDriverPrivateData, TtyDriverSubType, TtyOperation},
|
tty_driver::{TtyDriver, TtyDriverPrivateData, TtyDriverSubType, TtyOperation},
|
||||||
@ -76,7 +76,7 @@ impl TtyOperation for Unix98PtyDriverInner {
|
|||||||
fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
|
fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
|
||||||
let core = tty.core();
|
let core = tty.core();
|
||||||
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtyMaster {
|
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtyMaster {
|
||||||
return Err(SystemError::ENOSYS);
|
return Err(SystemError::ENOIOCTLCMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
@ -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();
|
let core = tty.core();
|
||||||
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
|
if core.driver().tty_driver_sub_type() != TtyDriverSubType::PtySlave {
|
||||||
return Err(SystemError::ENOSYS);
|
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> {
|
fn start(&self, core: &TtyCoreData) -> Result<(), SystemError> {
|
||||||
@ -171,8 +217,8 @@ impl TtyOperation for Unix98PtyDriverInner {
|
|||||||
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||||
let driver = tty.core().driver();
|
let driver = tty.core().driver();
|
||||||
|
|
||||||
driver.ttys().remove(&tty.core().index());
|
|
||||||
if tty.core().driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave {
|
if tty.core().driver().tty_driver_sub_type() == TtyDriverSubType::PtySlave {
|
||||||
|
driver.ttys().remove(&tty.core().index());
|
||||||
let pts_root_inode =
|
let pts_root_inode =
|
||||||
ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
|
ROOT_INODE().lookup_follow_symlink("/dev/pts", VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
|
||||||
let _ = pts_root_inode.unlink(&tty.core().index().to_string());
|
let _ = pts_root_inode.unlink(&tty.core().index().to_string());
|
||||||
@ -180,6 +226,24 @@ impl TtyOperation for Unix98PtyDriverInner {
|
|||||||
|
|
||||||
Ok(())
|
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(
|
pub fn ptmx_open(
|
||||||
|
@ -2,7 +2,7 @@ use super::tty_ldisc::LineDisciplineType;
|
|||||||
|
|
||||||
/// ## 窗口大小
|
/// ## 窗口大小
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||||
pub struct WindowSize {
|
pub struct WindowSize {
|
||||||
/// 行
|
/// 行
|
||||||
pub row: u16,
|
pub row: u16,
|
||||||
|
@ -12,7 +12,7 @@ use alloc::{
|
|||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
driver::serial::serial8250::send_to_default_serial8250_port,
|
driver::{serial::serial8250::send_to_default_serial8250_port, tty::pty::ptm_driver},
|
||||||
libs::{
|
libs::{
|
||||||
rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
|
rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
|
||||||
spinlock::{SpinLock, SpinLockGuard},
|
spinlock::{SpinLock, SpinLockGuard},
|
||||||
@ -42,6 +42,14 @@ pub struct TtyCore {
|
|||||||
line_discipline: Arc<dyn TtyLineDiscipline>,
|
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 {
|
impl TtyCore {
|
||||||
pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
|
pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
|
||||||
let name = driver.tty_line_name(index);
|
let name = driver.tty_line_name(index);
|
||||||
@ -232,7 +240,9 @@ impl TtyCore {
|
|||||||
let tmp = termios.control_mode;
|
let tmp = termios.control_mode;
|
||||||
termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;
|
termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;
|
||||||
|
|
||||||
|
drop(termios);
|
||||||
let ret = tty.set_termios(tty.clone(), old_termios);
|
let ret = tty.set_termios(tty.clone(), old_termios);
|
||||||
|
let mut termios = tty.core().termios_write();
|
||||||
if ret.is_err() {
|
if ret.is_err() {
|
||||||
termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL;
|
termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL;
|
||||||
termios.control_mode |= old_termios.control_mode
|
termios.control_mode |= old_termios.control_mode
|
||||||
@ -247,6 +257,12 @@ impl TtyCore {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tty_do_resize(&self, windowsize: WindowSize) -> Result<(), SystemError> {
|
||||||
|
// TODO: 向前台进程发送信号
|
||||||
|
*self.core.window_size_write() = windowsize;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -394,6 +410,11 @@ impl TtyCoreData {
|
|||||||
self.window_size.read()
|
self.window_size.read()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn window_size_write(&self) -> RwLockWriteGuard<WindowSize> {
|
||||||
|
self.window_size.write()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_closing(&self) -> bool {
|
pub fn is_closing(&self) -> bool {
|
||||||
self.closing.load(core::sync::atomic::Ordering::SeqCst)
|
self.closing.load(core::sync::atomic::Ordering::SeqCst)
|
||||||
@ -511,6 +532,10 @@ impl TtyOperation for TtyCore {
|
|||||||
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||||
self.core().tty_driver.driver_funcs().close(tty)
|
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! {
|
bitflags! {
|
||||||
|
@ -134,10 +134,10 @@ impl IndexNode for TtyDevice {
|
|||||||
mut data: SpinLockGuard<FilePrivateData>,
|
mut data: SpinLockGuard<FilePrivateData>,
|
||||||
mode: &crate::filesystem::vfs::file::FileMode,
|
mode: &crate::filesystem::vfs::file::FileMode,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
|
if let FilePrivateData::Tty(_) = &*data {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
if self.tty_type == TtyType::Pty(PtyType::Ptm) {
|
if self.tty_type == TtyType::Pty(PtyType::Ptm) {
|
||||||
if let FilePrivateData::Tty(_) = &*data {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
return ptmx_open(data, mode);
|
return ptmx_open(data, mode);
|
||||||
}
|
}
|
||||||
let dev_num = self.metadata()?.raw_dev;
|
let dev_num = self.metadata()?.raw_dev;
|
||||||
@ -360,6 +360,23 @@ impl IndexNode for TtyDevice {
|
|||||||
}
|
}
|
||||||
return Ok(0);
|
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) {
|
_ => match TtyJobCtrlManager::job_ctrl_ioctl(tty.clone(), cmd, arg) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
|
@ -27,7 +27,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
termios::Termios,
|
termios::{Termios, WindowSize},
|
||||||
tty_core::{TtyCore, TtyCoreData},
|
tty_core::{TtyCore, TtyCoreData},
|
||||||
tty_ldisc::TtyLdiscManager,
|
tty_ldisc::TtyLdiscManager,
|
||||||
tty_port::{DefaultTtyPort, TtyPort},
|
tty_port::{DefaultTtyPort, TtyPort},
|
||||||
@ -273,7 +273,7 @@ impl TtyDriver {
|
|||||||
tty.set_port(ports[core.index()].clone());
|
tty.set_port(ports[core.index()].clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
TtyLdiscManager::ldisc_setup(tty.clone(), None)?;
|
TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?;
|
||||||
|
|
||||||
Ok(tty)
|
Ok(tty)
|
||||||
}
|
}
|
||||||
@ -445,6 +445,8 @@ pub trait TtyOperation: Sync + Send + Debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
|
fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError>;
|
||||||
|
|
||||||
|
fn resize(&self, _tty: Arc<TtyCore>, _winsize: WindowSize) -> Result<(), SystemError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -122,7 +122,7 @@ pub struct NTtyData {
|
|||||||
read_flags: StaticBitmap<NTTY_BUFSIZE>,
|
read_flags: StaticBitmap<NTTY_BUFSIZE>,
|
||||||
char_map: StaticBitmap<256>,
|
char_map: StaticBitmap<256>,
|
||||||
|
|
||||||
tty: Option<Weak<TtyCore>>,
|
tty: Weak<TtyCore>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NTtyData {
|
impl NTtyData {
|
||||||
@ -151,7 +151,7 @@ impl NTtyData {
|
|||||||
echo_buf: [0; NTTY_BUFSIZE],
|
echo_buf: [0; NTTY_BUFSIZE],
|
||||||
read_flags: StaticBitmap::new(),
|
read_flags: StaticBitmap::new(),
|
||||||
char_map: StaticBitmap::new(),
|
char_map: StaticBitmap::new(),
|
||||||
tty: None,
|
tty: Weak::default(),
|
||||||
no_room: false,
|
no_room: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1168,7 +1168,7 @@ impl NTtyData {
|
|||||||
nr: usize,
|
nr: usize,
|
||||||
) -> Result<usize, SystemError> {
|
) -> Result<usize, SystemError> {
|
||||||
let mut nr = nr;
|
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());
|
let space = tty.write_room(tty.core());
|
||||||
|
|
||||||
// 如果读取数量大于了可用空间,则取最小的为真正的写入数量
|
// 如果读取数量大于了可用空间,则取最小的为真正的写入数量
|
||||||
@ -1541,7 +1541,7 @@ impl NTtyData {
|
|||||||
impl TtyLineDiscipline for NTtyLinediscipline {
|
impl TtyLineDiscipline for NTtyLinediscipline {
|
||||||
fn open(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
|
fn open(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
|
||||||
// 反向绑定tty到disc
|
// 反向绑定tty到disc
|
||||||
self.disc_data().tty = Some(Arc::downgrade(&tty));
|
self.disc_data().tty = Arc::downgrade(&tty);
|
||||||
// 特定的tty设备在这里可能需要取消端口节流
|
// 特定的tty设备在这里可能需要取消端口节流
|
||||||
return self.set_termios(tty, None);
|
return self.set_termios(tty, None);
|
||||||
}
|
}
|
||||||
|
@ -242,6 +242,14 @@ impl TtyOperation for TtyConsoleDriverInner {
|
|||||||
fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resize(
|
||||||
|
&self,
|
||||||
|
_tty: Arc<TtyCore>,
|
||||||
|
_winsize: super::termios::WindowSize,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -634,11 +634,6 @@ impl FileDescriptorVec {
|
|||||||
///
|
///
|
||||||
/// - `fd` 文件描述符序号
|
/// - `fd` 文件描述符序号
|
||||||
pub fn drop_fd(&mut self, fd: i32) -> Result<(), SystemError> {
|
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)?;
|
self.get_file_by_fd(fd).ok_or(SystemError::EBADF)?;
|
||||||
|
|
||||||
// 把文件描述符数组对应位置设置为空
|
// 把文件描述符数组对应位置设置为空
|
||||||
|
@ -978,6 +978,8 @@ impl Syscall {
|
|||||||
.ok_or(SystemError::EBADF)?;
|
.ok_or(SystemError::EBADF)?;
|
||||||
|
|
||||||
let new_file = old_file.try_clone().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);
|
let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize);
|
||||||
return res;
|
return res;
|
||||||
@ -1029,6 +1031,8 @@ impl Syscall {
|
|||||||
.get_file_by_fd(oldfd)
|
.get_file_by_fd(oldfd)
|
||||||
.ok_or(SystemError::EBADF)?;
|
.ok_or(SystemError::EBADF)?;
|
||||||
let new_file = old_file.try_clone().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
|
let res = fd_table_guard
|
||||||
.alloc_fd(new_file, Some(newfd))
|
.alloc_fd(new_file, Some(newfd))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user