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