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