1 use alloc::sync::Arc; 2 use system_error::SystemError; 3 4 use crate::{ 5 arch::ipc::signal::{SigSet, Signal}, 6 mm::VirtAddr, 7 process::{Pid, ProcessManager}, 8 syscall::{ 9 user_access::{UserBufferReader, UserBufferWriter}, 10 Syscall, 11 }, 12 }; 13 14 use super::tty_core::{TtyCore, TtyIoctlCmd}; 15 16 pub struct TtyJobCtrlManager; 17 18 impl TtyJobCtrlManager { 19 /// ### 设置当前进程的tty 20 pub fn proc_set_tty(tty: Arc<TtyCore>) { 21 let core = tty.core(); 22 let mut ctrl = core.contorl_info_irqsave(); 23 let pcb = ProcessManager::current_pcb(); 24 25 ctrl.session = Some(pcb.basic().sid()); 26 27 assert!(pcb.sig_info_irqsave().tty().is_none()); 28 29 let mut singal = pcb.sig_info_mut(); 30 drop(ctrl); 31 singal.set_tty(Some(tty.clone())); 32 } 33 34 /// ### 检查tty 35 pub fn tty_check_change(tty: Arc<TtyCore>, sig: Signal) -> Result<(), SystemError> { 36 let pcb = ProcessManager::current_pcb(); 37 38 if pcb.sig_info_irqsave().tty().is_none() 39 || !Arc::ptr_eq(&pcb.sig_info_irqsave().tty().unwrap(), &tty) 40 { 41 return Ok(()); 42 } 43 44 let core = tty.core(); 45 let ctrl = core.contorl_info_irqsave(); 46 47 // todo pgid 48 let pgid = pcb.pid(); 49 let tty_pgid = ctrl.pgid; 50 51 if tty_pgid.is_some() && tty_pgid.unwrap() != pgid { 52 if pcb 53 .sig_info_irqsave() 54 .sig_block() 55 .contains(SigSet::from_bits_truncate(1 << sig as u64)) 56 || pcb.sig_struct_irqsave().handlers[sig as usize].is_ignore() 57 { 58 // 忽略该信号 59 if sig == Signal::SIGTTIN { 60 return Err(SystemError::EIO); 61 } 62 } else { 63 // 暂时使用kill而不是killpg 64 Syscall::kill(pgid, sig as i32)?; 65 return Err(SystemError::ERESTART); 66 } 67 } 68 69 Ok(()) 70 } 71 72 pub fn job_ctrl_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> { 73 match cmd { 74 TtyIoctlCmd::TIOCSPGRP => { 75 match Self::tty_check_change(tty.clone(), Signal::SIGTTOU) { 76 Ok(_) => {} 77 Err(e) => { 78 if e == SystemError::EIO { 79 return Err(SystemError::ENOTTY); 80 } 81 return Err(e); 82 } 83 }; 84 85 let user_reader = UserBufferReader::new( 86 VirtAddr::new(arg).as_ptr::<i32>(), 87 core::mem::size_of::<i32>(), 88 true, 89 )?; 90 91 let pgrp = user_reader.read_one_from_user::<i32>(0)?; 92 93 let current = ProcessManager::current_pcb(); 94 95 let mut ctrl = tty.core().contorl_info_irqsave(); 96 97 if current.sig_info_irqsave().tty().is_none() 98 || !Arc::ptr_eq(¤t.sig_info_irqsave().tty().clone().unwrap(), &tty) 99 || ctrl.session.is_none() 100 || ctrl.session.unwrap() != current.basic().sid() 101 { 102 return Err(SystemError::ENOTTY); 103 } 104 105 ctrl.pgid = Some(Pid::new(*pgrp as usize)); 106 107 return Ok(0); 108 } 109 110 TtyIoctlCmd::TIOCGPGRP => { 111 let current = ProcessManager::current_pcb(); 112 if current.sig_info_irqsave().tty().is_some() 113 && !Arc::ptr_eq(¤t.sig_info_irqsave().tty().unwrap(), &tty) 114 { 115 return Err(SystemError::ENOTTY); 116 } 117 118 let mut user_writer = UserBufferWriter::new( 119 VirtAddr::new(arg).as_ptr::<i32>(), 120 core::mem::size_of::<i32>(), 121 true, 122 )?; 123 124 user_writer.copy_one_to_user( 125 &(tty 126 .core() 127 .contorl_info_irqsave() 128 .pgid 129 .unwrap_or(Pid::new(0)) 130 .data() as i32), 131 0, 132 )?; 133 134 return Ok(0); 135 } 136 137 _ => { 138 return Err(SystemError::ENOIOCTLCMD); 139 } 140 } 141 } 142 } 143