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