xref: /DragonOS/kernel/src/driver/tty/tty_job_control.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
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(&current.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(&current.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