1use crate::mutable_state::{state_accessor, state_implementation};
6use crate::task::{EventHandler, Pid, WaitCanceler, WaitQueue, Waiter};
7use crate::vfs::buffers::{InputBuffer, InputBufferExt as _, OutputBuffer};
8use crate::vfs::{DirEntryHandle, FsString, Mounts};
9use derivative::Derivative;
10pub use line_discipline::TerminalSide;
11use line_discipline::{LineDiscipline, PendingSignals};
12use macro_rules_attribute::apply;
13use starnix_sync::{DeviceTerminalsLock, LockDepMutex, LockDepRwLock, PtsIdsSetLock};
14use starnix_uapi::auth::FsCred;
15use starnix_uapi::device_id::DeviceId;
16use starnix_uapi::errors::Errno;
17use starnix_uapi::signals::{SIGCONT, SIGHUP, Signal};
18use starnix_uapi::vfs::FdEvents;
19use starnix_uapi::{error, pid_t, uapi};
20use std::collections::{BTreeSet, HashMap};
21use std::sync::{Arc, Weak};
22
23const DEVPTS_FIRST_MAJOR: u32 = 136;
24const DEVPTS_MAJOR_COUNT: u32 = 4;
25pub const DEVPTS_COUNT: u32 = DEVPTS_MAJOR_COUNT * 256;
26
27pub fn get_device_type_for_pts(id: u32) -> DeviceId {
29 DeviceId::new(DEVPTS_FIRST_MAJOR + id / 256, id % 256)
30}
31
32pub struct TtyState {
34 pub terminals: LockDepRwLock<HashMap<u32, Weak<Terminal>>, DeviceTerminalsLock>,
36
37 pts_ids_set: LockDepMutex<PtsIdsSet, PtsIdsSetLock>,
39}
40
41impl TtyState {
42 pub fn get_next_terminal(
44 self: &Arc<Self>,
45 dev_pts_root: DirEntryHandle,
46 creds: FsCred,
47 ) -> Result<Arc<Terminal>, Errno> {
48 let id = self.pts_ids_set.lock().acquire()?;
49 let terminal = Terminal::new(self.clone(), dev_pts_root, creds, id);
50 assert!(self.terminals.write().insert(id, Arc::downgrade(&terminal)).is_none());
51 Ok(terminal)
52 }
53
54 pub fn release_terminal(&self, id: u32) -> Result<(), Errno> {
56 assert!(self.terminals.write().remove(&id).is_some());
60 self.pts_ids_set.lock().release(id);
61 Ok(())
62 }
63}
64
65impl Default for TtyState {
66 fn default() -> Self {
67 Self { terminals: Default::default(), pts_ids_set: PtsIdsSet::new(DEVPTS_COUNT).into() }
68 }
69}
70
71#[derive(Derivative)]
72#[derivative(Default)]
73#[derivative(Debug)]
74pub struct TerminalMutableState {
75 pub line_discipline: LineDiscipline,
76
77 main_wait_queue: WaitQueue,
79
80 replica_wait_queue: WaitQueue,
82
83 pub controlling_session: Option<ControllingSession>,
85}
86
87#[derive(Derivative)]
89#[derivative(Debug)]
90pub struct Terminal {
91 weak_self: Weak<Self>,
93
94 #[derivative(Debug = "ignore")]
96 state: Arc<TtyState>,
97
98 pub dev_pts_root: DirEntryHandle,
100
101 pub fscred: FsCred,
103
104 pub id: u32,
106
107 mutable_state:
109 starnix_sync::LockDepRwLock<TerminalMutableState, starnix_sync::TerminalMutableStateLock>,
110}
111
112impl Terminal {
113 pub fn new(
114 state: Arc<TtyState>,
115 dev_pts_root: DirEntryHandle,
116 fscred: FsCred,
117 id: u32,
118 ) -> Arc<Self> {
119 Arc::new_cyclic(|weak_self| Self {
120 weak_self: weak_self.clone(),
121 state,
122 dev_pts_root,
123 fscred,
124 id,
125 mutable_state: Default::default(),
126 })
127 }
128
129 pub fn to_owned(&self) -> Arc<Terminal> {
130 self.weak_self.upgrade().expect("This should never be called while releasing the terminal")
131 }
132
133 pub fn set_termios(&self, termios: uapi::termios2) {
135 let signals = self.write().set_termios(termios);
136 self.send_signals(signals.signals());
137 }
138
139 pub fn flush(&self, is_main: bool, arg: u32) -> Result<(), Errno> {
140 self.write().flush(is_main, arg)
141 }
142
143 pub fn main_close(&self) {
145 let id = FsString::from(self.id.to_string());
147 self.dev_pts_root.remove_child(id.as_ref(), &Mounts::new());
149 self.write().main_close();
150 }
151
152 pub fn main_open(&self) {
154 self.write().main_open();
155 }
156
157 pub fn main_wait_async(
159 &self,
160 waiter: &Waiter,
161 events: FdEvents,
162 handler: EventHandler,
163 ) -> WaitCanceler {
164 self.read().main_wait_async(waiter, events, handler)
165 }
166
167 pub fn main_query_events(&self) -> FdEvents {
169 self.read().main_query_events()
170 }
171
172 pub fn main_read(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
174 self.write().main_read(data)
175 }
176
177 pub fn main_write(&self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
179 let (bytes, signals) = self.write().main_write(data)?;
180 self.send_signals(signals.signals());
181 Ok(bytes)
182 }
183
184 pub fn replica_close(&self) {
186 self.write().replica_close();
187 }
188
189 pub fn replica_open(&self) {
191 self.write().replica_open();
192 }
193
194 pub fn replica_wait_async(
196 &self,
197 waiter: &Waiter,
198 events: FdEvents,
199 handler: EventHandler,
200 ) -> WaitCanceler {
201 self.read().replica_wait_async(waiter, events, handler)
202 }
203
204 pub fn replica_query_events(&self) -> FdEvents {
206 self.read().replica_query_events()
207 }
208
209 pub fn replica_read(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
211 let (bytes, signals) = self.write().replica_read(data)?;
212 self.send_signals(signals.signals());
213 Ok(bytes)
214 }
215
216 pub fn replica_write(&self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
218 self.write().replica_write(data)
219 }
220
221 pub fn disassociate_controlling_session(&self) {
227 self.disassociate_controlling_session_if(None, None);
228 }
229
230 pub fn disassociate_controlling_session_if(
234 &self,
235 expected_session: Option<&Pid>,
236 side: Option<TerminalSide>,
237 ) {
238 let controlling_session = {
239 let mut terminal_state = self.write();
240 if expected_session.is_none_or(|sid| terminal_state.controlling_session() == Some(sid))
241 {
242 terminal_state.controlling_session.take()
243 } else {
244 None
245 }
246 };
247 if let Some(controlling_session) = controlling_session {
248 controlling_session.disassociate(self, side);
249 }
250 }
251
252 pub fn send_signals(&self, signals: &[Signal]) {
257 if signals.is_empty() {
258 return;
259 }
260 let foreground_pg = {
261 let state = self.read();
262 state.controlling_session.as_ref().map(|cs| cs.foreground_process_group.clone())
263 };
264 if let Some(pgid) = foreground_pg {
265 pgid.send_signals_to_pgid(signals);
266 }
267 }
268
269 pub fn device(&self) -> DeviceId {
270 get_device_type_for_pts(self.id)
271 }
272
273 state_accessor!(Terminal, mutable_state);
274}
275
276struct InputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::InputBuffer);
277
278impl<'a> line_discipline::InputBuffer for InputBufferWrapper<'a> {
279 fn available(&self) -> usize {
280 self.0.available()
281 }
282 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
283 self.0.read_to_vec_exact(size)
284 }
285}
286
287struct OutputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::OutputBuffer);
288
289impl<'a> line_discipline::OutputBuffer for OutputBufferWrapper<'a> {
290 fn available(&self) -> usize {
291 self.0.available()
292 }
293 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
294 self.0.write(data)
295 }
296}
297
298#[apply(state_implementation!)]
299impl TerminalMutableState<Base = Terminal> {
300 pub fn controlling_session(&self) -> Option<&Pid> {
302 self.controlling_session.as_ref().map(|cs| &cs.session)
303 }
304
305 pub fn termios(&self) -> &uapi::termios2 {
307 self.line_discipline.termios()
308 }
309
310 pub fn set_packet_mode(&mut self, enabled: bool) {
311 if enabled != self.line_discipline.is_packet_mode_enabled() {
312 self.line_discipline.set_packet_mode(enabled);
313 self.notify_waiters();
314 }
315 }
316
317 pub fn get_available_read_size(&self, is_main: bool) -> usize {
320 self.line_discipline.get_available_read_size(TerminalSide::from(is_main))
321 }
322
323 fn set_termios(&mut self, termios: uapi::termios2) -> PendingSignals {
325 let signals = self.line_discipline.set_termios(termios);
326 self.notify_waiters();
327 signals
328 }
329
330 pub fn flush(&mut self, is_main: bool, arg: u32) -> Result<(), Errno> {
331 self.line_discipline.flush(TerminalSide::from(is_main), arg)?;
332 self.notify_waiters();
333 Ok(())
334 }
335
336 pub fn main_close(&mut self) {
338 self.line_discipline.main_close();
339 self.notify_waiters();
340 }
341
342 pub fn main_open(&mut self) {
344 self.line_discipline.main_open();
345 }
346
347 pub fn is_main_closed(&self) -> bool {
348 self.line_discipline.is_main_closed()
349 }
350
351 fn main_wait_async(
353 &self,
354 waiter: &Waiter,
355 events: FdEvents,
356 handler: EventHandler,
357 ) -> WaitCanceler {
358 self.main_wait_queue.wait_async_fd_events(waiter, events, handler)
359 }
360
361 fn main_query_events(&self) -> FdEvents {
363 self.line_discipline.main_query_events()
364 }
365
366 fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
368 let mut wrapper = OutputBufferWrapper(data);
369 let result = self.line_discipline.main_read(&mut wrapper)?;
370 self.notify_waiters();
371 Ok(result)
372 }
373
374 fn main_write(&mut self, data: &mut dyn InputBuffer) -> Result<(usize, PendingSignals), Errno> {
378 let mut wrapper = InputBufferWrapper(data);
379 let (result, signals) = self.line_discipline.main_write(&mut wrapper)?;
380 self.notify_waiters();
381 Ok((result, signals))
382 }
383
384 pub fn replica_close(&mut self) {
386 self.line_discipline.replica_close();
387 self.notify_waiters();
388 }
389
390 pub fn replica_open(&mut self) {
392 self.line_discipline.replica_open();
393 }
394
395 fn replica_wait_async(
397 &self,
398 waiter: &Waiter,
399 events: FdEvents,
400 handler: EventHandler,
401 ) -> WaitCanceler {
402 self.replica_wait_queue.wait_async_fd_events(waiter, events, handler)
403 }
404
405 fn replica_query_events(&self) -> FdEvents {
407 self.line_discipline.replica_query_events()
408 }
409
410 fn replica_read(
415 &mut self,
416 data: &mut dyn OutputBuffer,
417 ) -> Result<(usize, PendingSignals), Errno> {
418 let mut wrapper = OutputBufferWrapper(data);
419 let (result, signals) = self.line_discipline.replica_read(&mut wrapper)?;
420 self.notify_waiters();
421 Ok((result, signals))
422 }
423
424 fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
426 let mut wrapper = InputBufferWrapper(data);
427 let result = self.line_discipline.replica_write(&mut wrapper)?;
428 self.notify_waiters();
429 Ok(result)
430 }
431
432 fn notify_waiters(&mut self) {
434 let main_events = self.line_discipline.main_query_events();
435 if main_events.bits() != 0 {
436 self.main_wait_queue.notify_fd_events(main_events);
437 }
438 let replica_events = self.line_discipline.replica_query_events();
439 if replica_events.bits() != 0 {
440 self.replica_wait_queue.notify_fd_events(replica_events);
441 }
442 }
443}
444
445impl Drop for Terminal {
446 fn drop(&mut self) {
447 self.state.release_terminal(self.id).unwrap()
448 }
449}
450
451#[derive(Clone, Debug)]
453pub struct ControllingTerminal {
454 pub terminal: Arc<Terminal>,
456 pub side: TerminalSide,
458}
459
460impl ControllingTerminal {
461 pub fn new(terminal: &Terminal, side: TerminalSide) -> Self {
462 Self { terminal: terminal.to_owned(), side }
463 }
464
465 pub fn matches(&self, terminal: &Terminal, side: TerminalSide) -> bool {
466 std::ptr::eq(terminal, Arc::as_ptr(&self.terminal)) && side == self.side
467 }
468}
469
470#[derive(Clone, Debug)]
472pub struct ControllingSession {
473 pub session: Pid,
475
476 pub foreground_process_group: Pid,
478}
479
480impl ControllingSession {
481 pub fn new(session: &Pid, foreground_pgrp: &Pid) -> Self {
482 Self { session: Arc::clone(session), foreground_process_group: Arc::clone(foreground_pgrp) }
483 }
484
485 pub fn foreground_process_group(&self) -> &Pid {
486 &self.foreground_process_group
487 }
488
489 pub fn foreground_pgid(&self) -> pid_t {
490 self.foreground_process_group.id
491 }
492
493 pub fn set_foreground_process_group(&mut self, pgid: Pid) {
494 self.foreground_process_group = pgid;
495 }
496
497 pub fn disassociate(self, terminal: &Terminal, side: Option<TerminalSide>) {
500 self.session.clear_controlling_terminal(Some((terminal, side)));
501 self.foreground_process_group.send_signals_to_pgid(&[SIGHUP, SIGCONT]);
502 }
503}
504
505#[derive(Debug)]
506struct PtsIdsSet {
507 pts_count: u32,
508 next_id: u32,
509 reclaimed_ids: BTreeSet<u32>,
510}
511
512impl PtsIdsSet {
513 fn new(pts_count: u32) -> Self {
514 Self { pts_count, next_id: 0, reclaimed_ids: BTreeSet::new() }
515 }
516
517 fn release(&mut self, id: u32) {
518 assert!(self.reclaimed_ids.insert(id))
519 }
520
521 fn acquire(&mut self) -> Result<u32, Errno> {
522 match self.reclaimed_ids.iter().next() {
523 Some(e) => {
524 let value = *e;
525 self.reclaimed_ids.remove(&value);
526 Ok(value)
527 }
528 None => {
529 if self.next_id < self.pts_count {
530 let id = self.next_id;
531 self.next_id += 1;
532 Ok(id)
533 } else {
534 error!(ENOSPC)
535 }
536 }
537 }
538 }
539}