DragonOS/kernel/src/driver/tty/tty_job_control.rs
火花 bc9bb9607f
Feat(tty): Supplement process group logic (#1139)
* 添加busybox的编译

* 完善tty job control的逻辑

* 修改copy_sighand的逻辑,符合Linux语义

* 以busybox作为启动shell去运行

* 修改setsid的逻辑

* 解决前台进程组无法处理信号的问题

* 移除ProcessBasicInfo其中的pgid和sid信息

* 修改setsid

* 新增get_pcb_info

* 在etc目录下新增必要的文件

* 改用busybox init作为引导程序

* 恢复dragonreach文件

* 修改busybox编译选项,能够读取环境变量

* 先让SYS_RT_SIGTIMEDWAIT返回Ok(0),能够正常进入系统

* 一些小更改

* 删除get_pcb_info

* 增加对默认termios的判断

* 完成backspace的修复

* 更改inittab,在shell启动之后更改termios

* 增加executable_path信息

* 补充proc下的exe链接文件以及读取逻辑

* 更改PosixTermios,使用stty完成erase的设置

* 用busybox作为引导程序

* 修改波特率的获取

* 修改函数方法

* 在baud_rate方法中添加对于cbaud的与操作

* 为rv64下的SigSet实现From<Signal>

* refactor(driver): 移除`#[derive(Debug)]`并手动实现`Debug` trait

移除`VirtIOBlkDevice`、`VirtIOConsoleDevice`和`VirtIONetDevice`的`#[derive(Debug)]`,并手动实现`Debug` trait以提供更详细的调试信息。

Co-authored-by: longjin <longjin@DragonOS.org>
2025-05-08 15:05:02 +08:00

217 lines
6.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use alloc::sync::Arc;
use system_error::SystemError;
use crate::{
arch::ipc::signal::{SigSet, Signal},
mm::VirtAddr,
process::{process_group::Pgid, Pid, ProcessFlags, ProcessManager},
syscall::{
user_access::{UserBufferReader, UserBufferWriter},
Syscall,
},
};
use super::tty_core::{TtyCore, TtyIoctlCmd};
pub struct TtyJobCtrlManager;
impl TtyJobCtrlManager {
/// ### 设置当前进程的tty
pub fn proc_set_tty(tty: Arc<TtyCore>) {
let core = tty.core();
let pcb = ProcessManager::current_pcb();
let mut ctrl = core.contorl_info_irqsave();
ctrl.set_info_by_pcb(pcb.clone());
drop(ctrl);
let mut singal = pcb.sig_info_mut();
singal.set_tty(Some(tty.clone()));
}
/// ### 检查tty
pub fn tty_check_change(tty: Arc<TtyCore>, sig: Signal) -> Result<(), SystemError> {
let pcb = ProcessManager::current_pcb();
if pcb.sig_info_irqsave().tty().is_none()
|| !Arc::ptr_eq(&pcb.sig_info_irqsave().tty().unwrap(), &tty)
{
return Ok(());
}
let pgid = pcb.pgid();
let ctrl = tty.core().contorl_info_irqsave();
let tty_pgid = ctrl.pgid;
drop(ctrl);
if tty_pgid.is_some() && tty_pgid.unwrap() != pgid {
if pcb
.sig_info_irqsave()
.sig_blocked()
.contains(SigSet::from(sig))
|| pcb.sig_struct_irqsave().handlers[sig as usize - 1].is_ignore()
{
// 忽略该信号
if sig == Signal::SIGTTIN {
return Err(SystemError::EIO);
}
} else if ProcessManager::is_current_pgrp_orphaned() {
return Err(SystemError::EIO);
} else {
Syscall::kill_process_group(pgid, sig)?;
ProcessManager::current_pcb()
.flags()
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
log::debug!("job_ctrl_ioctl: kill. pgid: {pgid}, tty_pgid: {tty_pgid:?}");
return Err(SystemError::ERESTARTSYS);
}
}
Ok(())
}
pub fn job_ctrl_ioctl(
real_tty: Arc<TtyCore>,
cmd: u32,
arg: usize,
) -> Result<usize, SystemError> {
match cmd {
TtyIoctlCmd::TIOCSPGRP => Self::tiocspgrp(real_tty, arg),
TtyIoctlCmd::TIOCGPGRP => Self::tiocgpgrp(real_tty, arg),
TtyIoctlCmd::TIOCGSID => Self::tiocgsid(real_tty, arg),
TtyIoctlCmd::TIOCSCTTY => Self::tiocsctty(real_tty),
_ => {
return Err(SystemError::ENOIOCTLCMD);
}
}
}
fn tiocsctty(real_tty: Arc<TtyCore>) -> Result<usize, SystemError> {
let current = ProcessManager::current_pcb();
// log::debug!("job_ctrl_ioctl: TIOCSCTTY,current: {:?}", current.pid());
if current.is_session_leader()
&& real_tty.core().contorl_info_irqsave().session.unwrap() == current.sid()
{
return Ok(0);
}
if !current.is_session_leader() || current.sig_info_irqsave().tty().is_some() {
return Err(SystemError::EPERM);
}
//todo 权限检查?
// https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/tty/tty_jobctrl.c#tiocsctty
if let Some(sid) = real_tty.core().contorl_info_irqsave().session {
//todo 目前只有一个tty设备所以选择复用1号进程的tty因此修改1号进程的tty暂时被允许
if sid != Pid::new(1) {
return Err(SystemError::EPERM);
}
}
Self::proc_set_tty(real_tty);
Ok(0)
}
fn tiocgpgrp(real_tty: Arc<TtyCore>, arg: usize) -> Result<usize, SystemError> {
// log::debug!("job_ctrl_ioctl: TIOCGPGRP");
let current = ProcessManager::current_pcb();
if current.sig_info_irqsave().tty().is_some()
&& !Arc::ptr_eq(&current.sig_info_irqsave().tty().unwrap(), &real_tty)
{
return Err(SystemError::ENOTTY);
}
let mut user_writer = UserBufferWriter::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
user_writer.copy_one_to_user(
&(real_tty
.core()
.contorl_info_irqsave()
.pgid
.unwrap_or(Pid::new(1))
.data() as i32),
0,
)?;
return Ok(0);
}
fn tiocgsid(real_tty: Arc<TtyCore>, arg: usize) -> Result<usize, SystemError> {
// log::debug!("job_ctrl_ioctl: TIOCGSID");
let current = ProcessManager::current_pcb();
if current.sig_info_irqsave().tty().is_some()
&& !Arc::ptr_eq(&current.sig_info_irqsave().tty().unwrap(), &real_tty)
{
return Err(SystemError::ENOTTY);
}
let guard = real_tty.core().contorl_info_irqsave();
if guard.session.is_none() {
return Err(SystemError::ENOTTY);
}
let sid = guard.session.unwrap();
drop(guard);
let mut user_writer = UserBufferWriter::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
user_writer.copy_one_to_user(&(sid.data() as i32), 0)?;
return Ok(0);
}
fn tiocspgrp(real_tty: Arc<TtyCore>, arg: usize) -> Result<usize, SystemError> {
// log::debug!("job_ctrl_ioctl: TIOCSPGRP");
match Self::tty_check_change(real_tty.clone(), Signal::SIGTTOU) {
Ok(_) => {}
Err(e) => {
if e == SystemError::EIO {
return Err(SystemError::ENOTTY);
}
return Err(e);
}
};
let user_reader = UserBufferReader::new(
VirtAddr::new(arg).as_ptr::<i32>(),
core::mem::size_of::<i32>(),
true,
)?;
let pgrp = user_reader.read_one_from_user::<i32>(0)?;
let current = ProcessManager::current_pcb();
let mut ctrl = real_tty.core().contorl_info_irqsave();
if current.sig_info_irqsave().tty().is_none()
|| !Arc::ptr_eq(
&current.sig_info_irqsave().tty().clone().unwrap(),
&real_tty,
)
|| ctrl.session.is_none()
|| ctrl.session.unwrap() != current.sid()
{
return Err(SystemError::ENOTTY);
}
let pg = ProcessManager::find_process_group(Pgid::from(*pgrp as usize));
if pg.is_none() {
return Err(SystemError::ESRCH);
} else if !Arc::ptr_eq(&pg.unwrap().session().unwrap(), &current.session().unwrap()) {
return Err(SystemError::EPERM);
}
ctrl.pgid = Some(Pid::from(*pgrp as usize));
return Ok(0);
}
}