Browse Source

完善pty,目前pty能够支持ssh (#708)

GnoCiYeH 11 months ago
parent
commit
9365e8017b

+ 69 - 5
kernel/src/driver/tty/pty/unix98pty.rs

@@ -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},
@@ -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 {
@@ -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> {
@@ -171,8 +217,8 @@ 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());
@@ -180,6 +226,24 @@ impl TtyOperation for Unix98PtyDriverInner {
 
         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(

+ 1 - 1
kernel/src/driver/tty/termios.rs

@@ -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,

+ 26 - 1
kernel/src/driver/tty/tty_core.rs

@@ -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},
@@ -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);
@@ -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
@@ -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)]
@@ -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)
@@ -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! {

+ 20 - 3
kernel/src/driver/tty/tty_device.rs

@@ -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;
@@ -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);

+ 4 - 2
kernel/src/driver/tty/tty_driver.rs

@@ -27,7 +27,7 @@ use crate::{
 };
 
 use super::{
-    termios::Termios,
+    termios::{Termios, WindowSize},
     tty_core::{TtyCore, TtyCoreData},
     tty_ldisc::TtyLdiscManager,
     tty_port::{DefaultTtyPort, TtyPort},
@@ -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)
     }
@@ -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)]

+ 4 - 4
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -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 {
@@ -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,
         }
     }
@@ -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());
 
         // 如果读取数量大于了可用空间,则取最小的为真正的写入数量
@@ -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);
     }

+ 8 - 0
kernel/src/driver/tty/virtual_terminal/mod.rs

@@ -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)]

+ 0 - 5
kernel/src/filesystem/vfs/file.rs

@@ -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)?;
 
         // 把文件描述符数组对应位置设置为空

+ 4 - 0
kernel/src/filesystem/vfs/syscall.rs

@@ -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;
@@ -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))