1use crate::fs::devpts::{DEVPTS_COUNT, get_device_type_for_pts};
6use crate::mutable_state::{state_accessor, state_implementation};
7use crate::task::{EventHandler, ProcessGroup, Session, WaitCanceler, WaitQueue, Waiter};
8use crate::vfs::buffers::{InputBuffer, InputBufferExt as _, OutputBuffer};
9use crate::vfs::{DirEntryHandle, FsString, Mounts};
10use derivative::Derivative;
11use macro_rules_attribute::apply;
12
13use line_discipline::{LineDiscipline, PendingSignals};
14use starnix_sync::{
15 DeviceTerminalsLock, LockBefore, LockDepMutex, LockDepRwLock, Locked, ProcessGroupState,
16 PtsIdsSetLock, RwLock,
17};
18use starnix_uapi::auth::FsCred;
19use starnix_uapi::device_id::DeviceId;
20use starnix_uapi::errors::Errno;
21use starnix_uapi::vfs::FdEvents;
22use starnix_uapi::{error, uapi};
23use std::collections::{BTreeSet, HashMap};
24use std::sync::{Arc, Weak};
25
26pub struct TtyState {
28 pub terminals: LockDepRwLock<HashMap<u32, Weak<Terminal>>, DeviceTerminalsLock>,
30
31 pts_ids_set: LockDepMutex<PtsIdsSet, PtsIdsSetLock>,
33}
34
35impl TtyState {
36 pub fn get_next_terminal(
38 self: &Arc<Self>,
39 dev_pts_root: DirEntryHandle,
40 creds: FsCred,
41 ) -> Result<Arc<Terminal>, Errno> {
42 let id = self.pts_ids_set.lock().acquire()?;
43 let terminal = Terminal::new(self.clone(), dev_pts_root, creds, id);
44 assert!(self.terminals.write().insert(id, Arc::downgrade(&terminal)).is_none());
45 Ok(terminal)
46 }
47
48 pub fn release_terminal(&self, id: u32) -> Result<(), Errno> {
50 assert!(self.terminals.write().remove(&id).is_some());
54 self.pts_ids_set.lock().release(id);
55 Ok(())
56 }
57}
58
59impl Default for TtyState {
60 fn default() -> Self {
61 Self {
62 terminals: LockDepRwLock::new(HashMap::new()),
63 pts_ids_set: LockDepMutex::new(PtsIdsSet::new(DEVPTS_COUNT)),
64 }
65 }
66}
67
68#[derive(Derivative)]
69#[derivative(Default)]
70#[derivative(Debug)]
71pub struct TerminalMutableState {
72 pub line_discipline: LineDiscipline,
73
74 main_wait_queue: WaitQueue,
76
77 replica_wait_queue: WaitQueue,
79
80 pub controller: Option<TerminalController>,
82}
83
84#[derive(Derivative)]
86#[derivative(Debug)]
87pub struct Terminal {
88 weak_self: Weak<Self>,
90
91 #[derivative(Debug = "ignore")]
93 state: Arc<TtyState>,
94
95 pub dev_pts_root: DirEntryHandle,
97
98 pub fscred: FsCred,
100
101 pub id: u32,
103
104 mutable_state: RwLock<TerminalMutableState>,
106}
107
108impl Terminal {
109 pub fn new(
110 state: Arc<TtyState>,
111 dev_pts_root: DirEntryHandle,
112 fscred: FsCred,
113 id: u32,
114 ) -> Arc<Self> {
115 Arc::new_cyclic(|weak_self| Self {
116 weak_self: weak_self.clone(),
117 state,
118 dev_pts_root,
119 fscred,
120 id,
121 mutable_state: RwLock::new(Default::default()),
122 })
123 }
124
125 pub fn to_owned(&self) -> Arc<Terminal> {
126 self.weak_self.upgrade().expect("This should never be called while releasing the terminal")
127 }
128
129 pub fn set_termios<L>(&self, locked: &mut Locked<L>, termios: uapi::termios)
131 where
132 L: LockBefore<ProcessGroupState>,
133 {
134 let signals = self.write().set_termios(termios);
135 self.send_signals(locked, signals);
136 }
137
138 pub fn main_close(&self) {
140 let id = FsString::from(self.id.to_string());
142 self.dev_pts_root.remove_child(id.as_ref(), &Mounts::new());
144 self.write().main_close();
145 }
146
147 pub fn main_open(&self) {
149 self.write().main_open();
150 }
151
152 pub fn main_wait_async(
154 &self,
155 waiter: &Waiter,
156 events: FdEvents,
157 handler: EventHandler,
158 ) -> WaitCanceler {
159 self.read().main_wait_async(waiter, events, handler)
160 }
161
162 pub fn main_query_events(&self) -> FdEvents {
164 self.read().main_query_events()
165 }
166
167 pub fn main_read<L>(
169 &self,
170 _locked: &mut Locked<L>,
171 data: &mut dyn OutputBuffer,
172 ) -> Result<usize, Errno>
173 where
174 L: LockBefore<ProcessGroupState>,
175 {
176 self.write().main_read(data)
177 }
178
179 pub fn main_write<L>(
181 &self,
182 locked: &mut Locked<L>,
183 data: &mut dyn InputBuffer,
184 ) -> Result<usize, Errno>
185 where
186 L: LockBefore<ProcessGroupState>,
187 {
188 let (bytes, signals) = self.write().main_write(data)?;
189 self.send_signals(locked, signals);
190 Ok(bytes)
191 }
192
193 pub fn replica_close(&self) {
195 self.write().replica_close();
196 }
197
198 pub fn replica_open(&self) {
200 self.write().replica_open();
201 }
202
203 pub fn replica_wait_async(
205 &self,
206 waiter: &Waiter,
207 events: FdEvents,
208 handler: EventHandler,
209 ) -> WaitCanceler {
210 self.read().replica_wait_async(waiter, events, handler)
211 }
212
213 pub fn replica_query_events(&self) -> FdEvents {
215 self.read().replica_query_events()
216 }
217
218 pub fn replica_read<L>(
220 &self,
221 _locked: &mut Locked<L>,
222 data: &mut dyn OutputBuffer,
223 ) -> Result<usize, Errno>
224 where
225 L: LockBefore<ProcessGroupState>,
226 {
227 self.write().replica_read(data)
228 }
229
230 pub fn replica_write<L>(
232 &self,
233 _locked: &mut Locked<L>,
234 data: &mut dyn InputBuffer,
235 ) -> Result<usize, Errno>
236 where
237 L: LockBefore<ProcessGroupState>,
238 {
239 self.write().replica_write(data)
240 }
241
242 fn send_signals<L>(&self, locked: &mut Locked<L>, signals: PendingSignals)
244 where
245 L: LockBefore<ProcessGroupState>,
246 {
247 let signals = signals.signals();
248 if !signals.is_empty() {
249 let process_group = {
250 let terminal_state = self.read();
251 let Some(controller) = terminal_state.controller.as_ref() else {
252 return;
253 };
254 let Some(session) = controller.session.upgrade() else {
255 return;
256 };
257 let Some(process_group) = session.read().get_foreground_process_group() else {
258 return;
259 };
260 process_group
261 };
262 process_group.send_signals(locked, signals);
263 }
264 }
265
266 pub fn device(&self) -> DeviceId {
267 get_device_type_for_pts(self.id)
268 }
269
270 state_accessor!(Terminal, mutable_state);
271}
272
273struct InputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::InputBuffer);
274
275impl<'a> line_discipline::InputBuffer for InputBufferWrapper<'a> {
276 fn available(&self) -> usize {
277 self.0.available()
278 }
279 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
280 self.0.read_to_vec_exact(size)
281 }
282}
283
284struct OutputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::OutputBuffer);
285
286impl<'a> line_discipline::OutputBuffer for OutputBufferWrapper<'a> {
287 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
288 self.0.write(data)
289 }
290}
291
292#[apply(state_implementation!)]
293impl TerminalMutableState<Base = Terminal> {
294 pub fn termios(&self) -> &uapi::termios {
296 self.line_discipline.termios()
297 }
298
299 pub fn get_available_read_size(&self, is_main: bool) -> usize {
302 self.line_discipline.get_available_read_size(is_main)
303 }
304
305 fn set_termios(&mut self, termios: uapi::termios) -> PendingSignals {
307 let old_canon_enabled = self.line_discipline.is_canon_enabled();
308 let signals = self.line_discipline.set_termios(termios);
309 if old_canon_enabled && !self.line_discipline.is_canon_enabled() {
310 self.notify_waiters();
311 }
312 signals
313 }
314
315 pub fn main_close(&mut self) {
317 self.line_discipline.main_close();
318 self.notify_waiters();
319 }
320
321 pub fn main_open(&mut self) {
323 self.line_discipline.main_open();
324 }
325
326 pub fn is_main_closed(&self) -> bool {
327 self.line_discipline.is_main_closed()
328 }
329
330 fn main_wait_async(
332 &self,
333 waiter: &Waiter,
334 events: FdEvents,
335 handler: EventHandler,
336 ) -> WaitCanceler {
337 self.main_wait_queue.wait_async_fd_events(waiter, events, handler)
338 }
339
340 fn main_query_events(&self) -> FdEvents {
342 self.line_discipline.main_query_events()
343 }
344
345 fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
347 let mut wrapper = OutputBufferWrapper(data);
348 let result = self.line_discipline.main_read(&mut wrapper)?;
349 self.notify_waiters();
350 Ok(result)
351 }
352
353 fn main_write(&mut self, data: &mut dyn InputBuffer) -> Result<(usize, PendingSignals), Errno> {
355 let mut wrapper = InputBufferWrapper(data);
356 let (result, signals) = self.line_discipline.main_write(&mut wrapper)?;
357 self.notify_waiters();
358 Ok((result, signals))
359 }
360
361 pub fn replica_close(&mut self) {
363 self.line_discipline.replica_close();
364 self.notify_waiters();
365 }
366
367 pub fn replica_open(&mut self) {
369 self.line_discipline.replica_open();
370 }
371
372 fn replica_wait_async(
374 &self,
375 waiter: &Waiter,
376 events: FdEvents,
377 handler: EventHandler,
378 ) -> WaitCanceler {
379 self.replica_wait_queue.wait_async_fd_events(waiter, events, handler)
380 }
381
382 fn replica_query_events(&self) -> FdEvents {
384 self.line_discipline.replica_query_events()
385 }
386
387 fn replica_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
389 let mut wrapper = OutputBufferWrapper(data);
390 let result = self.line_discipline.replica_read(&mut wrapper)?;
391 self.notify_waiters();
392 Ok(result)
393 }
394
395 fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
397 let mut wrapper = InputBufferWrapper(data);
398 let result = self.line_discipline.replica_write(&mut wrapper)?;
399 self.notify_waiters();
400 Ok(result)
401 }
402
403 fn notify_waiters(&mut self) {
405 let main_events = self.line_discipline.main_query_events();
406 if main_events.bits() != 0 {
407 self.main_wait_queue.notify_fd_events(main_events);
408 }
409 let replica_events = self.line_discipline.replica_query_events();
410 if replica_events.bits() != 0 {
411 self.replica_wait_queue.notify_fd_events(replica_events);
412 }
413 }
414}
415
416impl Drop for Terminal {
417 fn drop(&mut self) {
418 self.state.release_terminal(self.id).unwrap()
419 }
420}
421
422#[derive(Debug)]
425pub struct TerminalController {
426 pub session: Weak<Session>,
427}
428
429impl TerminalController {
430 pub fn new(session: &Arc<Session>) -> Option<Self> {
431 Some(Self { session: Arc::downgrade(&session) })
432 }
433
434 pub fn get_foreground_process_group(&self) -> Option<Arc<ProcessGroup>> {
435 self.session.upgrade().and_then(|session| session.read().get_foreground_process_group())
436 }
437}
438
439#[derive(Debug)]
440struct PtsIdsSet {
441 pts_count: u32,
442 next_id: u32,
443 reclaimed_ids: BTreeSet<u32>,
444}
445
446impl PtsIdsSet {
447 fn new(pts_count: u32) -> Self {
448 Self { pts_count, next_id: 0, reclaimed_ids: BTreeSet::new() }
449 }
450
451 fn release(&mut self, id: u32) {
452 assert!(self.reclaimed_ids.insert(id))
453 }
454
455 fn acquire(&mut self) -> Result<u32, Errno> {
456 match self.reclaimed_ids.iter().next() {
457 Some(e) => {
458 let value = *e;
459 self.reclaimed_ids.remove(&value);
460 Ok(value)
461 }
462 None => {
463 if self.next_id < self.pts_count {
464 let id = self.next_id;
465 self.next_id += 1;
466 Ok(id)
467 } else {
468 error!(ENOSPC)
469 }
470 }
471 }
472 }
473}