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::{DeviceTerminalsLock, LockDepMutex, LockDepRwLock, PtsIdsSetLock};
15use starnix_uapi::auth::FsCred;
16use starnix_uapi::device_id::DeviceId;
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: LockDepRwLock<HashMap<u32, Weak<Terminal>>, DeviceTerminalsLock>,
27
28 pts_ids_set: LockDepMutex<PtsIdsSet, PtsIdsSetLock>,
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 { terminals: Default::default(), pts_ids_set: PtsIdsSet::new(DEVPTS_COUNT).into() }
59 }
60}
61
62#[derive(Derivative)]
63#[derivative(Default)]
64#[derivative(Debug)]
65pub struct TerminalMutableState {
66 pub line_discipline: LineDiscipline,
67
68 main_wait_queue: WaitQueue,
70
71 replica_wait_queue: WaitQueue,
73
74 pub controller: Option<TerminalController>,
76}
77
78#[derive(Derivative)]
80#[derivative(Debug)]
81pub struct Terminal {
82 weak_self: Weak<Self>,
84
85 #[derivative(Debug = "ignore")]
87 state: Arc<TtyState>,
88
89 pub dev_pts_root: DirEntryHandle,
91
92 pub fscred: FsCred,
94
95 pub id: u32,
97
98 mutable_state:
100 starnix_sync::LockDepRwLock<TerminalMutableState, starnix_sync::TerminalMutableStateLock>,
101}
102
103impl Terminal {
104 pub fn new(
105 state: Arc<TtyState>,
106 dev_pts_root: DirEntryHandle,
107 fscred: FsCred,
108 id: u32,
109 ) -> Arc<Self> {
110 Arc::new_cyclic(|weak_self| Self {
111 weak_self: weak_self.clone(),
112 state,
113 dev_pts_root,
114 fscred,
115 id,
116 mutable_state: Default::default(),
117 })
118 }
119
120 pub fn to_owned(&self) -> Arc<Terminal> {
121 self.weak_self.upgrade().expect("This should never be called while releasing the terminal")
122 }
123
124 pub fn set_termios(&self, termios: uapi::termios2) {
126 let signals = self.write().set_termios(termios);
127 self.send_signals(signals);
128 }
129
130 pub fn flush(&self, is_main: bool, arg: u32) -> Result<(), Errno> {
131 self.write().flush(is_main, arg)
132 }
133
134 pub fn main_close(&self) {
136 let id = FsString::from(self.id.to_string());
138 self.dev_pts_root.remove_child(id.as_ref(), &Mounts::new());
140 self.write().main_close();
141 }
142
143 pub fn main_open(&self) {
145 self.write().main_open();
146 }
147
148 pub fn main_wait_async(
150 &self,
151 waiter: &Waiter,
152 events: FdEvents,
153 handler: EventHandler,
154 ) -> WaitCanceler {
155 self.read().main_wait_async(waiter, events, handler)
156 }
157
158 pub fn main_query_events(&self) -> FdEvents {
160 self.read().main_query_events()
161 }
162
163 pub fn main_read(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
165 self.write().main_read(data)
166 }
167
168 pub fn main_write(&self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
170 let (bytes, signals) = self.write().main_write(data)?;
171 self.send_signals(signals);
172 Ok(bytes)
173 }
174
175 pub fn replica_close(&self) {
177 self.write().replica_close();
178 }
179
180 pub fn replica_open(&self) {
182 self.write().replica_open();
183 }
184
185 pub fn replica_wait_async(
187 &self,
188 waiter: &Waiter,
189 events: FdEvents,
190 handler: EventHandler,
191 ) -> WaitCanceler {
192 self.read().replica_wait_async(waiter, events, handler)
193 }
194
195 pub fn replica_query_events(&self) -> FdEvents {
197 self.read().replica_query_events()
198 }
199
200 pub fn replica_read(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
202 self.write().replica_read(data)
203 }
204
205 pub fn replica_write(&self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
207 self.write().replica_write(data)
208 }
209
210 fn send_signals(&self, signals: PendingSignals) {
212 let signals = signals.signals();
213 if !signals.is_empty() {
214 let process_group = {
215 let terminal_state = self.read();
216 let Some(controller) = terminal_state.controller.as_ref() else {
217 return;
218 };
219 let Some(session) = controller.session.upgrade() else {
220 return;
221 };
222 let Some(process_group) = session.read().get_foreground_process_group() else {
223 return;
224 };
225 process_group
226 };
227 process_group.send_signals(signals);
228 }
229 }
230
231 pub fn device(&self) -> DeviceId {
232 get_device_type_for_pts(self.id)
233 }
234
235 state_accessor!(Terminal, mutable_state);
236}
237
238struct InputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::InputBuffer);
239
240impl<'a> line_discipline::InputBuffer for InputBufferWrapper<'a> {
241 fn available(&self) -> usize {
242 self.0.available()
243 }
244 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
245 self.0.read_to_vec_exact(size)
246 }
247}
248
249struct OutputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::OutputBuffer);
250
251impl<'a> line_discipline::OutputBuffer for OutputBufferWrapper<'a> {
252 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
253 self.0.write(data)
254 }
255}
256
257#[apply(state_implementation!)]
258impl TerminalMutableState<Base = Terminal> {
259 pub fn termios(&self) -> &uapi::termios2 {
261 self.line_discipline.termios()
262 }
263
264 pub fn set_packet_mode(&mut self, enabled: bool) {
265 if enabled != self.line_discipline.is_packet_mode_enabled() {
266 self.line_discipline.set_packet_mode(enabled);
267 self.notify_waiters();
268 }
269 }
270
271 pub fn get_available_read_size(&self, is_main: bool) -> usize {
274 self.line_discipline.get_available_read_size(is_main)
275 }
276
277 fn set_termios(&mut self, termios: uapi::termios2) -> PendingSignals {
279 let old_canon_enabled = self.line_discipline.is_canon_enabled();
280 let signals = self.line_discipline.set_termios(termios);
281 let canon_disabled = old_canon_enabled && !self.line_discipline.is_canon_enabled();
282 if canon_disabled || self.line_discipline.has_packet_mode_pending_events() {
283 self.notify_waiters();
284 }
285 signals
286 }
287
288 pub fn flush(&mut self, is_main: bool, arg: u32) -> Result<(), Errno> {
289 self.line_discipline.flush(is_main, arg)?;
290 self.notify_waiters();
291 Ok(())
292 }
293
294 pub fn main_close(&mut self) {
296 self.line_discipline.main_close();
297 self.notify_waiters();
298 }
299
300 pub fn main_open(&mut self) {
302 self.line_discipline.main_open();
303 }
304
305 pub fn is_main_closed(&self) -> bool {
306 self.line_discipline.is_main_closed()
307 }
308
309 fn main_wait_async(
311 &self,
312 waiter: &Waiter,
313 events: FdEvents,
314 handler: EventHandler,
315 ) -> WaitCanceler {
316 self.main_wait_queue.wait_async_fd_events(waiter, events, handler)
317 }
318
319 fn main_query_events(&self) -> FdEvents {
321 self.line_discipline.main_query_events()
322 }
323
324 fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
326 let mut wrapper = OutputBufferWrapper(data);
327 let result = self.line_discipline.main_read(&mut wrapper)?;
328 self.notify_waiters();
329 Ok(result)
330 }
331
332 fn main_write(&mut self, data: &mut dyn InputBuffer) -> Result<(usize, PendingSignals), Errno> {
334 let mut wrapper = InputBufferWrapper(data);
335 let (result, signals) = self.line_discipline.main_write(&mut wrapper)?;
336 self.notify_waiters();
337 Ok((result, signals))
338 }
339
340 pub fn replica_close(&mut self) {
342 self.line_discipline.replica_close();
343 self.notify_waiters();
344 }
345
346 pub fn replica_open(&mut self) {
348 self.line_discipline.replica_open();
349 }
350
351 fn replica_wait_async(
353 &self,
354 waiter: &Waiter,
355 events: FdEvents,
356 handler: EventHandler,
357 ) -> WaitCanceler {
358 self.replica_wait_queue.wait_async_fd_events(waiter, events, handler)
359 }
360
361 fn replica_query_events(&self) -> FdEvents {
363 self.line_discipline.replica_query_events()
364 }
365
366 fn replica_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
368 let mut wrapper = OutputBufferWrapper(data);
369 let result = self.line_discipline.replica_read(&mut wrapper)?;
370 self.notify_waiters();
371 Ok(result)
372 }
373
374 fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
376 let mut wrapper = InputBufferWrapper(data);
377 let result = self.line_discipline.replica_write(&mut wrapper)?;
378 self.notify_waiters();
379 Ok(result)
380 }
381
382 fn notify_waiters(&mut self) {
384 let main_events = self.line_discipline.main_query_events();
385 if main_events.bits() != 0 {
386 self.main_wait_queue.notify_fd_events(main_events);
387 }
388 let replica_events = self.line_discipline.replica_query_events();
389 if replica_events.bits() != 0 {
390 self.replica_wait_queue.notify_fd_events(replica_events);
391 }
392 }
393}
394
395impl Drop for Terminal {
396 fn drop(&mut self) {
397 self.state.release_terminal(self.id).unwrap()
398 }
399}
400
401#[derive(Debug)]
404pub struct TerminalController {
405 pub session: Weak<Session>,
406}
407
408impl TerminalController {
409 pub fn new(session: &Arc<Session>) -> Option<Self> {
410 Some(Self { session: Arc::downgrade(&session) })
411 }
412
413 pub fn get_foreground_process_group(&self) -> Option<Arc<ProcessGroup>> {
414 self.session.upgrade().and_then(|session| session.read().get_foreground_process_group())
415 }
416}
417
418#[derive(Debug)]
419struct PtsIdsSet {
420 pts_count: u32,
421 next_id: u32,
422 reclaimed_ids: BTreeSet<u32>,
423}
424
425impl PtsIdsSet {
426 fn new(pts_count: u32) -> Self {
427 Self { pts_count, next_id: 0, reclaimed_ids: BTreeSet::new() }
428 }
429
430 fn release(&mut self, id: u32) {
431 assert!(self.reclaimed_ids.insert(id))
432 }
433
434 fn acquire(&mut self) -> Result<u32, Errno> {
435 match self.reclaimed_ids.iter().next() {
436 Some(e) => {
437 let value = *e;
438 self.reclaimed_ids.remove(&value);
439 Ok(value)
440 }
441 None => {
442 if self.next_id < self.pts_count {
443 let id = self.next_id;
444 self.next_id += 1;
445 Ok(id)
446 } else {
447 error!(ENOSPC)
448 }
449 }
450 }
451 }
452}