1use crate::mutable_state::{state_accessor, state_implementation};
6use crate::task::{EventHandler, ProcessGroup, Session, WaitCanceler, WaitQueue, Waiter};
7use crate::vfs::buffers::{InputBuffer, InputBufferExt as _, OutputBuffer};
8use crate::vfs::{DirEntryHandle, FsString, Mounts};
9use derivative::Derivative;
10use line_discipline::{LineDiscipline, PendingSignals};
11use macro_rules_attribute::apply;
12use starnix_sync::{DeviceTerminalsLock, LockDepMutex, LockDepRwLock, PtsIdsSetLock};
13use starnix_uapi::auth::FsCred;
14use starnix_uapi::device_id::DeviceId;
15use starnix_uapi::errors::Errno;
16use starnix_uapi::vfs::FdEvents;
17use starnix_uapi::{errno, error, uapi};
18use std::collections::{BTreeSet, HashMap};
19use std::sync::{Arc, Weak};
20
21const DEVPTS_FIRST_MAJOR: u32 = 136;
22const DEVPTS_MAJOR_COUNT: u32 = 4;
23pub const DEVPTS_COUNT: u32 = DEVPTS_MAJOR_COUNT * 256;
24
25pub fn get_device_type_for_pts(id: u32) -> DeviceId {
27 DeviceId::new(DEVPTS_FIRST_MAJOR + id / 256, id % 256)
28}
29
30pub struct TtyState {
32 pub terminals: LockDepRwLock<HashMap<u32, Weak<Terminal>>, DeviceTerminalsLock>,
34
35 pts_ids_set: LockDepMutex<PtsIdsSet, PtsIdsSetLock>,
37}
38
39impl TtyState {
40 pub fn get_next_terminal(
42 self: &Arc<Self>,
43 dev_pts_root: DirEntryHandle,
44 creds: FsCred,
45 ) -> Result<Arc<Terminal>, Errno> {
46 let id = self.pts_ids_set.lock().acquire()?;
47 let terminal = Terminal::new(self.clone(), dev_pts_root, creds, id);
48 assert!(self.terminals.write().insert(id, Arc::downgrade(&terminal)).is_none());
49 Ok(terminal)
50 }
51
52 pub fn release_terminal(&self, id: u32) -> Result<(), Errno> {
54 assert!(self.terminals.write().remove(&id).is_some());
58 self.pts_ids_set.lock().release(id);
59 Ok(())
60 }
61}
62
63impl Default for TtyState {
64 fn default() -> Self {
65 Self { terminals: Default::default(), pts_ids_set: PtsIdsSet::new(DEVPTS_COUNT).into() }
66 }
67}
68
69#[derive(Derivative)]
70#[derivative(Default)]
71#[derivative(Debug)]
72pub struct TerminalMutableState {
73 pub line_discipline: LineDiscipline,
74
75 main_wait_queue: WaitQueue,
77
78 replica_wait_queue: WaitQueue,
80
81 pub controller: Option<TerminalController>,
83}
84
85#[derive(Derivative)]
87#[derivative(Debug)]
88pub struct Terminal {
89 weak_self: Weak<Self>,
91
92 #[derivative(Debug = "ignore")]
94 state: Arc<TtyState>,
95
96 pub dev_pts_root: DirEntryHandle,
98
99 pub fscred: FsCred,
101
102 pub id: u32,
104
105 mutable_state:
107 starnix_sync::LockDepRwLock<TerminalMutableState, starnix_sync::TerminalMutableStateLock>,
108}
109
110impl Terminal {
111 pub fn new(
112 state: Arc<TtyState>,
113 dev_pts_root: DirEntryHandle,
114 fscred: FsCred,
115 id: u32,
116 ) -> Arc<Self> {
117 Arc::new_cyclic(|weak_self| Self {
118 weak_self: weak_self.clone(),
119 state,
120 dev_pts_root,
121 fscred,
122 id,
123 mutable_state: Default::default(),
124 })
125 }
126
127 pub fn to_owned(&self) -> Arc<Terminal> {
128 self.weak_self.upgrade().expect("This should never be called while releasing the terminal")
129 }
130
131 pub fn set_termios(&self, termios: uapi::termios2) {
133 let signals = self.write().set_termios(termios);
134 self.send_signals(signals);
135 }
136
137 pub fn flush(&self, is_main: bool, arg: u32) -> Result<(), Errno> {
138 self.write().flush(is_main, arg)
139 }
140
141 pub fn main_close(&self) {
143 let id = FsString::from(self.id.to_string());
145 self.dev_pts_root.remove_child(id.as_ref(), &Mounts::new());
147 self.write().main_close();
148 }
149
150 pub fn main_open(&self) {
152 self.write().main_open();
153 }
154
155 pub fn main_wait_async(
157 &self,
158 waiter: &Waiter,
159 events: FdEvents,
160 handler: EventHandler,
161 ) -> WaitCanceler {
162 self.read().main_wait_async(waiter, events, handler)
163 }
164
165 pub fn main_query_events(&self) -> FdEvents {
167 self.read().main_query_events()
168 }
169
170 pub fn main_read(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
172 self.write().main_read(data)
173 }
174
175 pub fn main_write(&self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
177 let (bytes, signals) = self.write().main_write(data)?;
178 self.send_signals(signals);
179 Ok(bytes)
180 }
181
182 pub fn replica_close(&self) {
184 self.write().replica_close();
185 }
186
187 pub fn replica_open(&self) {
189 self.write().replica_open();
190 }
191
192 pub fn replica_wait_async(
194 &self,
195 waiter: &Waiter,
196 events: FdEvents,
197 handler: EventHandler,
198 ) -> WaitCanceler {
199 self.read().replica_wait_async(waiter, events, handler)
200 }
201
202 pub fn replica_query_events(&self) -> FdEvents {
204 self.read().replica_query_events()
205 }
206
207 pub fn replica_read(&self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
209 self.write().replica_read(data)
210 }
211
212 pub fn replica_write(&self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
214 self.write().replica_write(data)
215 }
216
217 fn send_signals(&self, signals: PendingSignals) {
219 let signals = signals.signals();
220 if !signals.is_empty() {
221 let process_group = {
222 let terminal_state = self.read();
223 let Some(controller) = terminal_state.controller.as_ref() else {
224 return;
225 };
226 let Some(session) = controller.session.upgrade() else {
227 return;
228 };
229 let Ok(process_group) = session.read().get_foreground_process_group() else {
230 return;
231 };
232 process_group
233 };
234 process_group.send_signals(signals);
235 }
236 }
237
238 pub fn device(&self) -> DeviceId {
239 get_device_type_for_pts(self.id)
240 }
241
242 state_accessor!(Terminal, mutable_state);
243}
244
245struct InputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::InputBuffer);
246
247impl<'a> line_discipline::InputBuffer for InputBufferWrapper<'a> {
248 fn available(&self) -> usize {
249 self.0.available()
250 }
251 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
252 self.0.read_to_vec_exact(size)
253 }
254}
255
256struct OutputBufferWrapper<'a>(&'a mut dyn crate::vfs::buffers::OutputBuffer);
257
258impl<'a> line_discipline::OutputBuffer for OutputBufferWrapper<'a> {
259 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
260 self.0.write(data)
261 }
262}
263
264#[apply(state_implementation!)]
265impl TerminalMutableState<Base = Terminal> {
266 pub fn termios(&self) -> &uapi::termios2 {
268 self.line_discipline.termios()
269 }
270
271 pub fn set_packet_mode(&mut self, enabled: bool) {
272 if enabled != self.line_discipline.is_packet_mode_enabled() {
273 self.line_discipline.set_packet_mode(enabled);
274 self.notify_waiters();
275 }
276 }
277
278 pub fn get_available_read_size(&self, is_main: bool) -> usize {
281 self.line_discipline.get_available_read_size(is_main)
282 }
283
284 fn set_termios(&mut self, termios: uapi::termios2) -> PendingSignals {
286 let old_canon_enabled = self.line_discipline.is_canon_enabled();
287 let signals = self.line_discipline.set_termios(termios);
288 let canon_disabled = old_canon_enabled && !self.line_discipline.is_canon_enabled();
289 if canon_disabled || self.line_discipline.has_packet_mode_pending_events() {
290 self.notify_waiters();
291 }
292 signals
293 }
294
295 pub fn flush(&mut self, is_main: bool, arg: u32) -> Result<(), Errno> {
296 self.line_discipline.flush(is_main, arg)?;
297 self.notify_waiters();
298 Ok(())
299 }
300
301 pub fn main_close(&mut self) {
303 self.line_discipline.main_close();
304 self.notify_waiters();
305 }
306
307 pub fn main_open(&mut self) {
309 self.line_discipline.main_open();
310 }
311
312 pub fn is_main_closed(&self) -> bool {
313 self.line_discipline.is_main_closed()
314 }
315
316 fn main_wait_async(
318 &self,
319 waiter: &Waiter,
320 events: FdEvents,
321 handler: EventHandler,
322 ) -> WaitCanceler {
323 self.main_wait_queue.wait_async_fd_events(waiter, events, handler)
324 }
325
326 fn main_query_events(&self) -> FdEvents {
328 self.line_discipline.main_query_events()
329 }
330
331 fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
333 let mut wrapper = OutputBufferWrapper(data);
334 let result = self.line_discipline.main_read(&mut wrapper)?;
335 self.notify_waiters();
336 Ok(result)
337 }
338
339 fn main_write(&mut self, data: &mut dyn InputBuffer) -> Result<(usize, PendingSignals), Errno> {
341 let mut wrapper = InputBufferWrapper(data);
342 let (result, signals) = self.line_discipline.main_write(&mut wrapper)?;
343 self.notify_waiters();
344 Ok((result, signals))
345 }
346
347 pub fn replica_close(&mut self) {
349 self.line_discipline.replica_close();
350 self.notify_waiters();
351 }
352
353 pub fn replica_open(&mut self) {
355 self.line_discipline.replica_open();
356 }
357
358 fn replica_wait_async(
360 &self,
361 waiter: &Waiter,
362 events: FdEvents,
363 handler: EventHandler,
364 ) -> WaitCanceler {
365 self.replica_wait_queue.wait_async_fd_events(waiter, events, handler)
366 }
367
368 fn replica_query_events(&self) -> FdEvents {
370 self.line_discipline.replica_query_events()
371 }
372
373 fn replica_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
375 let mut wrapper = OutputBufferWrapper(data);
376 let result = self.line_discipline.replica_read(&mut wrapper)?;
377 self.notify_waiters();
378 Ok(result)
379 }
380
381 fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
383 let mut wrapper = InputBufferWrapper(data);
384 let result = self.line_discipline.replica_write(&mut wrapper)?;
385 self.notify_waiters();
386 Ok(result)
387 }
388
389 fn notify_waiters(&mut self) {
391 let main_events = self.line_discipline.main_query_events();
392 if main_events.bits() != 0 {
393 self.main_wait_queue.notify_fd_events(main_events);
394 }
395 let replica_events = self.line_discipline.replica_query_events();
396 if replica_events.bits() != 0 {
397 self.replica_wait_queue.notify_fd_events(replica_events);
398 }
399 }
400}
401
402impl Drop for Terminal {
403 fn drop(&mut self) {
404 self.state.release_terminal(self.id).unwrap()
405 }
406}
407
408#[derive(Debug)]
411pub struct TerminalController {
412 pub session: Weak<Session>,
413}
414
415impl TerminalController {
416 pub fn new(session: &Arc<Session>) -> Option<Self> {
417 Some(Self { session: Arc::downgrade(&session) })
418 }
419
420 pub fn get_foreground_process_group(&self) -> Result<Arc<ProcessGroup>, Errno> {
421 let session = self.session.upgrade().ok_or_else(|| errno!(ESRCH))?;
422 session.read().get_foreground_process_group()
423 }
424}
425
426#[derive(Debug)]
427struct PtsIdsSet {
428 pts_count: u32,
429 next_id: u32,
430 reclaimed_ids: BTreeSet<u32>,
431}
432
433impl PtsIdsSet {
434 fn new(pts_count: u32) -> Self {
435 Self { pts_count, next_id: 0, reclaimed_ids: BTreeSet::new() }
436 }
437
438 fn release(&mut self, id: u32) {
439 assert!(self.reclaimed_ids.insert(id))
440 }
441
442 fn acquire(&mut self) -> Result<u32, Errno> {
443 match self.reclaimed_ids.iter().next() {
444 Some(e) => {
445 let value = *e;
446 self.reclaimed_ids.remove(&value);
447 Ok(value)
448 }
449 None => {
450 if self.next_id < self.pts_count {
451 let id = self.next_id;
452 self.next_id += 1;
453 Ok(id)
454 } else {
455 error!(ENOSPC)
456 }
457 }
458 }
459 }
460}