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> {
214 match (is_main, queue_selector) {
215 (_, uapi::TCOFLUSH) => {}
216 (true, uapi::TCIFLUSH) | (true, uapi::TCIOFLUSH) => {
217 self.output_queue.as_mut().unwrap().flush();
218 }
219 (false, uapi::TCIFLUSH) | (false, uapi::TCIOFLUSH) => {
220 self.input_queue.as_mut().unwrap().flush();
221 }
222 _ => return error!(EINVAL),
223 }
224 Ok(())
225 }
226
227 pub fn main_close(&mut self) {
229 self.main_references = self.main_references.map(|v| v - 1);
230 }
231
232 pub fn main_open(&mut self) {
234 self.main_references = Some(self.main_references.unwrap_or(0) + 1);
235 }
236
237 pub fn is_main_closed(&self) -> bool {
238 matches!(self.main_references, Some(0))
239 }
240
241 pub fn main_query_events(&self) -> FdEvents {
243 if self.is_replica_closed() && self.output_queue().readable_size() == 0 {
244 return FdEvents::POLLOUT | FdEvents::POLLHUP;
245 }
246 let mut events =
247 self.output_queue().read_readiness() | self.input_queue().write_readiness();
248 if self.packet_mode_enabled && self.packet_mode_pending_events != 0 {
249 events |= FdEvents::POLLIN | FdEvents::POLLPRI;
250 }
251 events
252 }
253
254 pub fn main_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
256 if self.is_replica_closed() && self.output_queue().readable_size() == 0 {
257 return error!(EIO);
258 }
259 if self.packet_mode_enabled {
260 if self.packet_mode_pending_events != 0 {
261 let event = self.packet_mode_pending_events;
262 self.packet_mode_pending_events = 0;
263 return data.write(&[event]);
264 }
265 if self.output_queue().readable_size() == 0 {
266 return error!(EAGAIN);
267 }
268 let written = data.write(&[0])?;
269 if written == 0 {
270 return Ok(0);
271 }
272 let res = with_queue!(self.output_queue.read(self, data));
273 match res {
274 Ok(n) => return Ok(n + 1),
275 Err(e) if e == errno!(EAGAIN) => return Ok(1),
276 Err(e) => return Err(e),
277 }
278 }
279 with_queue!(self.output_queue.read(self, data))
280 }
281
282 pub fn main_write(
284 &mut self,
285 data: &mut dyn InputBuffer,
286 ) -> Result<(usize, PendingSignals), Errno> {
287 with_queue!(self.input_queue.write(self, data))
288 }
289
290 pub fn replica_close(&mut self) {
292 self.replica_references = self.replica_references.map(|v| v - 1);
293 }
294
295 pub fn replica_open(&mut self) {
297 self.replica_references = Some(self.replica_references.unwrap_or(0) + 1);
298 }
299
300 pub fn is_replica_closed(&self) -> bool {
301 matches!(self.replica_references, Some(0))
302 }
303
304 pub fn replica_query_events(&self) -> FdEvents {
306 if self.is_main_closed() {
307 return FdEvents::POLLIN | FdEvents::POLLOUT | FdEvents::POLLERR | FdEvents::POLLHUP;
308 }
309 self.input_queue().read_readiness() | self.output_queue().write_readiness()
310 }
311
312 pub fn replica_read(&mut self, data: &mut dyn OutputBuffer) -> Result<usize, Errno> {
314 if self.is_main_closed() {
315 return Ok(0);
316 }
317 with_queue!(self.input_queue.read(self, data))
318 }
319
320 pub fn replica_write(&mut self, data: &mut dyn InputBuffer) -> Result<usize, Errno> {
322 if self.is_main_closed() {
323 return error!(EIO);
324 }
325 if self.stopped && self.termios.has_input_flags(IXON) {
326 return error!(EAGAIN);
327 }
328 let (read_from_userspace, signals) = with_queue!(self.output_queue.write(self, data))?;
329 assert!(signals.signals().is_empty());
331 Ok(read_from_userspace)
332 }
333
334 fn input_queue(&self) -> &Queue {
336 self.input_queue.as_ref().unwrap()
337 }
338
339 fn output_queue(&self) -> &Queue {
341 self.output_queue.as_ref().unwrap()
342 }
343
344 fn handle_signals(&mut self, byte: RawByte) -> Option<Signal> {
346 if !self.termios.has_local_flags(ISIG) {
347 return None;
348 }
349 self.termios.signal(byte)
350 }
351
352 fn extend_echo_bytes(&self, target: &mut Vec<RawByte>, byte: RawByte) {
353 if self.termios.has_local_flags(ECHOCTL) {
354 if let Some(control_character_echo) = generate_control_character_echo(byte) {
355 target.extend(control_character_echo);
356 return;
357 }
358 }
359 target.push(byte);
360 }
361
362 fn transform(
363 &mut self,
364 is_input: bool,
365 queue: &mut Queue,
366 buffer: &[RawByte],
367 ) -> (usize, PendingSignals) {
368 if is_input {
369 self.transform_input(queue, buffer)
370 } else {
371 (self.transform_output(queue, buffer), PendingSignals::new())
372 }
373 }
374
375 fn transform_output(&mut self, queue: &mut Queue, original_buffer: &[RawByte]) -> usize {
376 let mut buffer = original_buffer;
377
378 if !self.termios.has_output_flags(OPOST) {
382 queue.read_queue.push_back(buffer.to_vec());
383 return buffer.len();
384 }
385
386 let mut return_value = 0;
387 while !buffer.is_empty() {
388 let size = compute_next_character_size(buffer, &self.termios);
389 let mut character_bytes = buffer[..size].to_vec();
390 return_value += size;
391 buffer = &buffer[size..];
392
393 if self.termios.has_output_flags(OLCUC) {
394 character_bytes[0].make_ascii_uppercase();
395 }
396 match character_bytes[0] {
397 b'\n' => {
398 if self.termios.has_output_flags(ONLRET) {
399 self.column = 0;
400 }
401 if self.termios.has_output_flags(ONLCR) {
402 queue.line_buffer.extend_from_slice(&[b'\r', b'\n']);
403 continue;
404 }
405 }
406 b'\r' => {
407 if self.termios.has_output_flags(ONOCR) && self.column == 0 {
408 continue;
409 }
410 if self.termios.has_output_flags(OCRNL) {
411 character_bytes[0] = b'\n';
412 if self.termios.has_output_flags(ONLRET) {
413 self.column = 0;
414 }
415 } else {
416 self.column = 0;
417 }
418 }
419 b'\t' => {
420 let spaces = SPACES_PER_TAB - self.column % SPACES_PER_TAB;
421 if self.termios.c_oflag & TABDLY == XTABS {
422 self.column += spaces;
423 queue.line_buffer.extend(std::iter::repeat(b' ').take(spaces));
424 continue;
425 }
426 self.column += spaces;
427 }
428 BACKSPACE_CHAR => {
429 if self.column > 0 {
430 self.column -= 1;
431 }
432 }
433 _ => {
434 self.column += 1;
435 }
436 }
437 queue.line_buffer.append(&mut character_bytes);
438 }
439 if !queue.line_buffer.is_empty() {
440 queue.flush_line_buffer();
441 }
442 return_value
443 }
444
445 fn transform_input(
446 &mut self,
447 queue: &mut Queue,
448 original_buffer: &[RawByte],
449 ) -> (usize, PendingSignals) {
450 let mut buffer = original_buffer;
451
452 let max_bytes = if self.termios.has_local_flags(ICANON) {
453 CANON_MAX_BYTES
454 } else {
455 NON_CANON_MAX_BYTES
456 };
457
458 let mut return_value = 0;
459 let mut signals = PendingSignals::new();
460 while !buffer.is_empty() && queue.line_buffer.len() < CANON_MAX_BYTES {
461 let size = compute_next_character_size(buffer, &self.termios);
462 let mut character_bytes = buffer[..size].to_vec();
463 if self.lnext {
466 self.lnext = false;
467 if self.termios.has_local_flags(ECHO) {
468 let mut echo_bytes = vec![];
469 self.extend_echo_bytes(&mut echo_bytes, character_bytes[0]);
470 signals.append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
471 }
472
473 queue.line_buffer.extend_from_slice(&character_bytes);
474 buffer = &buffer[size..];
475 return_value += size;
476 continue;
477 }
478
479 if self.termios.has_local_flags(IEXTEN) {
480 if character_bytes[0] == self.termios.c_cc[VLNEXT as usize]
482 && self.termios.c_cc[VLNEXT as usize] != DISABLED_CHAR
483 {
484 self.lnext = true;
485 if self.termios.has_local_flags(ECHO) && self.termios.has_local_flags(ECHOCTL) {
486 let echo_bytes = vec![b'^', BACKSPACE_CHAR];
487 signals
488 .append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
489 }
490 buffer = &buffer[size..];
491 return_value += size;
492 continue;
493 }
494 if character_bytes[0] == self.termios.c_cc[VREPRINT as usize]
496 && self.termios.c_cc[VREPRINT as usize] != DISABLED_CHAR
497 {
498 if self.termios.has_local_flags(ECHO) {
499 let mut echo_bytes = vec![];
500 self.extend_echo_bytes(&mut echo_bytes, character_bytes[0]);
501 echo_bytes.push(b'\n');
502 for byte in &queue.line_buffer {
503 self.extend_echo_bytes(&mut echo_bytes, *byte);
504 }
505 signals
506 .append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
507 }
508 buffer = &buffer[size..];
509 return_value += size;
510 continue;
511 }
512 }
513
514 if self.termios.has_input_flags(IUCLC) && self.termios.has_local_flags(IEXTEN) {
515 character_bytes[0].make_ascii_lowercase();
516 }
517
518 let mut signal_generated = false;
519 if let Some(signal) = self.handle_signals(character_bytes[0]) {
520 signals.add(signal);
521 signal_generated = true;
522 if !self.termios.has_local_flags(NOFLSH) {
523 queue.flush();
524 if let Some(ref mut output_queue) = self.output_queue {
525 output_queue.flush();
526 }
527 }
528 }
529
530 if self.termios.has_input_flags(IXON) {
532 if character_bytes[0] == self.termios.c_cc[VSTOP as usize] {
533 self.stopped = true;
534 buffer = &buffer[size..];
535 return_value += size;
536 continue;
537 }
538 if self.stopped
545 && (character_bytes[0] == self.termios.c_cc[VSTART as usize]
546 || self.termios.has_input_flags(IXANY))
547 {
548 self.stopped = false;
549 if character_bytes[0] == self.termios.c_cc[VSTART as usize] {
554 buffer = &buffer[size..];
555 return_value += size;
556 continue;
557 }
558 }
559 }
560
561 match character_bytes[0] {
562 b'\r' => {
563 if self.termios.has_input_flags(IGNCR) {
564 buffer = &buffer[size..];
565 return_value += size;
566 continue;
567 }
568 if self.termios.has_input_flags(ICRNL) {
569 character_bytes[0] = b'\n';
570 }
571 }
572 b'\n' => {
573 if self.termios.has_input_flags(INLCR) {
574 character_bytes[0] = b'\r'
575 }
576 }
577 _ => {}
578 }
579 if self.termios.has_local_flags(ICANON)
582 && queue.line_buffer.len() + size >= max_bytes
583 && !self.termios.is_terminating(&character_bytes)
584 {
585 buffer = &buffer[size..];
586 return_value += size;
587 continue;
588 }
589
590 if queue.line_buffer.len() + size > max_bytes {
591 break;
592 }
593
594 buffer = &buffer[size..];
595 return_value += size;
596
597 let first_byte = character_bytes[0];
598
599 if self.termios.has_local_flags(ICANON) && self.termios.is_eof(first_byte) {
601 if !queue.line_buffer.is_empty() {
602 queue.flush_line_buffer();
603 }
604 queue.read_queue.push_back(vec![]);
605 break;
606 }
607
608 let mut maybe_erase_span = None;
609 let mut erase_type = None;
610 if self.termios.has_local_flags(ICANON) {
611 if self.termios.is_erase(first_byte) {
612 maybe_erase_span =
613 Some(compute_last_character_span(&queue.line_buffer[..], &self.termios));
614 erase_type = Some(EraseType::Character);
615 } else if self.termios.is_werase(first_byte) {
616 maybe_erase_span =
617 Some(compute_last_word_span(&queue.line_buffer[..], &self.termios));
618 erase_type = Some(EraseType::Word);
619 }
620 if self.termios.is_kill(first_byte) {
621 maybe_erase_span =
622 Some(compute_last_line_span(&queue.line_buffer[..], &self.termios));
623 erase_type = Some(EraseType::Line);
624 }
625 }
626
627 let mut erased_bytes = Option::None;
628 if let Some(erase_span) = maybe_erase_span {
629 if erase_span.bytes == 0 {
630 continue;
631 }
632 if self.termios.has_local_flags(ECHOPRT) {
633 erased_bytes = Some(
634 queue.line_buffer[queue.line_buffer.len() - erase_span.bytes..].to_vec(),
635 );
636 }
637 queue.line_buffer.truncate(queue.line_buffer.len() - erase_span.bytes);
638 } else if !signal_generated {
639 queue.line_buffer.extend_from_slice(&character_bytes);
640 }
641
642 let mut echo_bytes = vec![];
644 if self.termios.has_local_flags(ECHO) {
645 if let Some(erase_span) = maybe_erase_span {
646 match erase_type {
647 Some(EraseType::Character) | Some(EraseType::Word) => {
648 if self.termios.has_local_flags(ECHOPRT) {
649 if let Some(bytes) = erased_bytes {
650 if !self.erasing {
651 echo_bytes.push(b'\\');
652 self.erasing = true;
653 }
654 for byte in bytes.iter().rev() {
655 self.extend_echo_bytes(&mut echo_bytes, *byte);
656 }
657 }
658 } else if self.termios.has_local_flags(ECHOE) {
659 echo_bytes = generate_erase_echo(&erase_span);
660 }
661 }
662 Some(EraseType::Line) => {
663 if self.termios.has_local_flags(ECHOKE) {
664 echo_bytes = generate_erase_echo(&erase_span);
665 } else if self.termios.has_local_flags(ECHOK) {
666 self.extend_echo_bytes(&mut echo_bytes, first_byte);
667 echo_bytes.push(b'\n');
668 }
669 }
670 None => {
671 unreachable!("Erase type should be Some when maybe_erase_span is Some")
672 }
673 }
674 if self.erasing && queue.line_buffer.is_empty() {
675 echo_bytes.push(b'/');
676 self.erasing = false;
677 }
678 } else {
679 if self.erasing && first_byte != b'\n' {
680 echo_bytes.push(b'/');
681 self.erasing = false;
682 }
683 }
684
685 let needs_normal_echo =
686 if maybe_erase_span.is_some() { echo_bytes.is_empty() } else { true };
687
688 if needs_normal_echo {
689 let mut char_echo = vec![];
690 if self.termios.has_local_flags(ECHOCTL) {
691 if let Some(control_character_echo) =
692 generate_control_character_echo(first_byte)
693 {
694 char_echo = control_character_echo;
695 }
696 }
697 if char_echo.is_empty() {
698 char_echo = character_bytes.clone();
699 }
700 echo_bytes.extend(char_echo);
701 }
702 } else if self.termios.has_local_flags(ECHONL) && first_byte == b'\n' {
703 echo_bytes.extend_from_slice(&character_bytes);
704 }
705
706 if !echo_bytes.is_empty() {
707 signals.append(with_queue!(self.output_queue.write_bytes(self, &echo_bytes)));
708 }
709
710 if self.termios.has_local_flags(ICANON) && self.termios.is_terminating(&character_bytes)
712 {
713 queue.flush_line_buffer();
714 }
715 }
716 if !self.termios.has_local_flags(ICANON) && !queue.line_buffer.is_empty() {
718 queue.flush_line_buffer();
719 }
720
721 (return_value, signals)
722 }
723}
724
725type RawByte = u8;
728
729#[derive(Debug, Default)]
730struct Queue {
731 read_queue: VecDeque<Vec<u8>>,
734
735 line_buffer: Vec<u8>,
739
740 wait_buffers: VecDeque<Vec<RawByte>>,
743
744 total_wait_buffer_length: usize,
746
747 is_input: bool,
749}
750
751impl Queue {
752 fn output_queue() -> Option<Self> {
753 Some(Queue { is_input: false, ..Default::default() })
754 }
755
756 fn input_queue() -> Option<Self> {
757 Some(Queue { is_input: true, ..Default::default() })
758 }
759
760 fn write_readiness(&self) -> FdEvents {
762 if self.total_wait_buffer_length < WAIT_BUFFER_MAX_BYTES {
763 FdEvents::POLLOUT
764 } else {
765 FdEvents::empty()
766 }
767 }
768
769 fn read_readiness(&self) -> FdEvents {
771 if !self.read_queue.is_empty() { FdEvents::POLLIN } else { FdEvents::empty() }
773 }
774
775 fn readable_size(&self) -> usize {
777 self.read_queue.iter().map(|v| v.len()).sum()
780 }
781
782 fn read(
784 &mut self,
785 terminal: &mut LineDiscipline,
786 data: &mut dyn OutputBuffer,
787 ) -> Result<usize, Errno> {
788 if self.read_queue.is_empty() {
789 return error!(EAGAIN);
790 }
791
792 let mut total_written = 0;
793 while let Some(mut packet) = self.read_queue.pop_front() {
794 if packet.is_empty() {
795 if total_written > 0 {
796 self.read_queue.push_front(packet);
799 }
800 break;
801 }
802
803 match data.write(&packet) {
804 Ok(written) => {
805 total_written += written;
806 if written < packet.len() {
807 let remaining = packet.split_off(written);
809 self.read_queue.push_front(remaining);
810 break;
812 }
813
814 if self.is_input && terminal.termios.has_local_flags(ICANON) {
816 break;
817 }
818 }
819 Err(e) => {
820 self.read_queue.push_front(packet);
822 if total_written > 0 {
823 return Ok(total_written);
825 }
826 return Err(e);
827 }
828 }
829 }
830
831 let signals = self.drain_waiting_buffer(terminal);
832 assert!(signals.signals().is_empty());
833 Ok(total_written)
834 }
835
836 fn write(
838 &mut self,
839 terminal: &mut LineDiscipline,
840 data: &mut dyn InputBuffer,
841 ) -> Result<(usize, PendingSignals), Errno> {
842 let room = WAIT_BUFFER_MAX_BYTES - self.total_wait_buffer_length;
843 let data_length = data.available();
844 if room == 0 && data_length > 0 {
845 return error!(EAGAIN);
846 }
847 let buffer = data.read_to_vec_exact(std::cmp::min(room, data_length))?;
848 let read_from_userspace = buffer.len();
849 let signals = self.push_to_waiting_buffer(terminal, buffer);
850 Ok((read_from_userspace, signals))
851 }
852
853 fn write_bytes(&mut self, terminal: &mut LineDiscipline, buffer: &[RawByte]) -> PendingSignals {
855 self.push_to_waiting_buffer(terminal, buffer.to_vec())
856 }
857
858 fn push_to_waiting_buffer(
860 &mut self,
861 terminal: &mut LineDiscipline,
862 buffer: Vec<RawByte>,
863 ) -> PendingSignals {
864 self.total_wait_buffer_length += buffer.len();
865 self.wait_buffers.push_back(buffer);
866 self.drain_waiting_buffer(terminal)
867 }
868
869 fn drain_waiting_buffer(&mut self, terminal: &mut LineDiscipline) -> PendingSignals {
871 let mut signals_to_return = PendingSignals::new();
872 while let Some(wait_buffer) = self.wait_buffers.pop_front() {
873 self.total_wait_buffer_length -= wait_buffer.len();
874 let (count, signals) = terminal.transform(self.is_input, self, &wait_buffer);
875 signals_to_return.append(signals);
876 if count != wait_buffer.len() {
877 let remaining = wait_buffer[count..].to_vec();
878 self.total_wait_buffer_length += remaining.len();
879 self.wait_buffers.push_front(remaining);
880 break;
881 }
882 }
883 signals_to_return
884 }
885
886 fn flush_line_buffer(&mut self) {
888 self.read_queue.push_back(std::mem::take(&mut self.line_buffer));
889 }
890
891 fn flush(&mut self) {
893 self.read_queue.clear();
894 self.line_buffer.clear();
895 self.wait_buffers.clear();
896 self.total_wait_buffer_length = 0;
897 }
898
899 fn on_canon_disabled(&mut self, terminal: &mut LineDiscipline) -> PendingSignals {
901 let signals = self.drain_waiting_buffer(terminal);
902 if !self.line_buffer.is_empty() {
903 self.flush_line_buffer();
904 }
905 signals
906 }
907}
908
909fn get_ascii(c: char) -> u8 {
913 let mut dest: [u8; 1] = [0];
914 c.encode_utf8(&mut dest);
915 dest[0]
916}
917
918fn get_control_character(c: char) -> cc_t {
920 get_ascii(c) - get_ascii('A') + 1
921}
922
923fn get_default_control_characters() -> [cc_t; 19usize] {
925 [
926 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, ]
946}
947
948const DEFAULT_SPEED: u32 = 38400;
949
950pub fn get_default_termios() -> uapi::termios2 {
952 uapi::termios2 {
953 c_iflag: uapi::ICRNL | uapi::IXON,
954 c_oflag: uapi::OPOST | uapi::ONLCR,
955 c_cflag: uapi::B38400 | uapi::CS8 | uapi::CREAD,
956 c_lflag: uapi::ISIG
957 | uapi::ICANON
958 | uapi::ECHO
959 | uapi::ECHOE
960 | uapi::ECHOK
961 | uapi::ECHOCTL
962 | uapi::ECHOKE
963 | uapi::IEXTEN,
964 c_line: 0,
965 c_cc: get_default_control_characters(),
966 c_ispeed: DEFAULT_SPEED,
967 c_ospeed: DEFAULT_SPEED,
968 }
969}
970
971trait TermIOS {
973 fn has_input_flags(&self, flags: tcflag_t) -> bool;
974 fn has_output_flags(&self, flags: tcflag_t) -> bool;
975 fn has_local_flags(&self, flags: tcflag_t) -> bool;
976 fn is_eof(&self, c: RawByte) -> bool;
977 fn is_erase(&self, c: RawByte) -> bool;
978 fn is_werase(&self, c: RawByte) -> bool;
979 fn is_kill(&self, c: RawByte) -> bool;
980 fn is_terminating(&self, character_bytes: &[RawByte]) -> bool;
981 fn signal(&self, c: RawByte) -> Option<Signal>;
982}
983
984impl TermIOS for uapi::termios2 {
985 fn has_input_flags(&self, flags: tcflag_t) -> bool {
986 self.c_iflag & flags == flags
987 }
988 fn has_output_flags(&self, flags: tcflag_t) -> bool {
989 self.c_oflag & flags == flags
990 }
991 fn has_local_flags(&self, flags: tcflag_t) -> bool {
992 self.c_lflag & flags == flags
993 }
994 fn is_eof(&self, c: RawByte) -> bool {
995 c == self.c_cc[VEOF as usize] && self.c_cc[VEOF as usize] != DISABLED_CHAR
996 }
997 fn is_erase(&self, c: RawByte) -> bool {
998 c == self.c_cc[VERASE as usize] && self.c_cc[VERASE as usize] != DISABLED_CHAR
999 }
1000 fn is_werase(&self, c: RawByte) -> bool {
1001 c == self.c_cc[VWERASE as usize]
1002 && self.c_cc[VWERASE as usize] != DISABLED_CHAR
1003 && self.has_local_flags(IEXTEN)
1004 }
1005 fn is_kill(&self, c: RawByte) -> bool {
1006 c == self.c_cc[VKILL as usize] && self.c_cc[VKILL as usize] != DISABLED_CHAR
1007 }
1008 fn is_terminating(&self, character_bytes: &[RawByte]) -> bool {
1009 if character_bytes.len() != 1 {
1011 return false;
1012 }
1013 let c = character_bytes[0];
1014
1015 if self.is_eof(c) {
1017 return true;
1018 }
1019
1020 if c == DISABLED_CHAR {
1021 return false;
1022 }
1023 if c == b'\n' || c == self.c_cc[VEOL as usize] {
1024 return true;
1025 }
1026 if c == self.c_cc[VEOL2 as usize] {
1027 return self.has_local_flags(IEXTEN);
1028 }
1029 false
1030 }
1031 fn signal(&self, c: RawByte) -> Option<Signal> {
1032 if c == DISABLED_CHAR {
1033 return None;
1034 }
1035 if c == self.c_cc[VINTR as usize] {
1036 return Some(SIGINT);
1037 }
1038 if c == self.c_cc[VQUIT as usize] {
1039 return Some(SIGQUIT);
1040 }
1041 if c == self.c_cc[VSUSP as usize] {
1042 return Some(SIGSTOP);
1043 }
1044 None
1045 }
1046}
1047
1048fn compute_next_character_size(buffer: &[RawByte], termios: &uapi::termios2) -> usize {
1049 if !termios.has_input_flags(IUTF8) {
1050 return 1;
1051 }
1052
1053 #[derive(Default)]
1054 struct Receiver {
1055 done: Option<bool>,
1056 }
1057
1058 impl utf8parse::Receiver for Receiver {
1059 fn codepoint(&mut self, _c: char) {
1060 self.done = Some(true);
1061 }
1062 fn invalid_sequence(&mut self) {
1063 self.done = Some(false);
1064 }
1065 }
1066
1067 let mut byte_count = 0;
1068 let mut receiver = Receiver::default();
1069 let mut parser = utf8parse::Parser::new();
1070 while receiver.done.is_none() && byte_count < buffer.len() {
1071 parser.advance(&mut receiver, buffer[byte_count]);
1072 byte_count += 1;
1073 }
1074 if receiver.done == Some(true) { byte_count } else { 1 }
1075}
1076
1077fn is_ascii(c: RawByte) -> bool {
1078 c & 0x80 == 0
1079}
1080
1081fn is_utf8_start(c: RawByte) -> bool {
1082 c & 0xC0 == 0xC0
1083}
1084
1085fn generate_erase_echo(erase_span: &BufferSpan) -> Vec<RawByte> {
1086 let erase_echo = [BACKSPACE_CHAR, b' ', BACKSPACE_CHAR];
1087 erase_echo.iter().cycle().take(erase_echo.len() * erase_span.characters).map(|c| *c).collect()
1088}
1089
1090fn generate_control_character_echo(c: RawByte) -> Option<Vec<RawByte>> {
1091 if matches!(c, 0..=0x8 | 0xB..=0xC | 0xE..=0x1F) {
1092 Some(vec![b'^', c + CONTROL_OFFSET])
1093 } else {
1094 None
1095 }
1096}
1097
1098#[derive(Default, Debug, Clone, Copy)]
1099struct BufferSpan {
1100 bytes: usize,
1101 characters: usize,
1102}
1103
1104impl std::ops::AddAssign<Self> for BufferSpan {
1105 fn add_assign(&mut self, rhs: Self) {
1106 self.bytes += rhs.bytes;
1107 self.characters += rhs.characters;
1108 }
1109}
1110
1111fn compute_last_character_span(buffer: &[RawByte], termios: &uapi::termios2) -> BufferSpan {
1112 if buffer.is_empty() {
1113 return BufferSpan::default();
1114 }
1115 if termios.has_input_flags(IUTF8) {
1116 let mut bytes = 0;
1117 for c in buffer.iter().rev() {
1118 bytes += 1;
1119 if is_ascii(*c) || is_utf8_start(*c) {
1120 return BufferSpan { bytes, characters: 1 };
1121 }
1122 }
1123 BufferSpan::default()
1124 } else {
1125 BufferSpan { bytes: 1, characters: 1 }
1126 }
1127}
1128
1129fn compute_last_word_span(buffer: &[RawByte], termios: &uapi::termios2) -> BufferSpan {
1130 fn is_whitespace(c: RawByte) -> bool {
1131 c == b' ' || c == b'\t'
1132 }
1133
1134 let mut in_word = false;
1135 let mut word_span = BufferSpan::default();
1136 let mut remaining = buffer.len();
1137 loop {
1138 let span = compute_last_character_span(&buffer[..remaining], termios);
1139 if span.bytes == 0 {
1140 break;
1141 }
1142 if span.bytes == 1 {
1143 let c = buffer[remaining - 1];
1144 if in_word {
1145 if is_whitespace(c) {
1146 break;
1147 }
1148 } else {
1149 if !is_whitespace(c) {
1150 in_word = true;
1151 }
1152 }
1153 }
1154 remaining -= span.bytes;
1155 word_span += span;
1156 }
1157
1158 word_span
1159}
1160
1161fn compute_last_line_span(buffer: &[RawByte], termios: &uapi::termios2) -> BufferSpan {
1162 let mut line_span = BufferSpan::default();
1163 let mut remaining = buffer.len();
1164
1165 loop {
1166 let span = compute_last_character_span(&buffer[..remaining], termios);
1167 if span.bytes == 0 {
1168 break;
1169 }
1170 if span.bytes == 1 {
1171 let c = buffer[remaining - 1];
1172 if c == b'\n' {
1173 break;
1174 }
1175 }
1176 remaining -= span.bytes;
1177 line_span += span;
1178 }
1179
1180 line_span
1181}
1182
1183#[cfg(test)]
1184mod tests {
1185 use super::*;
1186
1187 #[::fuchsia::test]
1188 fn test_ascii_conversion() {
1189 assert_eq!(get_ascii(' '), 32);
1190 }
1191
1192 #[::fuchsia::test]
1193 fn test_control_character() {
1194 assert_eq!(get_control_character('C'), 3);
1195 }
1196
1197 #[::fuchsia::test]
1198 fn test_compute_next_character_size_non_utf8() {
1199 let termios = get_default_termios();
1200 for i in 0..=255 {
1201 let array: &[u8] = &[i, 0xa9, 0];
1202 assert_eq!(compute_next_character_size(array, &termios), 1);
1203 }
1204 }
1205
1206 #[::fuchsia::test]
1207 fn test_compute_next_character_size_utf8() {
1208 let mut termios = get_default_termios();
1209 termios.c_iflag |= IUTF8;
1210 for i in 0..128 {
1211 let array: &[RawByte] = &[i, 0xa9, 0];
1212 assert_eq!(compute_next_character_size(array, &termios), 1);
1213 }
1214 let array: &[RawByte] = &[0xc2, 0xa9, 0];
1215 assert_eq!(compute_next_character_size(array, &termios), 2);
1216 let array: &[RawByte] = &[0xc2, 255, 0];
1217 assert_eq!(compute_next_character_size(array, &termios), 1);
1218 }
1219
1220 #[::fuchsia::test]
1221 fn test_signal_handling_with_disabled_chars() {
1222 let mut termios = get_default_termios();
1223 termios.c_cc[VINTR as usize] = DISABLED_CHAR;
1224 termios.c_cc[VQUIT as usize] = DISABLED_CHAR;
1225 termios.c_cc[VSUSP as usize] = DISABLED_CHAR;
1226
1227 assert_eq!(termios.signal(0), None);
1228 assert_eq!(termios.signal(3), None); assert_eq!(termios.signal(28), None); assert_eq!(termios.signal(26), None); }
1232
1233 struct TestBuffer {
1234 data: Vec<u8>,
1235 }
1236
1237 impl InputBuffer for TestBuffer {
1238 fn available(&self) -> usize {
1239 self.data.len()
1240 }
1241 fn read_to_vec_exact(&mut self, size: usize) -> Result<Vec<u8>, Errno> {
1242 if size > self.data.len() {
1243 return error!(EAGAIN);
1244 }
1245 Ok(self.data.drain(0..size).collect())
1246 }
1247 }
1248
1249 impl OutputBuffer for TestBuffer {
1250 fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
1251 self.data.extend_from_slice(data);
1252 Ok(data.len())
1253 }
1254 }
1255
1256 #[::fuchsia::test]
1257 fn test_flush() {
1258 fn make_ld() -> LineDiscipline {
1259 let mut ld = LineDiscipline::default();
1260 ld.main_open();
1261 ld.replica_open();
1262
1263 let mut termios = get_default_termios();
1264 termios.c_lflag &= !ECHO;
1265 termios.c_oflag &= !OPOST;
1266 let _ = ld.set_termios(termios);
1267
1268 let mut input = TestBuffer { data: b"ping\n".to_vec() };
1271 let (written, signals) = ld.main_write(&mut input).unwrap();
1272 assert_eq!(written, 5);
1273 assert!(signals.signals().is_empty());
1274
1275 let mut output = TestBuffer { data: b"pong\n".to_vec() };
1278 let written = ld.replica_write(&mut output).unwrap();
1279 assert_eq!(written, 5);
1280 ld
1281 }
1282
1283 let mut read_buf = TestBuffer { data: vec![] };
1284
1285 let mut ld = make_ld();
1287 ld.flush(true, uapi::TCIFLUSH).unwrap();
1288 read_buf.data.clear();
1289 assert_eq!(error!(EAGAIN), ld.main_read(&mut read_buf));
1290 assert!(read_buf.data.is_empty());
1291 read_buf.data.clear();
1292 assert!(ld.replica_read(&mut read_buf).is_ok());
1293 assert_eq!(read_buf.data, b"ping\n");
1294
1295 let mut ld = make_ld();
1297 ld.flush(false, uapi::TCIFLUSH).unwrap();
1298 read_buf.data.clear();
1299 assert!(ld.main_read(&mut read_buf).is_ok());
1300 assert_eq!(read_buf.data, b"pong\n");
1301 read_buf.data.clear();
1302 assert_eq!(error!(EAGAIN), ld.replica_read(&mut read_buf));
1303 assert!(read_buf.data.is_empty());
1304
1305 let mut ld = make_ld();
1307 ld.flush(true, uapi::TCOFLUSH).unwrap();
1308 read_buf.data.clear();
1309 assert!(ld.main_read(&mut read_buf).is_ok());
1310 assert_eq!(read_buf.data, b"pong\n");
1311 read_buf.data.clear();
1312 assert!(ld.replica_read(&mut read_buf).is_ok());
1313 assert_eq!(read_buf.data, b"ping\n");
1314
1315 let mut ld = make_ld();
1317 ld.flush(false, uapi::TCOFLUSH).unwrap();
1318 read_buf.data.clear();
1319 assert!(ld.main_read(&mut read_buf).is_ok());
1320 assert_eq!(read_buf.data, b"pong\n");
1321 read_buf.data.clear();
1322 assert!(ld.replica_read(&mut read_buf).is_ok());
1323 assert_eq!(read_buf.data, b"ping\n");
1324
1325 let mut ld = make_ld();
1327 ld.flush(true, uapi::TCIOFLUSH).unwrap();
1328 read_buf.data.clear();
1329 assert_eq!(error!(EAGAIN), ld.main_read(&mut read_buf));
1330 read_buf.data.clear();
1331 assert!(ld.replica_read(&mut read_buf).is_ok());
1332 assert_eq!(read_buf.data, b"ping\n");
1333
1334 let mut ld = make_ld();
1336 ld.flush(false, uapi::TCIOFLUSH).unwrap();
1337 read_buf.data.clear();
1338 assert!(ld.main_read(&mut read_buf).is_ok());
1339 assert_eq!(read_buf.data, b"pong\n");
1340 read_buf.data.clear();
1341 assert_eq!(error!(EAGAIN), ld.replica_read(&mut read_buf));
1342 }
1343}
1344
1345pub mod testing;