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,
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 { terminals: Default::default(), pts_ids_set: PtsIdsSet::new(DEVPTS_COUNT).into() }
62 }
63}
64
65#[derive(Derivative)]
66#[derivative(Default)]
67#[derivative(Debug)]
68pub struct TerminalMutableState {
69 pub line_discipline: LineDiscipline,
70
71 main_wait_queue: WaitQueue,
73
74 replica_wait_queue: WaitQueue,
76
77 pub controller: Option<TerminalController>,
79}
80
81#[derive(Derivative)]
83#[derivative(Debug)]
84pub struct Terminal {
85 weak_self: Weak<Self>,
87
88 #[derivative(Debug = "ignore")]
90 state: Arc<TtyState>,
91
92 pub dev_pts_root: DirEntryHandle,
94
95 pub fscred: FsCred,
97
98 pub id: u32,
100
101 mutable_state:
103 starnix_sync::LockDepRwLock<TerminalMutableState, starnix_sync::TerminalMutableStateLock>,
104}
105
106impl Terminal {
107 pub fn new(
108 state: Arc<TtyState>,
109 dev_pts_root: DirEntryHandle,
110 fscred: FsCred,
111 id: u32,
112 ) -> Arc<Self> {
113 Arc::new_cyclic(|weak_self| Self {
114 weak_self: weak_self.clone(),
115 state,
116 dev_pts_root,
117 fscred,
118 id,
119 mutable_state: Default::default(),
120 })
121 }
122
123 pub fn to_owned(&self) -> Arc<Terminal> {
124 self.weak_self.upgrade().expect("This should never be called while releasing the terminal")
125 }
126
127 pub fn set_termios<L>(&self, locked: &mut Locked<L>, termios: uapi::termios2)
129 where
130 L: LockBefore<ProcessGroupState>,
131 {
132 let signals = self.write().set_termios(termios);
133 self.send_signals(locked, signals);
134 }
135
136 pub fn flush(&self, is_main: bool, arg: u32) -> Result<(), Errno> {
137 self.write().flush(is_main, arg)
138 }
139
140 pub fn main_close(&self) {
142 let id = FsString::from(self.id.to_string());
144 self.dev_pts_root.remove_child(id.as_ref(), &Mounts::new());
146 self.write().main_close();
147 }
148
149 pub fn main_open(&self) {
151 self.write().main_open();
152 }
153
154 pub fn main_wait_async(
156 &self,
157 waiter: &Waiter,
158 events: FdEvents,
159 handler: EventHandler,
160 ) -> WaitCanceler {
161 self.read().main_wait_async(waiter, events, handler)
162 }
163
164 pub fn main_query_events(&self) -> FdEvents {
166 self.read().main_query_events()
167 }
168
169 pub fn main_read<L>(
171 &self,
172 _locked: &mut Locked<L>,
173 data: &mut dyn OutputBuffer,
174 ) -> Result<usize, Errno>
175 where
176 L: LockBefore<ProcessGroupState>,
177 {
178 self.write().main_read(data)
179 }
180
181 pub fn main_write<L>(
183 &self,
184 locked: &mut Locked<L>,
185 data: &mut dyn InputBuffer,
186 ) -> Result<usize, Errno>
187 where
188 L: LockBefore<ProcessGroupState>,
189 {
190 let (bytes, signals) = self.write().main_write(data)?;
191 self.send_signals(locked, signals);
192 Ok(bytes)
193 }
194
195 pub fn replica_close(&self) {
197 self.write().replica_close();
198 }
199
200 pub fn replica_open(&self) {
202 self.write().replica_open();
203 }
204
205 pub fn replica_wait_async(
207 &self,
208 waiter: &Waiter,
209 events: FdEvents,
210 handler: EventHandler,
211 ) -> WaitCanceler {
212 self.read().replica_wait_async(waiter, events, handler)
213 }
214
215 pub fn replica_query_events(&self) -> FdEvents {
217 self.read().replica_query_events()
218 }
219
220 pub fn replica_read<L>(
222 &self,
223 _locked: &mut Locked<L>,
224 data: &mut dyn OutputBuffer,
225 ) -> Result<usize, Errno>
226 where
227 L: LockBefore<ProcessGroupState>,
228 {
229 self.write().replica_read(data)
230 }
231
232 pub fn replica_write<L>(
234 &self,
235 _locked: &mut Locked<L>,
236 data: &mut dyn InputBuffer,
237 ) -> Result<usize, Errno>
238 where
239 L: LockBefore<ProcessGroupState>,
240 {
241 self.write().replica_write(data)
242 }
243
244 fn send_signals<L>(&self, locked: &mut Locked<L>, signals: PendingSignals)
246 where
247 L: LockBefore<ProcessGroupState>,
248 {
249 let signals = signals.signals();
250 if !signals.is_empty() {
251 let process_group = {
252 let terminal_state = self.read();
253 let Some(controller) = terminal_state.controller.as_ref() else {
254 return;
255 };
256 let Some(session) = controller.session.upgrade() else {
257 return;
258 };
259 let Some(process_group) = session.read().get_foreground_process_group() else {
260 return;
261 };
262 process_group
263 };
264 process_group.send_signals(locked, signals);
265 }
266 }
267
268 pub fn device(&self) -> DeviceId {
269 get_device_type_for_pts(self.id)
270 }
271
272 state_accessor!(Terminal, mutable_state);
273}
274
275struct InputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::InputBuffer);
276
277impl<'a> line_discipline::InputBuffer for InputBufferWrapper<'a> {
278 fn available(&self) -> usize {
279 self.0.available()
280 }
281 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
282 self.0.read_to_vec_exact(size)
283 }
284}
285
286struct OutputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::OutputBuffer);
287
288impl<'a> line_discipline::OutputBuffer for OutputBufferWrapper<'a> {
289 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
290 self.0.write(data)
291 }
292}
293
294#[apply(state_implementation!)]
295impl TerminalMutableState<Base = Terminal> {
296 pub fn termios(&self) -> &uapi::termios2 {
298 self.line_discipline.termios()
299 }
300
301 pub fn set_packet_mode(&mut self, enabled: bool) {
302 if enabled != self.line_discipline.is_packet_mode_enabled() {
303 self.line_discipline.set_packet_mode(enabled);
304 self.notify_waiters();
305 }
306 }
307
308 pub fn get_available_read_size(&self, is_main: bool) -> usize {
311 self.line_discipline.get_available_read_size(is_main)
312 }
313
314 fn set_termios(&mut self, termios: uapi::termios2) -> PendingSignals {
316 let old_canon_enabled = self.line_discipline.is_canon_enabled();
317 let signals = self.line_discipline.set_termios(termios);
318 let canon_disabled = old_canon_enabled && !self.line_discipline.is_canon_enabled();
319 if canon_disabled || self.line_discipline.has_packet_mode_pending_events() {
320 self.notify_waiters();
321 }
322 signals
323 }
324
325 pub fn flush(&mut self, is_main: bool, arg: u32) -> Result<(), Errno> {
326 self.line_discipline.flush(is_main, arg)?;
327 self.main_wait_queue
328 .notify_fd_events(FdEvents::POLLIN | FdEvents::POLLOUT | FdEvents::POLLHUP);
329 self.replica_wait_queue
330 .notify_fd_events(FdEvents::POLLIN | FdEvents::POLLOUT | FdEvents::POLLHUP);
331 Ok(())
332 }
333
334 pub fn main_close(&mut self) {
336 self.line_discipline.main_close();
337 self.notify_waiters();
338 }
339
340 pub fn main_open(&mut self) {
342 self.line_discipline.main_open();
343 }
344
345 pub fn is_main_closed(&self) -> bool {
346 self.line_discipline.is_main_closed()
347 }
348
349 fn main_wait_async(
351 &self,
352 waiter: &Waiter,
353 events: FdEvents,
354 handler: EventHandler,
355 ) -> WaitCanceler {
356 self.main_wait_queue.wait_async_fd_events(waiter, events, handler)
357 }
358
359 fn main_query_events(&self) -> FdEvents {
361 self.line_discipline.main_query_events()
362 }
363
364 fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
366 let mut wrapper = OutputBufferWrapper(data);
367 let result = self.line_discipline.main_read(&mut wrapper)?;
368 self.notify_waiters();
369 Ok(result)
370 }
371
372 fn main_write(&mut self, data: &mut dyn InputBuffer) -> Result<(usize, PendingSignals), Errno> {
374 let mut wrapper = InputBufferWrapper(data);
375 let (result, signals) = self.line_discipline.main_write(&mut wrapper)?;
376 self.notify_waiters();
377 Ok((result, signals))
378 }
379
380 pub fn replica_close(&mut self) {
382 self.line_discipline.replica_close();
383 self.notify_waiters();
384 }
385
386 pub fn replica_open(&mut self) {
388 self.line_discipline.replica_open();
389 }
390
391 fn replica_wait_async(
393 &self,
394 waiter: &Waiter,
395 events: FdEvents,
396 handler: EventHandler,
397 ) -> WaitCanceler {
398 self.replica_wait_queue.wait_async_fd_events(waiter, events, handler)
399 }
400
401 fn replica_query_events(&self) -> FdEvents {
403 self.line_discipline.replica_query_events()
404 }
405
406 fn replica_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
408 let mut wrapper = OutputBufferWrapper(data);
409 let result = self.line_discipline.replica_read(&mut wrapper)?;
410 self.notify_waiters();
411 Ok(result)
412 }
413
414 fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
416 let mut wrapper = InputBufferWrapper(data);
417 let result = self.line_discipline.replica_write(&mut wrapper)?;
418 self.notify_waiters();
419 Ok(result)
420 }
421
422 fn notify_waiters(&mut self) {
424 let main_events = self.line_discipline.main_query_events();
425 if main_events.bits() != 0 {
426 self.main_wait_queue.notify_fd_events(main_events);
427 }
428 let replica_events = self.line_discipline.replica_query_events();
429 if replica_events.bits() != 0 {
430 self.replica_wait_queue.notify_fd_events(replica_events);
431 }
432 }
433}
434
435impl Drop for Terminal {
436 fn drop(&mut self) {
437 self.state.release_terminal(self.id).unwrap()
438 }
439}
440
441#[derive(Debug)]
444pub struct TerminalController {
445 pub session: Weak<Session>,
446}
447
448impl TerminalController {
449 pub fn new(session: &Arc<Session>) -> Option<Self> {
450 Some(Self { session: Arc::downgrade(&session) })
451 }
452
453 pub fn get_foreground_process_group(&self) -> Option<Arc<ProcessGroup>> {
454 self.session.upgrade().and_then(|session| session.read().get_foreground_process_group())
455 }
456}
457
458#[derive(Debug)]
459struct PtsIdsSet {
460 pts_count: u32,
461 next_id: u32,
462 reclaimed_ids: BTreeSet<u32>,
463}
464
465impl PtsIdsSet {
466 fn new(pts_count: u32) -> Self {
467 Self { pts_count, next_id: 0, reclaimed_ids: BTreeSet::new() }
468 }
469
470 fn release(&mut self, id: u32) {
471 assert!(self.reclaimed_ids.insert(id))
472 }
473
474 fn acquire(&mut self) -> Result<u32, Errno> {
475 match self.reclaimed_ids.iter().next() {
476 Some(e) => {
477 let value = *e;
478 self.reclaimed_ids.remove(&value);
479 Ok(value)
480 }
481 None => {
482 if self.next_id < self.pts_count {
483 let id = self.next_id;
484 self.next_id += 1;
485 Ok(id)
486 } else {
487 error!(ENOSPC)
488 }
489 }
490 }
491 }
492}