1use derivative::Derivative;
6use starnix_uapi::errors::Errno;
7use starnix_uapi::signals::{SIGINT, SIGQUIT, SIGSTOP, Signal};
8use starnix_uapi::vfs::FdEvents;
9use starnix_uapi::{
10 ECHO, ECHOCTL, ECHOE, ECHOK, ECHOKE, ECHONL, ECHOPRT, ICANON, ICRNL, IEXTEN, IGNCR, INLCR,
11 ISIG, IUCLC, IUTF8, IXANY, IXON, NOFLSH, OCRNL, OLCUC, ONLCR, ONLRET, ONOCR, OPOST, TABDLY,
12 VEOF, VEOL, VEOL2, VERASE, VINTR, VKILL, VLNEXT, VQUIT, VREPRINT, VSTART, VSTOP, VSUSP,
13 VWERASE, XTABS, cc_t, errno, error, tcflag_t, uapi,
14};
15use std::collections::VecDeque;
16
17const CANON_MAX_BYTES: usize = 4096;
20
21const NON_CANON_MAX_BYTES: usize = CANON_MAX_BYTES - 1;
24
25const WAIT_BUFFER_MAX_BYTES: usize = 131072;
28
29const SPACES_PER_TAB: usize = 8;
30
31const DISABLED_CHAR: u8 = 0;
33
34const BACKSPACE_CHAR: u8 = 8; const CONTROL_OFFSET: u8 = 0x40;
40
41#[derive(Derivative)]
42#[derivative(Default)]
43#[derivative(Debug)]
44pub struct LineDiscipline {
45 #[derivative(Default(value = "true"))]
47 pub locked: bool,
48
49 #[derivative(Default(value = "false"))]
51 pub stopped: bool,
52
53 pub window_size: uapi::winsize,
55
56 #[derivative(Default(value = "get_default_termios()"))]
58 termios: uapi::termios2,
59
60 #[derivative(Default(value = "false"))]
62 erasing: bool,
63
64 #[derivative(Default(value = "false"))]
66 lnext: bool,
67
68 column: usize,
71
72 #[derivative(Default(value = "false"))]
74 packet_mode_enabled: bool,
75
76 #[derivative(Default(value = "0"))]
78 packet_mode_pending_events: u8,
79
80 main_references: Option<u32>,
83
84 replica_references: Option<u32>,
87
88 #[derivative(Default(value = "Queue::input_queue()"))]
90 input_queue: Option<Queue>,
91
92 #[derivative(Default(value = "Queue::output_queue()"))]
94 output_queue: Option<Queue>,
95}
96
97pub trait InputBuffer {
99 fn available(&self) -> usize;
100 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno>;
101}
102
103pub trait OutputBuffer {
104 fn write(&mut self, data: &[u8]) -> Result<usize, Errno>;
105}
106
107macro_rules! with_queue {
109 ($self_:tt . $name:ident . $fn:ident ( $($param:expr),*$(,)?)) => {
110 {
111 let mut queue = $self_.$name . take().unwrap();
112 let result = queue.$fn( $($param),* );
113 $self_.$name = Some(queue);
114 result
115 }
116 };
117}
118
119#[must_use]
121pub struct PendingSignals {
122 signals: Vec<Signal>,
123}
124
125impl PendingSignals {
126 pub fn new() -> Self {
127 Self { signals: vec![] }
128 }
129
130 fn add(&mut self, signal: Signal) {
132 self.signals.push(signal);
133 }
134
135 fn append(&mut self, mut other: Self) {
137 self.signals.append(&mut other.signals);
138 }
139
140 pub fn signals(&self) -> &[Signal] {
142 &self.signals[..]
143 }
144}
145
146#[derive(Debug, PartialEq)]
148enum EraseType {
149 Character,
151 Word,
153 Line,
155}
156
157impl LineDiscipline {
158 pub fn termios(&self) -> &uapi::termios2 {
160 &self.termios
161 }
162
163 pub fn is_canon_enabled(&self) -> bool {
164 self.termios.has_local_flags(ICANON)
165 }
166
167 pub fn is_packet_mode_enabled(&self) -> bool {
168 self.packet_mode_enabled
169 }
170
171 pub fn set_packet_mode(&mut self, enabled: bool) {
172 self.packet_mode_enabled = enabled;
173 if !enabled {
174 self.packet_mode_pending_events = 0;
175 }
176 }
177
178 pub fn has_packet_mode_pending_events(&self) -> bool {
179 self.packet_mode_enabled && self.packet_mode_pending_events != 0
180 }
181
182 pub fn get_available_read_size(&self, is_main: bool) -> usize {
185 let queue = if is_main { self.output_queue() } else { self.input_queue() };
186 queue.readable_size()
187 }
188
189 pub fn set_termios(&mut self, termios: uapi::termios2) -> PendingSignals {
191 let old_canon_enabled = self.is_canon_enabled();
192 let old_ixon = self.termios.c_iflag & uapi::IXON != 0;
193 self.termios = termios;
194
195 if self.packet_mode_enabled {
196 let new_ixon = self.termios.c_iflag & uapi::IXON != 0;
197 if old_ixon != new_ixon {
198 let event = if new_ixon { uapi::TIOCPKT_DOSTOP } else { uapi::TIOCPKT_NOSTOP };
199 self.packet_mode_pending_events |= event as u8;
200 }
201 }
202
203 if old_canon_enabled && !self.is_canon_enabled() {
204 with_queue!(self.input_queue.on_canon_disabled(self))
205 } else {
206 PendingSignals::new()
207 }
208 }
209
210 pub fn flush(&mut self, is_main: bool, queue_selector: u32) -> Result<(), Errno> {
212 let (input_queue, output_queue) = if is_main {
215 (self.output_queue.as_mut().unwrap(), self.input_queue.as_mut().unwrap())
216 } else {
217 (self.input_queue.as_mut().unwrap(), self.output_queue.as_mut().unwrap())
218 };
219
220 let event;
221 match queue_selector {
229 uapi::TCIFLUSH => {
230 input_queue.flush();
231 event = uapi::TIOCPKT_FLUSHREAD;
232 }
233 uapi::TCOFLUSH => {
234 output_queue.flush_unprocessed();
235 event = uapi::TIOCPKT_FLUSHWRITE;
236 }
237 uapi::TCIOFLUSH => {
238 input_queue.flush();
239 output_queue.flush_unprocessed();
240 event = uapi::TIOCPKT_FLUSHREAD | uapi::TIOCPKT_FLUSHWRITE;
241 }
242 _ => return error!(EINVAL),
243 };
244
245 if !is_main && self.packet_mode_enabled {
246 self.packet_mode_pending_events |= event as u8;
247 }
248
249 Ok(())
250 }
251
252 pub fn main_close(&mut self) {
254 self.main_references = self.main_references.map(|v| v - 1);
255 }
256
257 pub fn main_open(&mut self) {
259 self.main_references = Some(self.main_references.unwrap_or(0) + 1);
260 }
261
262 pub fn is_main_closed(&self) -> bool {
263 matches!(self.main_references, Some(0))
264 }
265
266 pub fn main_query_events(&self) -> FdEvents {
268 if self.is_replica_closed() && self.output_queue().readable_size() == 0 {
269 return FdEvents::POLLOUT | FdEvents::POLLHUP;
270 }
271 let mut events =
272 self.output_queue().read_readiness() | self.input_queue().write_readiness();
273 if self.packet_mode_enabled && self.packet_mode_pending_events != 0 {
274 events |= FdEvents::POLLIN | FdEvents::POLLPRI;
275 }
276 events
277 }
278
279 pub fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
281 if self.is_replica_closed() && self.output_queue().readable_size() == 0 {
282 return error!(EIO);
283 }
284 if self.packet_mode_enabled {
285 if self.packet_mode_pending_events != 0 {
286 let event = self.packet_mode_pending_events;
287 self.packet_mode_pending_events = 0;
288 return data.write(&[event]);
289 }
290 if self.output_queue().readable_size() == 0 {
291 return error!(EAGAIN);
292 }
293 let written = data.write(&[0])?;
294 if written == 0 {
295 return Ok(0);
296 }
297 let res = with_queue!(self.output_queue.read(self, data));
298 match res {
299 Ok(n) => return Ok(n + 1),
300 Err(e) if e == errno!(EAGAIN) => return Ok(1),
301 Err(e) => return Err(e),
302 }
303 }
304 with_queue!(self.output_queue.read(self, data))
305 }
306
307 pub fn main_write(
309 &mut self,
310 data: &mut dyn InputBuffer,
311 ) -> Result<(usize, PendingSignals), Errno> {
312 with_queue!(self.input_queue.write(self, data))
313 }
314
315 pub fn replica_close(&mut self) {
317 self.replica_references = self.replica_references.map(|v| v - 1);
318 }
319
320 pub fn replica_open(&mut self) {
322 self.replica_references = Some(self.replica_references.unwrap_or(0) + 1);
323 }
324
325 pub fn is_replica_closed(&self) -> bool {
326 matches!(self.replica_references, Some(0))
327 }
328
329 pub fn replica_query_events(&self) -> FdEvents {
331 if self.is_main_closed() {
332 return FdEvents::POLLIN | FdEvents::POLLOUT | FdEvents::POLLERR | FdEvents::POLLHUP;
333 }
334 self.input_queue().read_readiness() | self.output_queue().write_readiness()
335 }
336
337 pub fn replica_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
339 if self.is_main_closed() {
340 return Ok(0);
341 }
342 with_queue!(self.input_queue.read(self, data))
343 }
344
345 pub fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
347 if self.is_main_closed() {
348 return error!(EIO);
349 }
350 if self.stopped && self.termios.has_input_flags(IXON) {
351 return error!(EAGAIN);
352 }
353 let (read_from_userspace, signals) = with_queue!(self.output_queue.write(self, data))?;
354 assert!(signals.signals().is_empty());
356 Ok(read_from_userspace)
357 }
358
359 fn input_queue(&self) -> &Queue {
361 self.input_queue.as_ref().unwrap()
362 }
363
364 fn output_queue(&self) -> &Queue {
366 self.output_queue.as_ref().unwrap()
367 }
368
369 fn handle_signals(&mut self, byte: RawByte) -> Option<Signal> {
371 if !self.termios.has_local_flags(ISIG) {
372 return None;
373 }
374 self.termios.signal(byte)
375 }
376
377 fn extend_echo_bytes(&self, target: &mut Vec<RawByte>, byte: RawByte) {
378 if self.termios.has_local_flags(ECHOCTL) {
379 if let Some(control_character_echo) = generate_control_character_echo(byte) {
380 target.extend(control_character_echo);
381 return;
382 }
383 }
384 target.push(byte);
385 }
386
387 fn transform(
388 &mut self,
389 is_input: bool,
390 queue: &mut Queue,
391 buffer: &[RawByte],
392 ) -> (usize, PendingSignals) {
393 if is_input {
394 self.transform_input(queue, buffer)
395 } else {
396 (self.transform_output(queue, buffer), PendingSignals::new())
397 }
398 }
399
400 fn transform_output(&mut self, queue: &mut Queue, original_buffer: &[RawByte]) -> usize {
401 let mut buffer = original_buffer;
402
403 if !self.termios.has_output_flags(OPOST) {
407 let limit = CANON_MAX_BYTES.saturating_sub(queue.readable_size());
408 if limit == 0 {
409 return 0;
410 }
411 let to_write = std::cmp::min(limit, buffer.len());
412 queue.read_queue.push_back(buffer[..to_write].to_vec());
413 return to_write;
414 }
415
416 let mut return_value = 0;
417 while !buffer.is_empty()
418 && queue.readable_size() + queue.line_buffer.len() < CANON_MAX_BYTES
419 {
420 let size = compute_next_character_size(buffer, &self.termios);
421 let mut character_bytes = buffer[..size].to_vec();
422 return_value += size;
423 buffer = &buffer[size..];
424
425 if self.termios.has_output_flags(OLCUC) {
426 character_bytes[0].make_ascii_uppercase();
427 }
428 match character_bytes[0] {
429 b'\n' => {
430 if self.termios.has_output_flags(ONLRET) {
431 self.column = 0;
432 }
433 if self.termios.has_output_flags(ONLCR) {
434 queue.line_buffer.extend_from_slice(&[b'\r', b'\n']);
435 continue;
436 }
437 }
438 b'\r' => {
439 if self.termios.has_output_flags(ONOCR) && self.column == 0 {
440 continue;
441 }
442 if self.termios.has_output_flags(OCRNL) {
443 character_bytes[0] = b'\n';
444 if self.termios.has_output_flags(ONLRET) {
445 self.column = 0;
446 }
447 } else {
448 self.column = 0;
449 }
450 }
451 b'\t' => {
452 let spaces = SPACES_PER_TAB - self.column % SPACES_PER_TAB;
453 if self.termios.c_oflag & TABDLY == XTABS {
454 self.column += spaces;
455 queue.line_buffer.extend(std::iter::repeat(b' ').take(spaces));
456 continue;
457 }
458 self.column += spaces;
459 }
460 BACKSPACE_CHAR => {
461 if self.column > 0 {
462 self.column -= 1;
463 }
464 }
465 _ => {
466 self.column += 1;
467 }
468 }
469 queue.line_buffer.append(&mut character_bytes);
470 }
471 if !queue.line_buffer.is_empty() {
472 queue.flush_line_buffer();
473 }
474 return_value
475 }
476
477 fn transform_input(
478 &mut self,
479 queue: &mut Queue,
480 original_buffer: &[RawByte],
481 ) -> (usize, PendingSignals) {
482 let mut buffer = original_buffer;
483
484 let max_bytes = if self.termios.has_local_flags(ICANON) {
485 CANON_MAX_BYTES
486 } else {
487 NON_CANON_MAX_BYTES
488 };
489
490 let mut return_value = 0;
491 let mut signals = PendingSignals::new();
492 while !buffer.is_empty()
493 && queue.readable_size() + queue.line_buffer.len() < CANON_MAX_BYTES
494 {
495 let size = compute_next_character_size(buffer, &self.termios);
496 let mut character_bytes = buffer[..size].to_vec();
497 if self.lnext {
500 self.lnext = false;
501 if self.termios.has_local_flags(ECHO) {
502 let mut echo_bytes = vec![];
503 self.extend_echo_bytes(&mut echo_bytes, character_bytes[0]);
504 signals.append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
505 }
506
507 queue.line_buffer.extend_from_slice(&character_bytes);
508 buffer = &buffer[size..];
509 return_value += size;
510 continue;
511 }
512
513 if self.termios.has_local_flags(IEXTEN) {
514 if character_bytes[0] == self.termios.c_cc[VLNEXT as usize]
516 && self.termios.c_cc[VLNEXT as usize] != DISABLED_CHAR
517 {
518 self.lnext = true;
519 if self.termios.has_local_flags(ECHO) && self.termios.has_local_flags(ECHOCTL) {
520 let echo_bytes = vec![b'^', BACKSPACE_CHAR];
521 signals
522 .append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
523 }
524 buffer = &buffer[size..];
525 return_value += size;
526 continue;
527 }
528 if character_bytes[0] == self.termios.c_cc[VREPRINT as usize]
530 && self.termios.c_cc[VREPRINT as usize] != DISABLED_CHAR
531 {
532 if self.termios.has_local_flags(ECHO) {
533 let mut echo_bytes = vec![];
534 self.extend_echo_bytes(&mut echo_bytes, character_bytes[0]);
535 echo_bytes.push(b'\n');
536 for byte in &queue.line_buffer {
537 self.extend_echo_bytes(&mut echo_bytes, *byte);
538 }
539 signals
540 .append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
541 }
542 buffer = &buffer[size..];
543 return_value += size;
544 continue;
545 }
546 }
547
548 if self.termios.has_input_flags(IUCLC) && self.termios.has_local_flags(IEXTEN) {
549 character_bytes[0].make_ascii_lowercase();
550 }
551
552 let mut signal_generated = false;
553 if let Some(signal) = self.handle_signals(character_bytes[0]) {
554 signals.add(signal);
555 signal_generated = true;
556 if !self.termios.has_local_flags(NOFLSH) {
557 queue.flush();
558 if let Some(ref mut output_queue) = self.output_queue {
559 output_queue.flush();
560 }
561 }
562 }
563
564 if self.termios.has_input_flags(IXON) {
566 if character_bytes[0] == self.termios.c_cc[VSTOP as usize] {
567 self.stopped = true;
568 buffer = &buffer[size..];
569 return_value += size;
570 continue;
571 }
572 if self.stopped
579 && (character_bytes[0] == self.termios.c_cc[VSTART as usize]
580 || self.termios.has_input_flags(IXANY))
581 {
582 self.stopped = false;
583 if character_bytes[0] == self.termios.c_cc[VSTART as usize] {
588 buffer = &buffer[size..];
589 return_value += size;
590 continue;
591 }
592 }
593 }
594
595 match character_bytes[0] {
596 b'\r' => {
597 if self.termios.has_input_flags(IGNCR) {
598 buffer = &buffer[size..];
599 return_value += size;
600 continue;
601 }
602 if self.termios.has_input_flags(ICRNL) {
603 character_bytes[0] = b'\n';
604 }
605 }
606 b'\n' => {
607 if self.termios.has_input_flags(INLCR) {
608 character_bytes[0] = b'\r'
609 }
610 }
611 _ => {}
612 }
613 if self.termios.has_local_flags(ICANON)
616 && queue.line_buffer.len() + size >= max_bytes
617 && !self.termios.is_terminating(&character_bytes)
618 {
619 buffer = &buffer[size..];
620 return_value += size;
621 continue;
622 }
623
624 if queue.line_buffer.len() + size > max_bytes {
625 break;
626 }
627
628 buffer = &buffer[size..];
629 return_value += size;
630
631 let first_byte = character_bytes[0];
632
633 if self.termios.has_local_flags(ICANON) && self.termios.is_eof(first_byte) {
635 if !queue.line_buffer.is_empty() {
636 queue.flush_line_buffer();
637 }
638 queue.read_queue.push_back(vec![]);
639 break;
640 }
641
642 let mut maybe_erase_span = None;
643 let mut erase_type = None;
644 if self.termios.has_local_flags(ICANON) {
645 if self.termios.is_erase(first_byte) {
646 maybe_erase_span =
647 Some(compute_last_character_span(&queue.line_buffer[..], &self.termios));
648 erase_type = Some(EraseType::Character);
649 } else if self.termios.is_werase(first_byte) {
650 maybe_erase_span =
651 Some(compute_last_word_span(&queue.line_buffer[..], &self.termios));
652 erase_type = Some(EraseType::Word);
653 }
654 if self.termios.is_kill(first_byte) {
655 maybe_erase_span =
656 Some(compute_last_line_span(&queue.line_buffer[..], &self.termios));
657 erase_type = Some(EraseType::Line);
658 }
659 }
660
661 let mut erased_bytes = Option::None;
662 if let Some(erase_span) = maybe_erase_span {
663 if erase_span.bytes == 0 {
664 continue;
665 }
666 if self.termios.has_local_flags(ECHOPRT) {
667 erased_bytes = Some(
668 queue.line_buffer[queue.line_buffer.len() - erase_span.bytes..].to_vec(),
669 );
670 }
671 queue.line_buffer.truncate(queue.line_buffer.len() - erase_span.bytes);
672 } else if !signal_generated {
673 queue.line_buffer.extend_from_slice(&character_bytes);
674 }
675
676 let mut echo_bytes = vec![];
678 if self.termios.has_local_flags(ECHO) {
679 if let Some(erase_span) = maybe_erase_span {
680 match erase_type {
681 Some(EraseType::Character) | Some(EraseType::Word) => {
682 if self.termios.has_local_flags(ECHOPRT) {
683 if let Some(bytes) = erased_bytes {
684 if !self.erasing {
685 echo_bytes.push(b'\\');
686 self.erasing = true;
687 }
688 for byte in bytes.iter().rev() {
689 self.extend_echo_bytes(&mut echo_bytes, *byte);
690 }
691 }
692 } else if self.termios.has_local_flags(ECHOE) {
693 echo_bytes = generate_erase_echo(&erase_span);
694 }
695 }
696 Some(EraseType::Line) => {
697 if self.termios.has_local_flags(ECHOKE) {
698 echo_bytes = generate_erase_echo(&erase_span);
699 } else if self.termios.has_local_flags(ECHOK) {
700 self.extend_echo_bytes(&mut echo_bytes, first_byte);
701 echo_bytes.push(b'\n');
702 }
703 }
704 None => {
705 unreachable!("Erase type should be Some when maybe_erase_span is Some")
706 }
707 }
708 if self.erasing && queue.line_buffer.is_empty() {
709 echo_bytes.push(b'/');
710 self.erasing = false;
711 }
712 } else {
713 if self.erasing && first_byte != b'\n' {
714 echo_bytes.push(b'/');
715 self.erasing = false;
716 }
717 }
718
719 let needs_normal_echo =
720 if maybe_erase_span.is_some() { echo_bytes.is_empty() } else { true };
721
722 if needs_normal_echo {
723 let mut char_echo = vec![];
724 if self.termios.has_local_flags(ECHOCTL) {
725 if let Some(control_character_echo) =
726 generate_control_character_echo(first_byte)
727 {
728 char_echo = control_character_echo;
729 }
730 }
731 if char_echo.is_empty() {
732 char_echo = character_bytes.clone();
733 }
734 echo_bytes.extend(char_echo);
735 }
736 } else if self.termios.has_local_flags(ECHONL) && first_byte == b'\n' {
737 echo_bytes.extend_from_slice(&character_bytes);
738 }
739
740 if !echo_bytes.is_empty() {
741 signals.append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
742 }
743
744 if self.termios.has_local_flags(ICANON) && self.termios.is_terminating(&character_bytes)
746 {
747 queue.flush_line_buffer();
748 }
749 }
750 if !self.termios.has_local_flags(ICANON) && !queue.line_buffer.is_empty() {
752 queue.flush_line_buffer();
753 }
754
755 (return_value, signals)
756 }
757}
758
759type RawByte = u8;
762
763#[derive(Debug, Default)]
764struct Queue {
765 read_queue: VecDeque<Vec<u8>>,
768
769 line_buffer: Vec<u8>,
773
774 wait_buffers: VecDeque<Vec<RawByte>>,
777
778 total_wait_buffer_length: usize,
780
781 is_input: bool,
783}
784
785impl Queue {
786 fn output_queue() -> Option<Self> {
787 Some(Queue { is_input: false, ..Default::default() })
788 }
789
790 fn input_queue() -> Option<Self> {
791 Some(Queue { is_input: true, ..Default::default() })
792 }
793
794 fn write_readiness(&self) -> FdEvents {
796 if self.total_wait_buffer_length < WAIT_BUFFER_MAX_BYTES {
797 FdEvents::POLLOUT
798 } else {
799 FdEvents::empty()
800 }
801 }
802
803 fn read_readiness(&self) -> FdEvents {
805 if !self.read_queue.is_empty() { FdEvents::POLLIN } else { FdEvents::empty() }
807 }
808
809 fn readable_size(&self) -> usize {
811 self.read_queue.iter().map(|v| v.len()).sum()
814 }
815
816 fn read(
818 &mut self,
819 terminal: &mut LineDiscipline,
820 data: &mut dyn OutputBuffer,
821 ) -> Result<usize, Errno> {
822 if self.read_queue.is_empty() {
823 return error!(EAGAIN);
824 }
825
826 let mut total_written = 0;
827 while let Some(mut packet) = self.read_queue.pop_front() {
828 if packet.is_empty() {
829 if total_written > 0 {
830 self.read_queue.push_front(packet);
833 }
834 break;
835 }
836
837 match data.write(&packet) {
838 Ok(written) => {
839 total_written += written;
840 if written < packet.len() {
841 let remaining = packet.split_off(written);
843 self.read_queue.push_front(remaining);
844 break;
846 }
847
848 if self.is_input && terminal.termios.has_local_flags(ICANON) {
850 break;
851 }
852 }
853 Err(e) => {
854 self.read_queue.push_front(packet);
856 if total_written > 0 {
857 return Ok(total_written);
859 }
860 return Err(e);
861 }
862 }
863 }
864
865 let signals = self.drain_waiting_buffer(terminal);
866 assert!(signals.signals().is_empty());
867 Ok(total_written)
868 }
869
870 fn write(
872 &mut self,
873 terminal: &mut LineDiscipline,
874 data: &mut dyn InputBuffer,
875 ) -> Result<(usize, PendingSignals), Errno> {
876 let room = WAIT_BUFFER_MAX_BYTES - self.total_wait_buffer_length;
877 let data_length = data.available();
878 if room == 0 && data_length > 0 {
879 return error!(EAGAIN);
880 }
881 let buffer = data.read_to_vec_exact(std::cmp::min(room, data_length))?;
882 let read_from_userspace = buffer.len();
883 let signals = self.push_to_waiting_buffer(terminal, buffer);
884 Ok((read_from_userspace, signals))
885 }
886
887 fn write_bytes(&mut self, terminal: &mut LineDiscipline, buffer: &[RawByte]) -> PendingSignals {
889 self.push_to_waiting_buffer(terminal, buffer.to_vec())
890 }
891
892 fn push_to_waiting_buffer(
894 &mut self,
895 terminal: &mut LineDiscipline,
896 buffer: Vec<RawByte>,
897 ) -> PendingSignals {
898 self.total_wait_buffer_length += buffer.len();
899 self.wait_buffers.push_back(buffer);
900 self.drain_waiting_buffer(terminal)
901 }
902
903 fn drain_waiting_buffer(&mut self, terminal: &mut LineDiscipline) -> PendingSignals {
905 let mut signals_to_return = PendingSignals::new();
906 while let Some(wait_buffer) = self.wait_buffers.pop_front() {
907 self.total_wait_buffer_length -= wait_buffer.len();
908 let (count, signals) = terminal.transform(self.is_input, self, &wait_buffer);
909 signals_to_return.append(signals);
910 if count != wait_buffer.len() {
911 let remaining = wait_buffer[count..].to_vec();
912 self.total_wait_buffer_length += remaining.len();
913 self.wait_buffers.push_front(remaining);
914 break;
915 }
916 }
917 signals_to_return
918 }
919
920 fn flush_line_buffer(&mut self) {
922 self.read_queue.push_back(std::mem::take(&mut self.line_buffer));
923 }
924
925 fn flush(&mut self) {
927 self.read_queue.clear();
928 self.line_buffer.clear();
929 self.wait_buffers.clear();
930 self.total_wait_buffer_length = 0;
931 }
932
933 fn flush_unprocessed(&mut self) {
935 self.wait_buffers.clear();
936 self.total_wait_buffer_length = 0;
937 }
938
939 fn on_canon_disabled(&mut self, terminal: &mut LineDiscipline) -> PendingSignals {
941 let signals = self.drain_waiting_buffer(terminal);
942 if !self.line_buffer.is_empty() {
943 self.flush_line_buffer();
944 }
945 signals
946 }
947}
948
949fn get_ascii(c: char) -> u8 {
953 let mut dest: [u8; 1] = [0];
954 c.encode_utf8(&mut dest);
955 dest[0]
956}
957
958fn get_control_character(c: char) -> cc_t {
960 get_ascii(c) - get_ascii('A') + 1
961}
962
963fn get_default_control_characters() -> [cc_t; 19usize] {
965 [
966 get_control_character('C'), get_control_character('\\'), get_ascii('\x7f'), get_control_character('U'), get_control_character('D'), 0, 1, 0, get_control_character('Q'), get_control_character('S'), get_control_character('Z'), 0, get_control_character('R'), get_control_character('O'), get_control_character('W'), get_control_character('V'), 0, 0, 0, ]
986}
987
988const DEFAULT_SPEED: u32 = 38400;
989
990pub fn get_default_termios() -> uapi::termios2 {
992 uapi::termios2 {
993 c_iflag: uapi::ICRNL | uapi::IXON,
994 c_oflag: uapi::OPOST | uapi::ONLCR,
995 c_cflag: uapi::B38400 | uapi::CS8 | uapi::CREAD,
996 c_lflag: uapi::ISIG
997 | uapi::ICANON
998 | uapi::ECHO
999 | uapi::ECHOE
1000 | uapi::ECHOK
1001 | uapi::ECHOCTL
1002 | uapi::ECHOKE
1003 | uapi::IEXTEN,
1004 c_line: 0,
1005 c_cc: get_default_control_characters(),
1006 c_ispeed: DEFAULT_SPEED,
1007 c_ospeed: DEFAULT_SPEED,
1008 }
1009}
1010
1011trait TermIOS {
1013 fn has_input_flags(&self, flags: tcflag_t) -> bool;
1014 fn has_output_flags(&self, flags: tcflag_t) -> bool;
1015 fn has_local_flags(&self, flags: tcflag_t) -> bool;
1016 fn is_eof(&self, c: RawByte) -> bool;
1017 fn is_erase(&self, c: RawByte) -> bool;
1018 fn is_werase(&self, c: RawByte) -> bool;
1019 fn is_kill(&self, c: RawByte) -> bool;
1020 fn is_terminating(&self, character_bytes: &[RawByte]) -> bool;
1021 fn signal(&self, c: RawByte) -> Option<Signal>;
1022}
1023
1024impl TermIOS for uapi::termios2 {
1025 fn has_input_flags(&self, flags: tcflag_t) -> bool {
1026 self.c_iflag & flags == flags
1027 }
1028 fn has_output_flags(&self, flags: tcflag_t) -> bool {
1029 self.c_oflag & flags == flags
1030 }
1031 fn has_local_flags(&self, flags: tcflag_t) -> bool {
1032 self.c_lflag & flags == flags
1033 }
1034 fn is_eof(&self, c: RawByte) -> bool {
1035 c == self.c_cc[VEOF as usize] && self.c_cc[VEOF as usize] != DISABLED_CHAR
1036 }
1037 fn is_erase(&self, c: RawByte) -> bool {
1038 c == self.c_cc[VERASE as usize] && self.c_cc[VERASE as usize] != DISABLED_CHAR
1039 }
1040 fn is_werase(&self, c: RawByte) -> bool {
1041 c == self.c_cc[VWERASE as usize]
1042 && self.c_cc[VWERASE as usize] != DISABLED_CHAR
1043 && self.has_local_flags(IEXTEN)
1044 }
1045 fn is_kill(&self, c: RawByte) -> bool {
1046 c == self.c_cc[VKILL as usize] && self.c_cc[VKILL as usize] != DISABLED_CHAR
1047 }
1048 fn is_terminating(&self, character_bytes: &[RawByte]) -> bool {
1049 if character_bytes.len() != 1 {
1051 return false;
1052 }
1053 let c = character_bytes[0];
1054
1055 if self.is_eof(c) {
1057 return true;
1058 }
1059
1060 if c == DISABLED_CHAR {
1061 return false;
1062 }
1063 if c == b'\n' || c == self.c_cc[VEOL as usize] {
1064 return true;
1065 }
1066 if c == self.c_cc[VEOL2 as usize] {
1067 return self.has_local_flags(IEXTEN);
1068 }
1069 false
1070 }
1071 fn signal(&self, c: RawByte) -> Option<Signal> {
1072 if c == DISABLED_CHAR {
1073 return None;
1074 }
1075 if c == self.c_cc[VINTR as usize] {
1076 return Some(SIGINT);
1077 }
1078 if c == self.c_cc[VQUIT as usize] {
1079 return Some(SIGQUIT);
1080 }
1081 if c == self.c_cc[VSUSP as usize] {
1082 return Some(SIGSTOP);
1083 }
1084 None
1085 }
1086}
1087
1088fn compute_next_character_size(buffer: &[RawByte], termios: &uapi::termios2) -> usize {
1089 if !termios.has_input_flags(IUTF8) {
1090 return 1;
1091 }
1092
1093 #[derive(Default)]
1094 struct Receiver {
1095 done: Option<bool>,
1096 }
1097
1098 impl utf8parse::Receiver for Receiver {
1099 fn codepoint(&mut self, _c: char) {
1100 self.done = Some(true);
1101 }
1102 fn invalid_sequence(&mut self) {
1103 self.done = Some(false);
1104 }
1105 }
1106
1107 let mut byte_count = 0;
1108 let mut receiver = Receiver::default();
1109 let mut parser = utf8parse::Parser::new();
1110 while receiver.done.is_none() && byte_count < buffer.len() {
1111 parser.advance(&mut receiver, buffer[byte_count]);
1112 byte_count += 1;
1113 }
1114 if receiver.done == Some(true) { byte_count } else { 1 }
1115}
1116
1117fn is_ascii(c: RawByte) -> bool {
1118 c & 0x80 == 0
1119}
1120
1121fn is_utf8_start(c: RawByte) -> bool {
1122 c & 0xC0 == 0xC0
1123}
1124
1125fn generate_erase_echo(erase_span: &BufferSpan) -> Vec<RawByte> {
1126 let erase_echo = [BACKSPACE_CHAR, b' ', BACKSPACE_CHAR];
1127 erase_echo.iter().cycle().take(erase_echo.len() * erase_span.characters).map(|c| *c).collect()
1128}
1129
1130fn generate_control_character_echo(c: RawByte) -> Option<Vec<RawByte>> {
1131 if matches!(c, 0..=0x8 | 0xB..=0xC | 0xE..=0x1F) {
1132 Some(vec![b'^', c + CONTROL_OFFSET])
1133 } else {
1134 None
1135 }
1136}
1137
1138#[derive(Default, Debug, Clone, Copy)]
1139struct BufferSpan {
1140 bytes: usize,
1141 characters: usize,
1142}
1143
1144impl std::ops::AddAssign<Self> for BufferSpan {
1145 fn add_assign(&mut self, rhs: Self) {
1146 self.bytes += rhs.bytes;
1147 self.characters += rhs.characters;
1148 }
1149}
1150
1151fn compute_last_character_span(buffer: &[RawByte], termios: &uapi::termios2) -> BufferSpan {
1152 if buffer.is_empty() {
1153 return BufferSpan::default();
1154 }
1155 if termios.has_input_flags(IUTF8) {
1156 let mut bytes = 0;
1157 for c in buffer.iter().rev() {
1158 bytes += 1;
1159 if is_ascii(*c) || is_utf8_start(*c) {
1160 return BufferSpan { bytes, characters: 1 };
1161 }
1162 }
1163 BufferSpan::default()
1164 } else {
1165 BufferSpan { bytes: 1, characters: 1 }
1166 }
1167}
1168
1169fn compute_last_word_span(buffer: &[RawByte], termios: &uapi::termios2) -> BufferSpan {
1170 fn is_whitespace(c: RawByte) -> bool {
1171 c == b' ' || c == b'\t'
1172 }
1173
1174 let mut in_word = false;
1175 let mut word_span = BufferSpan::default();
1176 let mut remaining = buffer.len();
1177 loop {
1178 let span = compute_last_character_span(&buffer[..remaining], termios);
1179 if span.bytes == 0 {
1180 break;
1181 }
1182 if span.bytes == 1 {
1183 let c = buffer[remaining - 1];
1184 if in_word {
1185 if is_whitespace(c) {
1186 break;
1187 }
1188 } else {
1189 if !is_whitespace(c) {
1190 in_word = true;
1191 }
1192 }
1193 }
1194 remaining -= span.bytes;
1195 word_span += span;
1196 }
1197
1198 word_span
1199}
1200
1201fn compute_last_line_span(buffer: &[RawByte], termios: &uapi::termios2) -> BufferSpan {
1202 let mut line_span = BufferSpan::default();
1203 let mut remaining = buffer.len();
1204
1205 loop {
1206 let span = compute_last_character_span(&buffer[..remaining], termios);
1207 if span.bytes == 0 {
1208 break;
1209 }
1210 if span.bytes == 1 {
1211 let c = buffer[remaining - 1];
1212 if c == b'\n' {
1213 break;
1214 }
1215 }
1216 remaining -= span.bytes;
1217 line_span += span;
1218 }
1219
1220 line_span
1221}
1222
1223#[cfg(test)]
1224mod tests {
1225 use super::*;
1226
1227 #[::fuchsia::test]
1228 fn test_ascii_conversion() {
1229 assert_eq!(get_ascii(' '), 32);
1230 }
1231
1232 #[::fuchsia::test]
1233 fn test_control_character() {
1234 assert_eq!(get_control_character('C'), 3);
1235 }
1236
1237 #[::fuchsia::test]
1238 fn test_compute_next_character_size_non_utf8() {
1239 let termios = get_default_termios();
1240 for i in 0..=255 {
1241 let array: &[u8] = &[i, 0xa9, 0];
1242 assert_eq!(compute_next_character_size(array, &termios), 1);
1243 }
1244 }
1245
1246 #[::fuchsia::test]
1247 fn test_compute_next_character_size_utf8() {
1248 let mut termios = get_default_termios();
1249 termios.c_iflag |= IUTF8;
1250 for i in 0..128 {
1251 let array: &[RawByte] = &[i, 0xa9, 0];
1252 assert_eq!(compute_next_character_size(array, &termios), 1);
1253 }
1254 let array: &[RawByte] = &[0xc2, 0xa9, 0];
1255 assert_eq!(compute_next_character_size(array, &termios), 2);
1256 let array: &[RawByte] = &[0xc2, 255, 0];
1257 assert_eq!(compute_next_character_size(array, &termios), 1);
1258 }
1259
1260 #[::fuchsia::test]
1261 fn test_signal_handling_with_disabled_chars() {
1262 let mut termios = get_default_termios();
1263 termios.c_cc[VINTR as usize] = DISABLED_CHAR;
1264 termios.c_cc[VQUIT as usize] = DISABLED_CHAR;
1265 termios.c_cc[VSUSP as usize] = DISABLED_CHAR;
1266
1267 assert_eq!(termios.signal(0), None);
1268 assert_eq!(termios.signal(3), None); assert_eq!(termios.signal(28), None); assert_eq!(termios.signal(26), None); }
1272
1273 struct TestBuffer {
1274 data: Vec<u8>,
1275 }
1276
1277 impl InputBuffer for TestBuffer {
1278 fn available(&self) -> usize {
1279 self.data.len()
1280 }
1281 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
1282 if size > self.data.len() {
1283 return error!(EAGAIN);
1284 }
1285 Ok(self.data.drain(0..size).collect())
1286 }
1287 }
1288
1289 impl OutputBuffer for TestBuffer {
1290 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
1291 self.data.extend_from_slice(data);
1292 Ok(data.len())
1293 }
1294 }
1295
1296 #[::fuchsia::test]
1297 fn test_flush() {
1298 fn make_ld() -> LineDiscipline {
1299 let mut ld = LineDiscipline::default();
1300 ld.main_open();
1301 ld.replica_open();
1302
1303 let mut termios = get_default_termios();
1304 termios.c_lflag &= !ECHO;
1305 termios.c_oflag &= !OPOST;
1306 let _ = ld.set_termios(termios);
1307
1308 let mut input = TestBuffer { data: b"ping\n".to_vec() };
1311 let (written, signals) = ld.main_write(&mut input).unwrap();
1312 assert_eq!(written, 5);
1313 assert!(signals.signals().is_empty());
1314
1315 let mut output = TestBuffer { data: b"pong\n".to_vec() };
1318 let written = ld.replica_write(&mut output).unwrap();
1319 assert_eq!(written, 5);
1320 ld
1321 }
1322
1323 let mut read_buf = TestBuffer { data: vec![] };
1324
1325 let mut ld = make_ld();
1327 ld.flush(true, uapi::TCIFLUSH).unwrap();
1328 read_buf.data.clear();
1329 assert_eq!(error!(EAGAIN), ld.main_read(&mut read_buf));
1330 assert!(read_buf.data.is_empty());
1331 read_buf.data.clear();
1332 assert!(ld.replica_read(&mut read_buf).is_ok());
1333 assert_eq!(read_buf.data, b"ping\n");
1334
1335 let mut ld = make_ld();
1337 ld.flush(false, uapi::TCIFLUSH).unwrap();
1338 read_buf.data.clear();
1339 assert!(ld.main_read(&mut read_buf).is_ok());
1340 assert_eq!(read_buf.data, b"pong\n");
1341 read_buf.data.clear();
1342 assert_eq!(error!(EAGAIN), ld.replica_read(&mut read_buf));
1343 assert!(read_buf.data.is_empty());
1344
1345 let mut ld = make_ld();
1347 ld.flush(true, uapi::TCOFLUSH).unwrap();
1348 read_buf.data.clear();
1349 assert!(ld.main_read(&mut read_buf).is_ok());
1350 assert_eq!(read_buf.data, b"pong\n");
1351 read_buf.data.clear();
1352 assert!(ld.replica_read(&mut read_buf).is_ok());
1353 assert_eq!(read_buf.data, b"ping\n");
1354
1355 let mut ld = make_ld();
1357 ld.flush(false, uapi::TCOFLUSH).unwrap();
1358 read_buf.data.clear();
1359 assert!(ld.main_read(&mut read_buf).is_ok());
1360 assert_eq!(read_buf.data, b"pong\n");
1361 read_buf.data.clear();
1362 assert!(ld.replica_read(&mut read_buf).is_ok());
1363 assert_eq!(read_buf.data, b"ping\n");
1364
1365 let mut ld = make_ld();
1367 ld.flush(true, uapi::TCIOFLUSH).unwrap();
1368 read_buf.data.clear();
1369 assert_eq!(error!(EAGAIN), ld.main_read(&mut read_buf));
1370 read_buf.data.clear();
1371 assert!(ld.replica_read(&mut read_buf).is_ok());
1372 assert_eq!(read_buf.data, b"ping\n");
1373
1374 let mut ld = make_ld();
1376 ld.flush(false, uapi::TCIOFLUSH).unwrap();
1377 read_buf.data.clear();
1378 assert!(ld.main_read(&mut read_buf).is_ok());
1379 assert_eq!(read_buf.data, b"pong\n");
1380 read_buf.data.clear();
1381 assert_eq!(error!(EAGAIN), ld.replica_read(&mut read_buf));
1382 }
1383}
1384
1385pub mod testing;