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::{LockBefore, Locked, Mutex, ProcessGroupState, RwLock};
15use starnix_uapi::auth::FsCred;
16use starnix_uapi::device_type::DeviceType;
17use starnix_uapi::errors::Errno;
18use starnix_uapi::vfs::FdEvents;
19use starnix_uapi::{error, uapi};
20use std::collections::{BTreeSet, HashMap};
21use std::sync::{Arc, Weak};
22
23pub struct TtyState {
25 pub terminals: RwLock<HashMap<u32, Weak<Terminal>>>,
27
28 pts_ids_set: Mutex<PtsIdsSet>,
30}
31
32impl TtyState {
33 pub fn get_next_terminal(
35 self: &Arc<Self>,
36 dev_pts_root: DirEntryHandle,
37 creds: FsCred,
38 ) -> Result<Arc<Terminal>, Errno> {
39 let id = self.pts_ids_set.lock().acquire()?;
40 let terminal = Terminal::new(self.clone(), dev_pts_root, creds, id);
41 assert!(self.terminals.write().insert(id, Arc::downgrade(&terminal)).is_none());
42 Ok(terminal)
43 }
44
45 pub fn release_terminal(&self, id: u32) -> Result<(), Errno> {
47 assert!(self.terminals.write().remove(&id).is_some());
51 self.pts_ids_set.lock().release(id);
52 Ok(())
53 }
54}
55
56impl Default for TtyState {
57 fn default() -> Self {
58 Self {
59 terminals: RwLock::new(HashMap::new()),
60 pts_ids_set: Mutex::new(PtsIdsSet::new(DEVPTS_COUNT)),
61 }
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: RwLock<TerminalMutableState>,
103}
104
105impl Terminal {
106 pub fn new(
107 state: Arc<TtyState>,
108 dev_pts_root: DirEntryHandle,
109 fscred: FsCred,
110 id: u32,
111 ) -> Arc<Self> {
112 Arc::new_cyclic(|weak_self| Self {
113 weak_self: weak_self.clone(),
114 state,
115 dev_pts_root,
116 fscred,
117 id,
118 mutable_state: RwLock::new(Default::default()),
119 })
120 }
121
122 pub fn to_owned(&self) -> Arc<Terminal> {
123 self.weak_self.upgrade().expect("This should never be called while releasing the terminal")
124 }
125
126 pub fn set_termios<L>(&self, locked: &mut Locked<L>, termios: uapi::termios)
128 where
129 L: LockBefore<ProcessGroupState>,
130 {
131 let signals = self.write().set_termios(termios);
132 self.send_signals(locked, signals);
133 }
134
135 pub fn main_close(&self) {
137 let id = FsString::from(self.id.to_string());
139 self.dev_pts_root.remove_child(id.as_ref(), &Mounts::new());
141 self.write().main_close();
142 }
143
144 pub fn main_open(&self) {
146 self.write().main_open();
147 }
148
149 pub fn main_wait_async(
151 &self,
152 waiter: &Waiter,
153 events: FdEvents,
154 handler: EventHandler,
155 ) -> WaitCanceler {
156 self.read().main_wait_async(waiter, events, handler)
157 }
158
159 pub fn main_query_events(&self) -> FdEvents {
161 self.read().main_query_events()
162 }
163
164 pub fn main_read<L>(
166 &self,
167 _locked: &mut Locked<L>,
168 data: &mut dyn OutputBuffer,
169 ) -> Result<usize, Errno>
170 where
171 L: LockBefore<ProcessGroupState>,
172 {
173 self.write().main_read(data)
174 }
175
176 pub fn main_write<L>(
178 &self,
179 locked: &mut Locked<L>,
180 data: &mut dyn InputBuffer,
181 ) -> Result<usize, Errno>
182 where
183 L: LockBefore<ProcessGroupState>,
184 {
185 let (bytes, signals) = self.write().main_write(data)?;
186 self.send_signals(locked, signals);
187 Ok(bytes)
188 }
189
190 pub fn replica_close(&self) {
192 self.write().replica_close();
193 }
194
195 pub fn replica_open(&self) {
197 self.write().replica_open();
198 }
199
200 pub fn replica_wait_async(
202 &self,
203 waiter: &Waiter,
204 events: FdEvents,
205 handler: EventHandler,
206 ) -> WaitCanceler {
207 self.read().replica_wait_async(waiter, events, handler)
208 }
209
210 pub fn replica_query_events(&self) -> FdEvents {
212 self.read().replica_query_events()
213 }
214
215 pub fn replica_read<L>(
217 &self,
218 _locked: &mut Locked<L>,
219 data: &mut dyn OutputBuffer,
220 ) -> Result<usize, Errno>
221 where
222 L: LockBefore<ProcessGroupState>,
223 {
224 self.write().replica_read(data)
225 }
226
227 pub fn replica_write<L>(
229 &self,
230 _locked: &mut Locked<L>,
231 data: &mut dyn InputBuffer,
232 ) -> Result<usize, Errno>
233 where
234 L: LockBefore<ProcessGroupState>,
235 {
236 self.write().replica_write(data)
237 }
238
239 fn send_signals<L>(&self, locked: &mut Locked<L>, signals: PendingSignals)
241 where
242 L: LockBefore<ProcessGroupState>,
243 {
244 let signals = signals.signals();
245 if !signals.is_empty() {
246 let process_group = {
247 let terminal_state = self.read();
248 let Some(controller) = terminal_state.controller.as_ref() else {
249 return;
250 };
251 let Some(session) = controller.session.upgrade() else {
252 return;
253 };
254 let Some(process_group) = session.read().get_foreground_process_group() else {
255 return;
256 };
257 process_group
258 };
259 process_group.send_signals(locked, signals);
260 }
261 }
262
263 pub fn device(&self) -> DeviceType {
264 get_device_type_for_pts(self.id)
265 }
266
267 state_accessor!(Terminal, mutable_state);
268}
269
270struct InputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::InputBuffer);
271
272impl<'a> line_discipline::InputBuffer for InputBufferWrapper<'a> {
273 fn available(&self) -> usize {
274 self.0.available()
275 }
276 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
277 self.0.read_to_vec_exact(size)
278 }
279}
280
281struct OutputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::OutputBuffer);
282
283impl<'a> line_discipline::OutputBuffer for OutputBufferWrapper<'a> {
284 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
285 self.0.write(data)
286 }
287}
288
289#[apply(state_implementation!)]
290impl TerminalMutableState<Base = Terminal> {
291 pub fn termios(&self) -> &uapi::termios {
293 self.line_discipline.termios()
294 }
295
296 pub fn get_available_read_size(&self, is_main: bool) -> usize {
299 self.line_discipline.get_available_read_size(is_main)
300 }
301
302 fn set_termios(&mut self, termios: uapi::termios) -> PendingSignals {
304 let old_canon_enabled = self.line_discipline.is_canon_enabled();
305 let signals = self.line_discipline.set_termios(termios);
306 if old_canon_enabled && !self.line_discipline.is_canon_enabled() {
307 self.notify_waiters();
308 }
309 signals
310 }
311
312 pub fn main_close(&mut self) {
314 self.line_discipline.main_close();
315 self.notify_waiters();
316 }
317
318 pub fn main_open(&mut self) {
320 self.line_discipline.main_open();
321 }
322
323 pub fn is_main_closed(&self) -> bool {
324 self.line_discipline.is_main_closed()
325 }
326
327 fn main_wait_async(
329 &self,
330 waiter: &Waiter,
331 events: FdEvents,
332 handler: EventHandler,
333 ) -> WaitCanceler {
334 self.main_wait_queue.wait_async_fd_events(waiter, events, handler)
335 }
336
337 fn main_query_events(&self) -> FdEvents {
339 self.line_discipline.main_query_events()
340 }
341
342 fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
344 let mut wrapper = OutputBufferWrapper(data);
345 let result = self.line_discipline.main_read(&mut wrapper)?;
346 self.notify_waiters();
347 Ok(result)
348 }
349
350 fn main_write(&mut self, data: &mut dyn InputBuffer) -> Result<(usize, PendingSignals), Errno> {
352 let mut wrapper = InputBufferWrapper(data);
353 let (result, signals) = self.line_discipline.main_write(&mut wrapper)?;
354 self.notify_waiters();
355 Ok((result, signals))
356 }
357
358 pub fn replica_close(&mut self) {
360 self.line_discipline.replica_close();
361 self.notify_waiters();
362 }
363
364 pub fn replica_open(&mut self) {
366 self.line_discipline.replica_open();
367 }
368
369 fn replica_wait_async(
371 &self,
372 waiter: &Waiter,
373 events: FdEvents,
374 handler: EventHandler,
375 ) -> WaitCanceler {
376 self.replica_wait_queue.wait_async_fd_events(waiter, events, handler)
377 }
378
379 fn replica_query_events(&self) -> FdEvents {
381 self.line_discipline.replica_query_events()
382 }
383
384 fn replica_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
386 let mut wrapper = OutputBufferWrapper(data);
387 let result = self.line_discipline.replica_read(&mut wrapper)?;
388 self.notify_waiters();
389 Ok(result)
390 }
391
392 fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
394 let mut wrapper = InputBufferWrapper(data);
395 let result = self.line_discipline.replica_write(&mut wrapper)?;
396 self.notify_waiters();
397 Ok(result)
398 }
399
400 fn notify_waiters(&mut self) {
402 let main_events = self.line_discipline.main_query_events();
403 if main_events.bits() != 0 {
404 self.main_wait_queue.notify_fd_events(main_events);
405 }
406 let replica_events = self.line_discipline.replica_query_events();
407 if replica_events.bits() != 0 {
408 self.replica_wait_queue.notify_fd_events(replica_events);
409 }
410 }
411}
412
413impl Drop for Terminal {
414 fn drop(&mut self) {
415 self.state.release_terminal(self.id).unwrap()
416 }
417}
418
419#[derive(Debug)]
422pub struct TerminalController {
423 pub session: Weak<Session>,
424}
425
426impl TerminalController {
427 pub fn new(session: &Arc<Session>) -> Option<Self> {
428 Some(Self { session: Arc::downgrade(&session) })
429 }
430
431 pub fn get_foreground_process_group(&self) -> Option<Arc<ProcessGroup>> {
432 self.session.upgrade().and_then(|session| session.read().get_foreground_process_group())
433 }
434}
435
436#[derive(Debug)]
437struct PtsIdsSet {
438 pts_count: u32,
439 next_id: u32,
440 reclaimed_ids: BTreeSet<u32>,
441}
442
443impl PtsIdsSet {
444 fn new(pts_count: u32) -> Self {
445 Self { pts_count, next_id: 0, reclaimed_ids: BTreeSet::new() }
446 }
447
448 fn release(&mut self, id: u32) {
449 assert!(self.reclaimed_ids.insert(id))
450 }
451
452 fn acquire(&mut self) -> Result<u32, Errno> {
453 match self.reclaimed_ids.iter().next() {
454 Some(e) => {
455 let value = *e;
456 self.reclaimed_ids.remove(&value);
457 Ok(value)
458 }
459 None => {
460 if self.next_id < self.pts_count {
461 let id = self.next_id;
462 self.next_id += 1;
463 Ok(id)
464 } else {
465 error!(ENOSPC)
466 }
467 }
468 }
469 }
470}