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