1 use core::intrinsics::likely;
2 use core::ops::BitXor;
3
4 use bitmap::{traits::BitMapOps, StaticBitmap};
5
6 use alloc::sync::{Arc, Weak};
7 use system_error::SystemError;
8
9 use crate::{
10 arch::ipc::signal::Signal,
11 driver::tty::{
12 termios::{ControlCharIndex, InputMode, LocalMode, OutputMode, Termios},
13 tty_core::{EchoOperation, TtyCore, TtyCoreData, TtyFlag, TtyIoctlCmd},
14 tty_driver::{TtyDriverFlag, TtyOperation},
15 tty_job_control::TtyJobCtrlManager,
16 },
17 filesystem::vfs::file::FileMode,
18 libs::{
19 rwlock::RwLockReadGuard,
20 spinlock::{SpinLock, SpinLockGuard},
21 },
22 mm::VirtAddr,
23 net::event_poll::EPollEventType,
24 process::ProcessManager,
25 syscall::{user_access::UserBufferWriter, Syscall},
26 };
27
28 use super::TtyLineDiscipline;
29 pub const NTTY_BUFSIZE: usize = 4096;
30 pub const ECHO_COMMIT_WATERMARK: usize = 256;
31 pub const ECHO_BLOCK: usize = 256;
32 pub const ECHO_DISCARD_WATERMARK: usize = NTTY_BUFSIZE - (ECHO_BLOCK + 32);
33
ntty_buf_mask(idx: usize) -> usize34 fn ntty_buf_mask(idx: usize) -> usize {
35 return idx & (NTTY_BUFSIZE - 1);
36 }
37
38 #[derive(Debug)]
39 pub struct NTtyLinediscipline {
40 pub data: SpinLock<NTtyData>,
41 }
42
43 impl NTtyLinediscipline {
44 #[inline]
disc_data(&self) -> SpinLockGuard<NTtyData>45 pub fn disc_data(&self) -> SpinLockGuard<NTtyData> {
46 self.data.lock_irqsave()
47 }
48
49 #[inline]
disc_data_try_lock(&self) -> Result<SpinLockGuard<NTtyData>, SystemError>50 pub fn disc_data_try_lock(&self) -> Result<SpinLockGuard<NTtyData>, SystemError> {
51 self.data.try_lock_irqsave()
52 }
53
ioctl_helper(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError>54 fn ioctl_helper(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
55 match cmd {
56 TtyIoctlCmd::TCXONC => {
57 todo!()
58 }
59 TtyIoctlCmd::TCFLSH => {
60 todo!()
61 }
62 _ => {
63 return TtyCore::tty_mode_ioctl(tty.clone(), cmd, arg);
64 }
65 }
66 }
67 }
68
69 #[derive(Debug)]
70 pub struct NTtyData {
71 /// 写者管理,tty只有一个写者,即ttydevice,所以不需要加锁
72 /// 读取缓冲区的头指针,表示下一个将要接受进buf的字符的位置
73 read_head: usize,
74 /// 提交缓冲区的头指针,用于行规程处理
75 commit_head: usize,
76 /// 规范缓冲区的头指针,用于规范模式的处理
77 canon_head: usize,
78 /// 回显缓冲区的头指针,用于存储需要回显的字符
79 echo_head: usize,
80 /// 回显过程中用于提交的头指针
81 echo_commit: usize,
82 /// 标记回显字符的起始位置
83 echo_mark: usize,
84
85 /// 读者管理
86 /// 读取字符的尾指针,即当前读取位置
87 read_tail: usize,
88 /// 行的起始位置
89 line_start: usize,
90 /// 预读字符数,用于处理控制字符
91 lookahead_count: usize,
92
93 // 更改以下六个标记时必须持有termios的锁
94 /// Line-next 标志,表示下一个输入字符应当按字面处理
95 lnext: bool,
96 /// 擦除状态的标志
97 erasing: bool,
98 /// Raw 模式的标志
99 raw: bool,
100 /// Real raw 模式的标志
101 real_raw: bool,
102 /// 规范模式的标志
103 icanon: bool,
104 /// 是否开启echo
105 echo: bool,
106 /// 标志是否正在进行推送
107 pushing: bool,
108 /// 是否没有空间可写
109 no_room: bool,
110
111 /// 光标所在列
112 cursor_column: u32,
113 /// 规范模式下光标所在列
114 canon_cursor_column: u32,
115 /// 回显缓冲区的尾指针
116 echo_tail: usize,
117
118 /// 写者与读者共享
119 read_buf: [u8; NTTY_BUFSIZE],
120 echo_buf: [u8; NTTY_BUFSIZE],
121
122 read_flags: StaticBitmap<NTTY_BUFSIZE>,
123 char_map: StaticBitmap<256>,
124
125 tty: Option<Weak<TtyCore>>,
126 }
127
128 impl NTtyData {
new() -> Self129 pub fn new() -> Self {
130 Self {
131 read_head: 0,
132 commit_head: 0,
133 canon_head: 0,
134 echo_head: 0,
135 echo_commit: 0,
136 echo_mark: 0,
137 read_tail: 0,
138 line_start: 0,
139 lookahead_count: 0,
140 lnext: false,
141 erasing: false,
142 raw: false,
143 real_raw: false,
144 icanon: false,
145 pushing: false,
146 echo: false,
147 cursor_column: 0,
148 canon_cursor_column: 0,
149 echo_tail: 0,
150 read_buf: [0; NTTY_BUFSIZE],
151 echo_buf: [0; NTTY_BUFSIZE],
152 read_flags: StaticBitmap::new(),
153 char_map: StaticBitmap::new(),
154 tty: None,
155 no_room: false,
156 }
157 }
158
159 #[inline]
read_cnt(&self) -> usize160 pub fn read_cnt(&self) -> usize {
161 self.read_head - self.read_tail
162 }
163
164 #[inline]
read_at(&self, i: usize) -> u8165 pub fn read_at(&self, i: usize) -> u8 {
166 let i = i & (NTTY_BUFSIZE - 1);
167 self.read_buf[i]
168 }
169
170 /// ### 接收数据到NTTY
receive_buf_common( &mut self, tty: Arc<TtyCore>, buf: &[u8], flags: Option<&[u8]>, mut count: usize, flow: bool, ) -> Result<usize, SystemError>171 pub fn receive_buf_common(
172 &mut self,
173 tty: Arc<TtyCore>,
174 buf: &[u8],
175 flags: Option<&[u8]>,
176 mut count: usize,
177 flow: bool,
178 ) -> Result<usize, SystemError> {
179 // 获取termios读锁
180 let termios = tty.core().termios();
181 let mut overflow;
182 let mut n;
183 let mut offset = 0;
184 let mut recved = 0;
185 loop {
186 let tail = self.read_tail;
187
188 let mut room = NTTY_BUFSIZE - (self.read_head - tail);
189 if termios.input_mode.contains(InputMode::PARMRK) {
190 room = (room + 2) / 3;
191 }
192
193 room -= 1;
194 if room == 0 || room > NTTY_BUFSIZE {
195 // 可能溢出
196 overflow = self.icanon && self.canon_head == tail;
197 if room > NTTY_BUFSIZE && overflow {
198 self.read_head -= 1;
199 }
200 self.no_room = flow && !overflow;
201 room = if overflow { !0 } else { 0 }
202 } else {
203 overflow = false;
204 }
205
206 n = count.min(room);
207 if n == 0 {
208 break;
209 }
210
211 if !overflow {
212 if flags.is_none() {
213 self.receive_buf(tty.clone(), &buf[offset..], flags, n);
214 } else {
215 self.receive_buf(
216 tty.clone(),
217 &buf[offset..],
218 Some(&flags.unwrap()[offset..]),
219 n,
220 );
221 }
222 }
223
224 offset += n;
225
226 count -= n;
227
228 recved += n;
229
230 if tty.core().flags().contains(TtyFlag::LDISC_CHANGING) {
231 break;
232 }
233 }
234
235 // TODO: throttle
236
237 Ok(recved)
238 }
239
receive_buf( &mut self, tty: Arc<TtyCore>, buf: &[u8], flags: Option<&[u8]>, count: usize, )240 pub fn receive_buf(
241 &mut self,
242 tty: Arc<TtyCore>,
243 buf: &[u8],
244 flags: Option<&[u8]>,
245 count: usize,
246 ) {
247 let termios = tty.core().termios();
248 let preops = termios.input_mode.contains(InputMode::ISTRIP)
249 || termios.input_mode.contains(InputMode::IUCLC)
250 || termios.local_mode.contains(LocalMode::IEXTEN);
251
252 let look_ahead = self.lookahead_count.min(count);
253 if self.real_raw {
254 self.receive_buf_real_raw(buf, count);
255 } else if self.raw || (termios.local_mode.contains(LocalMode::EXTPROC) && !preops) {
256 self.receive_buf_raw(buf, flags, count);
257 } else if tty.core().is_closing() && !termios.local_mode.contains(LocalMode::EXTPROC) {
258 todo!()
259 } else {
260 if look_ahead > 0 {
261 self.receive_buf_standard(tty.clone(), buf, flags, look_ahead, true);
262 }
263
264 if count > look_ahead {
265 self.receive_buf_standard(tty.clone(), buf, flags, count - look_ahead, false);
266 }
267
268 // 刷新echo
269 self.flush_echoes(tty.clone());
270
271 tty.flush_chars(tty.core());
272 }
273
274 self.lookahead_count -= look_ahead;
275
276 if self.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) {
277 return;
278 }
279
280 self.commit_head = self.read_head;
281
282 if self.read_cnt() > 0 {
283 tty.core()
284 .read_wq()
285 .wakeup_any((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDBAND).bits() as u64);
286 }
287 }
288
receive_buf_real_raw(&mut self, buf: &[u8], mut count: usize)289 fn receive_buf_real_raw(&mut self, buf: &[u8], mut count: usize) {
290 let mut head = ntty_buf_mask(self.read_head);
291 let mut n = count.min(NTTY_BUFSIZE - head);
292
293 // 假如有一部分在队列头部,则这部分是拷贝尾部部分
294 self.read_buf[head..(head + n)].copy_from_slice(&buf[0..n]);
295 self.read_head += n;
296 count -= n;
297 let offset = n;
298
299 // 假如有一部分在队列头部,则这部分是拷贝头部部分
300 head = ntty_buf_mask(self.read_head);
301 n = count.min(NTTY_BUFSIZE - head);
302 self.read_buf[head..(head + n)].copy_from_slice(&buf[offset..(offset + n)]);
303 self.read_head += n;
304 }
305
receive_buf_raw(&mut self, buf: &[u8], flags: Option<&[u8]>, mut count: usize)306 fn receive_buf_raw(&mut self, buf: &[u8], flags: Option<&[u8]>, mut count: usize) {
307 // TTY_NORMAL 目前这部分未做,所以先占位置而不做抽象
308 let mut flag = 1;
309 let mut f_offset = 0;
310 let mut c_offset = 0;
311 while count != 0 {
312 if flags.is_some() {
313 flag = flags.as_ref().unwrap()[f_offset];
314 f_offset += 1;
315 }
316
317 if likely(flag == 1) {
318 self.read_buf[self.read_head] = buf[c_offset];
319 c_offset += 1;
320 self.read_head += 1;
321 } else {
322 todo!()
323 }
324
325 count -= 1;
326 }
327 }
328
flush_echoes(&mut self, tty: Arc<TtyCore>)329 pub fn flush_echoes(&mut self, tty: Arc<TtyCore>) {
330 let termios = tty.core().termios();
331 if !termios.local_mode.contains(LocalMode::ECHO)
332 && !termios.local_mode.contains(LocalMode::ECHONL)
333 || self.echo_commit == self.echo_head
334 {
335 return;
336 }
337
338 self.echo_commit = self.echo_head;
339 drop(termios);
340 let _ = self.echoes(tty);
341 }
342
receive_buf_standard( &mut self, tty: Arc<TtyCore>, buf: &[u8], flags: Option<&[u8]>, mut count: usize, lookahead_done: bool, )343 pub fn receive_buf_standard(
344 &mut self,
345 tty: Arc<TtyCore>,
346 buf: &[u8],
347 flags: Option<&[u8]>,
348 mut count: usize,
349 lookahead_done: bool,
350 ) {
351 let termios = tty.core().termios();
352 if flags.is_some() {
353 todo!("ntty recv buf flags todo");
354 }
355
356 let mut offset = 0;
357 while count > 0 {
358 if offset >= buf.len() {
359 break;
360 }
361 let mut c = buf[offset];
362 offset += 1;
363
364 if self.lnext {
365 // 将下一个字符当做字面值处理
366 self.lnext = false;
367 if termios.input_mode.contains(InputMode::ISTRIP) {
368 c &= 0x7f;
369 }
370
371 if termios.input_mode.contains(InputMode::IUCLC)
372 && termios.local_mode.contains(LocalMode::IEXTEN)
373 {
374 c = (c as char).to_ascii_lowercase() as u8;
375 self.receive_char(c, tty.clone())
376 }
377
378 continue;
379 }
380
381 if termios.input_mode.contains(InputMode::ISTRIP) {
382 c &= 0x7f;
383 }
384
385 if termios.input_mode.contains(InputMode::IUCLC)
386 && termios.local_mode.contains(LocalMode::IEXTEN)
387 {
388 c = (c as char).to_ascii_lowercase() as u8;
389 }
390
391 if termios.local_mode.contains(LocalMode::EXTPROC) {
392 self.add_read_byte(c);
393 continue;
394 }
395
396 if self.char_map.get(c as usize).unwrap() {
397 // 特殊字符
398 self.receive_special_char(c, tty.clone(), lookahead_done)
399 } else {
400 self.receive_char(c, tty.clone());
401 }
402
403 count -= 1;
404 }
405 }
406
407 #[inline(never)]
receive_special_char(&mut self, mut c: u8, tty: Arc<TtyCore>, lookahead_done: bool)408 pub fn receive_special_char(&mut self, mut c: u8, tty: Arc<TtyCore>, lookahead_done: bool) {
409 let is_flow_ctrl = self.is_flow_ctrl_char(tty.clone(), c, lookahead_done);
410 let termios = tty.core().termios();
411
412 // 启用软件流控,并且该字符已经当做软件流控字符处理
413 if termios.input_mode.contains(InputMode::IXON) && is_flow_ctrl {
414 return;
415 }
416
417 if termios.local_mode.contains(LocalMode::ISIG) {
418 if c == termios.control_characters[ControlCharIndex::VINTR] {
419 self.recv_sig_char(tty.clone(), &termios, Signal::SIGINT, c);
420 return;
421 }
422
423 if c == termios.control_characters[ControlCharIndex::VQUIT] {
424 self.recv_sig_char(tty.clone(), &termios, Signal::SIGQUIT, c);
425 return;
426 }
427
428 if c == termios.control_characters[ControlCharIndex::VSUSP] {
429 self.recv_sig_char(tty.clone(), &termios, Signal::SIGTSTP, c);
430 return;
431 }
432 }
433
434 let flow = tty.core().flow_irqsave();
435 if flow.stopped
436 && !flow.tco_stopped
437 && termios.input_mode.contains(InputMode::IXON)
438 && termios.input_mode.contains(InputMode::IXANY)
439 {
440 tty.tty_start();
441 self.process_echoes(tty.clone());
442 }
443 drop(flow);
444
445 if c == b'\r' {
446 if termios.input_mode.contains(InputMode::IGNCR) {
447 // 忽略
448 return;
449 }
450 if termios.input_mode.contains(InputMode::ICRNL) {
451 // 映射为换行
452 c = b'\n';
453 }
454 } else if c == b'\n' && termios.input_mode.contains(InputMode::INLCR) {
455 // 映射为回车
456 c = b'\r';
457 }
458
459 if self.icanon {
460 if c == termios.control_characters[ControlCharIndex::VERASE]
461 || c == termios.control_characters[ControlCharIndex::VKILL]
462 || (c == termios.control_characters[ControlCharIndex::VWERASE]
463 && termios.local_mode.contains(LocalMode::IEXTEN))
464 {
465 self.eraser(c, &termios);
466 self.commit_echoes(tty.clone());
467 return;
468 }
469 if c == termios.control_characters[ControlCharIndex::VLNEXT]
470 && termios.local_mode.contains(LocalMode::IEXTEN)
471 {
472 self.lnext = true;
473 if termios.local_mode.contains(LocalMode::ECHO) {
474 self.finish_erasing();
475 if termios.local_mode.contains(LocalMode::ECHOCTL) {
476 self.echo_char_raw(b'^');
477 self.echo_char_raw(8);
478 self.commit_echoes(tty.clone());
479 }
480 }
481 return;
482 }
483 if c == termios.control_characters[ControlCharIndex::VREPRINT]
484 && termios.local_mode.contains(LocalMode::ECHO)
485 && termios.local_mode.contains(LocalMode::IEXTEN)
486 {
487 let mut tail = self.canon_head;
488 self.finish_erasing();
489 self.echo_char(c, &termios);
490 self.echo_char_raw(b'\n');
491 while ntty_buf_mask(tail) != ntty_buf_mask(self.read_head) {
492 self.echo_char(self.read_buf[ntty_buf_mask(tail)], &termios);
493 tail += 1;
494 }
495 self.commit_echoes(tty.clone());
496 return;
497 }
498
499 if c == b'\n' {
500 if termios.local_mode.contains(LocalMode::ECHO)
501 || termios.local_mode.contains(LocalMode::ECHONL)
502 {
503 self.echo_char_raw(b'\n');
504 self.commit_echoes(tty.clone());
505 }
506
507 self.read_flags.set(ntty_buf_mask(self.read_head), true);
508 self.read_buf[ntty_buf_mask(self.read_head)] = c;
509 self.read_head += 1;
510 self.canon_head = self.read_head;
511 tty.core().read_wq().wakeup_any(
512 (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64,
513 );
514 return;
515 }
516
517 if c == termios.control_characters[ControlCharIndex::VEOF] {
518 c = ControlCharIndex::DISABLE_CHAR;
519
520 self.read_flags.set(ntty_buf_mask(self.read_head), true);
521 self.read_buf[ntty_buf_mask(self.read_head)] = c;
522 self.read_head += 1;
523 self.canon_head = self.read_head;
524 tty.core().read_wq().wakeup_any(
525 (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64,
526 );
527 return;
528 }
529
530 if c == termios.control_characters[ControlCharIndex::VEOL]
531 || (c == termios.control_characters[ControlCharIndex::VEOL2]
532 && termios.local_mode.contains(LocalMode::IEXTEN))
533 {
534 if termios.local_mode.contains(LocalMode::ECHO) {
535 if self.canon_head == self.read_head {
536 self.add_echo_byte(EchoOperation::Start.to_u8());
537 self.add_echo_byte(EchoOperation::SetCanonCol.to_u8());
538 }
539 self.echo_char(c, &termios);
540 self.commit_echoes(tty.clone());
541 }
542
543 if c == 0o377 && termios.input_mode.contains(InputMode::PARMRK) {
544 self.read_buf[ntty_buf_mask(self.read_head)] = c;
545 self.read_head += 1;
546 }
547
548 self.read_flags.set(ntty_buf_mask(self.read_head), true);
549 self.read_buf[ntty_buf_mask(self.read_head)] = c;
550 self.read_head += 1;
551 self.canon_head = self.read_head;
552 tty.core().read_wq().wakeup_any(
553 (EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64,
554 );
555 return;
556 }
557 }
558
559 if termios.local_mode.contains(LocalMode::ECHO) {
560 self.finish_erasing();
561 if c == b'\n' {
562 self.echo_char_raw(b'\n');
563 } else {
564 if self.canon_head == self.read_head {
565 self.add_echo_byte(EchoOperation::Start.to_u8());
566 self.add_echo_byte(EchoOperation::SetCanonCol.to_u8());
567 }
568 self.echo_char(c, &termios);
569 }
570
571 self.commit_echoes(tty.clone());
572 }
573
574 if c == 0o377 && termios.input_mode.contains(InputMode::PARMRK) {
575 self.read_buf[ntty_buf_mask(self.read_head)] = c;
576 self.read_head += 1;
577 }
578
579 self.read_buf[ntty_buf_mask(self.read_head)] = c;
580 self.read_head += 1;
581 }
582
583 /// ## ntty默认eraser function
584 #[inline(never)]
eraser(&mut self, mut c: u8, termios: &RwLockReadGuard<Termios>)585 fn eraser(&mut self, mut c: u8, termios: &RwLockReadGuard<Termios>) {
586 if self.read_head == self.canon_head {
587 return;
588 }
589
590 let erase = c == termios.control_characters[ControlCharIndex::VERASE];
591 let werase = c == termios.control_characters[ControlCharIndex::VWERASE];
592 let kill = !erase && !werase;
593
594 if kill {
595 if !termios.local_mode.contains(LocalMode::ECHO) {
596 self.read_head = self.canon_head;
597 return;
598 }
599 if !termios.local_mode.contains(LocalMode::ECHOK)
600 || !termios.local_mode.contains(LocalMode::ECHOKE)
601 || !termios.local_mode.contains(LocalMode::ECHOE)
602 {
603 self.read_head = self.canon_head;
604 if self.erasing {
605 self.echo_char_raw(c);
606 self.erasing = false;
607 }
608 self.echo_char(c, termios);
609
610 if termios.local_mode.contains(LocalMode::ECHOK) {
611 // 添加新行
612 self.echo_char_raw(b'\n');
613 }
614 return;
615 }
616 }
617
618 let mut head;
619 let mut cnt;
620 while ntty_buf_mask(self.read_head) != ntty_buf_mask(self.canon_head) {
621 head = self.read_head;
622
623 loop {
624 // 消除多字节字符
625 head -= 1;
626 c = self.read_buf[ntty_buf_mask(head)];
627
628 if !(Self::is_continuation(c, termios)
629 && ntty_buf_mask(head) != ntty_buf_mask(self.canon_head))
630 {
631 break;
632 }
633 }
634
635 if Self::is_continuation(c, termios) {
636 break;
637 }
638
639 if werase {
640 todo!()
641 }
642
643 cnt = self.read_head - head;
644 self.read_head = head;
645 if termios.local_mode.contains(LocalMode::ECHO) {
646 if termios.local_mode.contains(LocalMode::ECHOPRT) {
647 if !self.erasing {
648 self.echo_char_raw(b'\\');
649 self.erasing = true;
650 }
651 self.echo_char(c, termios);
652 cnt -= 1;
653 while cnt > 0 {
654 cnt -= 1;
655 head += 1;
656 self.echo_char_raw(self.read_buf[ntty_buf_mask(head)]);
657 self.add_echo_byte(EchoOperation::Start.to_u8());
658 self.add_echo_byte(EchoOperation::MoveBackCol.to_u8());
659 }
660 } else if erase && !termios.local_mode.contains(LocalMode::ECHOE) {
661 self.echo_char(
662 termios.control_characters[ControlCharIndex::VERASE],
663 termios,
664 );
665 } else if c == b'\t' {
666 let mut num_chars = 0;
667 let mut after_tab = false;
668 let mut tail = self.read_head;
669
670 while ntty_buf_mask(tail) != ntty_buf_mask(self.canon_head) {
671 tail -= 1;
672 c = self.read_buf[ntty_buf_mask(tail)];
673 if c == b'\t' {
674 after_tab = true;
675 break;
676 } else if (c as char).is_control() {
677 if termios.local_mode.contains(LocalMode::ECHOCTL) {
678 num_chars += 2;
679 }
680 } else if !Self::is_continuation(c, termios) {
681 num_chars += 1;
682 }
683 }
684
685 self.echo_erase_tab(num_chars, after_tab);
686 } else {
687 if (c as char).is_control() && termios.local_mode.contains(LocalMode::ECHOCTL) {
688 // 8 => '\b'
689 self.echo_char_raw(8);
690 self.echo_char_raw(b' ');
691 self.echo_char_raw(8);
692 }
693
694 if !(c as char).is_control() || termios.local_mode.contains(LocalMode::ECHOCTL)
695 {
696 // 8 => '\b'
697 self.echo_char_raw(8);
698 self.echo_char_raw(b' ');
699 self.echo_char_raw(8);
700 }
701 }
702 }
703
704 if erase {
705 break;
706 }
707 }
708
709 if self.read_head == self.canon_head && termios.local_mode.contains(LocalMode::ECHO) {
710 self.finish_erasing();
711 }
712 }
713
finish_erasing(&mut self)714 fn finish_erasing(&mut self) {
715 if self.erasing {
716 self.echo_char_raw(b'/');
717 self.erasing = false;
718 }
719 }
720
echo_erase_tab(&mut self, mut num: u8, after_tab: bool)721 fn echo_erase_tab(&mut self, mut num: u8, after_tab: bool) {
722 self.add_echo_byte(EchoOperation::Start.to_u8());
723 self.add_echo_byte(EchoOperation::EraseTab.to_u8());
724
725 num &= 7;
726
727 if after_tab {
728 num |= 0x80;
729 }
730
731 self.add_echo_byte(num);
732 }
733
734 /// ## 多字节字符检测
735 /// 检测是否为多字节字符的后续字节
is_continuation(c: u8, termios: &RwLockReadGuard<Termios>) -> bool736 fn is_continuation(c: u8, termios: &RwLockReadGuard<Termios>) -> bool {
737 return termios.input_mode.contains(InputMode::IUTF8) && (c & 0xc0) == 0x80;
738 }
739
740 /// ## 该字符是否已经当做流控字符处理
is_flow_ctrl_char(&mut self, tty: Arc<TtyCore>, c: u8, lookahead_done: bool) -> bool741 pub fn is_flow_ctrl_char(&mut self, tty: Arc<TtyCore>, c: u8, lookahead_done: bool) -> bool {
742 let termios = tty.core().termios();
743
744 if !(termios.control_characters[ControlCharIndex::VSTART] == c
745 || termios.control_characters[ControlCharIndex::VSTOP] == c)
746 {
747 return false;
748 }
749
750 if lookahead_done {
751 return true;
752 }
753
754 if termios.control_characters[ControlCharIndex::VSTART] == c {
755 tty.tty_start();
756 self.process_echoes(tty.clone());
757 return true;
758 } else {
759 tty.tty_stop();
760 return true;
761 }
762 }
763
764 /// ## 接收到信号字符时的处理
recv_sig_char( &mut self, tty: Arc<TtyCore>, termios: &RwLockReadGuard<Termios>, signal: Signal, c: u8, )765 fn recv_sig_char(
766 &mut self,
767 tty: Arc<TtyCore>,
768 termios: &RwLockReadGuard<Termios>,
769 signal: Signal,
770 c: u8,
771 ) {
772 self.input_signal(tty.clone(), termios, signal);
773 if termios.input_mode.contains(InputMode::IXON) {
774 tty.tty_start();
775 }
776
777 if termios.local_mode.contains(LocalMode::ECHO) {
778 self.echo_char(c, termios);
779 self.commit_echoes(tty);
780 } else {
781 self.process_echoes(tty);
782 }
783 }
784
785 /// ## 处理输入信号
input_signal( &mut self, tty: Arc<TtyCore>, termios: &RwLockReadGuard<Termios>, signal: Signal, )786 pub fn input_signal(
787 &mut self,
788 tty: Arc<TtyCore>,
789 termios: &RwLockReadGuard<Termios>,
790 signal: Signal,
791 ) {
792 // 先处理信号
793 let mut ctrl_info = tty.core().contorl_info_irqsave();
794 let pg = ctrl_info.pgid;
795 if pg.is_some() {
796 let _ = Syscall::kill(pg.unwrap(), signal as i32);
797 }
798
799 ctrl_info.pgid = None;
800 ctrl_info.session = None;
801
802 if !termios.local_mode.contains(LocalMode::NOFLSH) {
803 // 重置
804 self.echo_head = 0;
805 self.echo_tail = 0;
806 self.echo_mark = 0;
807 self.echo_commit = 0;
808
809 let _ = tty.flush_buffer(tty.core());
810
811 self.read_head = 0;
812 self.canon_head = 0;
813 self.read_tail = 0;
814 self.line_start = 0;
815
816 self.erasing = false;
817 self.read_flags.set_all(false);
818 self.pushing = false;
819 self.lookahead_count = 0;
820 }
821 }
822
receive_char(&mut self, c: u8, tty: Arc<TtyCore>)823 pub fn receive_char(&mut self, c: u8, tty: Arc<TtyCore>) {
824 let termios = tty.core().termios();
825
826 if termios.local_mode.contains(LocalMode::ECHO) {
827 if self.erasing {
828 self.add_echo_byte(b'/');
829 self.erasing = false;
830 }
831
832 if self.canon_head == self.read_head {
833 self.add_echo_byte(EchoOperation::Start.to_u8());
834 self.add_echo_byte(EchoOperation::SetCanonCol.to_u8());
835 }
836
837 self.echo_char(c, &termios);
838 self.commit_echoes(tty.clone());
839 }
840
841 if c == 0o377 && tty.core().termios().input_mode.contains(InputMode::PARMRK) {
842 self.add_read_byte(c);
843 }
844 self.add_read_byte(c);
845 }
846
echo_char(&mut self, c: u8, termios: &RwLockReadGuard<Termios>)847 pub fn echo_char(&mut self, c: u8, termios: &RwLockReadGuard<Termios>) {
848 if c == EchoOperation::Start.to_u8() {
849 self.add_echo_byte(EchoOperation::Start.to_u8());
850 self.add_echo_byte(EchoOperation::Start.to_u8());
851 } else {
852 if termios.local_mode.contains(LocalMode::ECHOCTL)
853 && (c as char).is_control()
854 && c != b'\t'
855 {
856 self.add_echo_byte(EchoOperation::Start.to_u8());
857 }
858 self.add_echo_byte(c);
859 }
860 }
861
echo_char_raw(&mut self, c: u8)862 pub fn echo_char_raw(&mut self, c: u8) {
863 if c == EchoOperation::Start.to_u8() {
864 self.add_echo_byte(EchoOperation::Start.to_u8());
865 self.add_echo_byte(EchoOperation::Start.to_u8());
866 } else {
867 self.add_echo_byte(c);
868 }
869 }
870
871 /// ## 提交echobuf里的数据显示
commit_echoes(&mut self, tty: Arc<TtyCore>)872 pub fn commit_echoes(&mut self, tty: Arc<TtyCore>) {
873 let head = self.echo_head;
874 self.echo_mark = head;
875 let old = self.echo_commit - self.echo_tail;
876
877 // 需要echo的字符个数
878 let nr = head - self.echo_tail;
879
880 if nr < ECHO_COMMIT_WATERMARK || nr % ECHO_BLOCK > old % ECHO_BLOCK {
881 return;
882 }
883
884 self.echo_commit = head;
885 let echoed = self.echoes(tty.clone());
886
887 if echoed.is_ok() && echoed.unwrap() > 0 {
888 tty.flush_chars(tty.core());
889 }
890 }
891
add_echo_byte(&mut self, c: u8)892 pub fn add_echo_byte(&mut self, c: u8) {
893 self.echo_buf[ntty_buf_mask(self.echo_head)] = c;
894 self.echo_head += 1;
895 }
896
add_read_byte(&mut self, c: u8)897 pub fn add_read_byte(&mut self, c: u8) {
898 self.read_buf[ntty_buf_mask(self.read_head)] = c;
899 self.read_head += 1;
900 }
901
902 /// ### 将read_buffer的部分值置0
903 ///
904 /// 只会在规范模式和禁用echo下执行
905 #[inline]
zero_buffer(&mut self, offset: usize, size: usize)906 pub fn zero_buffer(&mut self, offset: usize, size: usize) {
907 let offset = offset & (NTTY_BUFSIZE - 1);
908 if self.icanon && !self.echo {
909 let n = offset + size;
910 if n > NTTY_BUFSIZE {
911 for c in &mut self.read_buf[offset..NTTY_BUFSIZE] {
912 *c = 0
913 }
914
915 for c in &mut self.read_buf[0..(n - NTTY_BUFSIZE)] {
916 *c = 0
917 }
918 } else {
919 for c in &mut self.read_buf[offset..n] {
920 *c = 0
921 }
922 };
923 }
924 }
925
926 /// ## 从ntty中拷贝数据
927 ///
928 /// ### 参数
929 ///
930 /// ### to: 存储数据
931 /// ### tail: 读取尾
ntty_copy( &mut self, to: &mut [u8], tail: usize, n: &mut usize, ) -> Result<(), SystemError>932 pub fn ntty_copy(
933 &mut self,
934 to: &mut [u8],
935 tail: usize,
936 n: &mut usize,
937 ) -> Result<(), SystemError> {
938 if to.len() < *n {
939 *n = to.len();
940 // return Err(SystemError::EINVAL);
941 }
942 if tail > NTTY_BUFSIZE {
943 return Err(SystemError::EINVAL);
944 }
945
946 let size = NTTY_BUFSIZE - tail;
947
948 if size < *n {
949 // 有一部分数据在头部,则先拷贝后面部分,再拷贝头部
950 // TODO: tty审计?
951 to[0..size].copy_from_slice(&self.read_buf[tail..(tail + size)]);
952 to[size..(*n)].copy_from_slice(&self.read_buf[0..(*n - size)]);
953 } else {
954 to[..*n].copy_from_slice(&self.read_buf[tail..(tail + *n)])
955 }
956
957 self.zero_buffer(tail, *n);
958
959 Ok(())
960 }
961
962 /// ## 规范模式下跳过EOF
canon_skip_eof(&mut self)963 pub fn canon_skip_eof(&mut self) {
964 // 没有数据
965 if self.read_tail == self.canon_head {
966 return;
967 }
968
969 let tail = self.read_tail & (NTTY_BUFSIZE - 1);
970
971 // 查看read_flags是否读取位置为特殊字符
972 if !self.read_flags.get(tail).unwrap() {
973 return;
974 }
975
976 // 确保读取位置是'\0'字符
977 if self.read_buf[tail] != ControlCharIndex::DISABLE_CHAR {
978 return;
979 }
980
981 // 处理该字符,将read_flagsw该位清除
982 self.read_flags.set(tail, false);
983 // 读取位置+1,即跳过该字符不做处理
984 self.read_tail += 1;
985 }
986
987 /// ## 在规范模式(canonical mode)下从读缓冲中复制一行
988 ///
989 /// 一次只拷贝一行
990 ///
991 /// ## 参数
992 /// ### dst: 存放数据
993 /// ### nr: 需要拷贝的数据大小
994 ///
995 /// ## 返回值
996 /// ### true: 表示一行未结束并且还有数据可读
997 /// ### false: 一行已结束或者没有数据可读
canon_copy_from_read_buf( &mut self, dst: &mut [u8], nr: &mut usize, offset: &mut usize, ) -> Result<bool, SystemError>998 pub fn canon_copy_from_read_buf(
999 &mut self,
1000 dst: &mut [u8],
1001 nr: &mut usize,
1002 offset: &mut usize,
1003 ) -> Result<bool, SystemError> {
1004 if *nr == 0 {
1005 return Ok(false);
1006 }
1007
1008 let canon_head = self.canon_head;
1009
1010 // 取得能够读到的字符数,即canon_head - self.read_tail和nr最小值
1011 let mut n = (*nr).min(canon_head - self.read_tail);
1012
1013 // 获得读尾index
1014 let tail = self.read_tail & (NTTY_BUFSIZE - 1);
1015
1016 // 避免越界,这个size才是实际读取大小
1017 let size = if tail + n > NTTY_BUFSIZE {
1018 NTTY_BUFSIZE
1019 } else {
1020 tail + n
1021 };
1022
1023 // 找到eol的坐标
1024 let tmp = self.read_flags.next_index(tail);
1025 // 找到的话即为坐标,未找到的话即为NTTY_BUFSIZE
1026 let mut eol = if tmp.is_none() { size } else { tmp.unwrap() };
1027 if eol > size {
1028 eol = size
1029 }
1030
1031 // 是否需要绕回缓冲区头部
1032 let more = n - (size - tail);
1033
1034 // 是否找到eol
1035 let found = if eol == NTTY_BUFSIZE && more > 0 {
1036 // 需要返回头部
1037 let ret = self.read_flags.first_index();
1038 if ret.is_some() {
1039 let tmp = ret.unwrap();
1040 // 在头部范围内找到eol
1041 if tmp < more {
1042 eol = tmp;
1043 }
1044 } else {
1045 eol = more;
1046 }
1047 eol != more
1048 } else {
1049 // 不需要返回头部
1050 eol != size
1051 };
1052
1053 n = eol - tail;
1054 if n > NTTY_BUFSIZE {
1055 // 减法溢出则加上BUFSIZE即可限制在0-NTTY_BUFSIZE内
1056 n += NTTY_BUFSIZE;
1057 }
1058
1059 // 规范模式下实际扫描过的字符数,需要将eol计算在内
1060 let count = if found { n + 1 } else { n };
1061
1062 // 表示这一行未结束
1063 if !found || self.read_at(eol) != ControlCharIndex::DISABLE_CHAR {
1064 n = count;
1065 }
1066
1067 self.ntty_copy(&mut dst[*offset..], tail, &mut n)?;
1068 *nr -= n;
1069 *offset += n;
1070
1071 if found {
1072 self.read_flags.set(eol, false);
1073 }
1074
1075 self.read_tail += count;
1076
1077 if found {
1078 if !self.pushing {
1079 self.line_start = self.read_tail;
1080 } else {
1081 self.pushing = false;
1082 }
1083
1084 // todo: 审计?
1085 return Ok(false);
1086 }
1087
1088 // 这里是表示没有找到eol,根据是否还有数据可读返回
1089 Ok(self.read_tail != canon_head)
1090 }
1091
1092 /// ## 根据终端的模式和输入缓冲区中的数据量,判断是否可读字符
input_available(&self, termios: RwLockReadGuard<Termios>, poll: bool) -> bool1093 pub fn input_available(&self, termios: RwLockReadGuard<Termios>, poll: bool) -> bool {
1094 // 计算最小字符数
1095 let amt = if poll
1096 && termios.control_characters[ControlCharIndex::VTIME] as u32 == 0
1097 && termios.control_characters[ControlCharIndex::VMIN] as u32 != 0
1098 {
1099 termios.control_characters[ControlCharIndex::VMIN] as usize
1100 } else {
1101 1
1102 };
1103
1104 // 规范模式且非拓展
1105 if self.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) {
1106 return self.canon_head != self.read_tail;
1107 } else {
1108 return (self.commit_head - self.read_tail) >= amt;
1109 }
1110 }
1111
1112 /// ## 非规范模式下从read_buf读取数据
1113 ///
1114 /// ## 参数
1115 /// ### termios: tty对应的termioss读锁守卫
1116 /// ### dst: 存储读取数据
1117 /// ### nr: 读取长度
1118 ///
1119 /// ## 返回值
1120 /// ### true: 还有更多数据可读
1121 /// ### false: 无更多数据可读
copy_from_read_buf( &mut self, termios: RwLockReadGuard<Termios>, dst: &mut [u8], nr: &mut usize, offset: &mut usize, ) -> Result<bool, SystemError>1122 pub fn copy_from_read_buf(
1123 &mut self,
1124 termios: RwLockReadGuard<Termios>,
1125 dst: &mut [u8],
1126 nr: &mut usize,
1127 offset: &mut usize,
1128 ) -> Result<bool, SystemError> {
1129 let head = self.commit_head;
1130 let tail = self.read_tail & (NTTY_BUFSIZE - 1);
1131
1132 // 计算出可读的字符数
1133 let mut n = (NTTY_BUFSIZE - tail).min(head - self.read_tail);
1134 n = n.min(*nr);
1135
1136 if n > 0 {
1137 // 拷贝数据
1138 self.ntty_copy(&mut dst[*offset..], tail, &mut n)?;
1139 // todo:审计?
1140 self.read_tail += n;
1141
1142 // 是否只读取了eof
1143 let eof =
1144 n == 1 && self.read_buf[tail] == termios.control_characters[ControlCharIndex::VEOF];
1145
1146 if termios.local_mode.contains(LocalMode::EXTPROC)
1147 && self.icanon
1148 && eof
1149 && head == self.read_tail
1150 {
1151 return Ok(false);
1152 }
1153
1154 *nr -= n;
1155 *offset += n;
1156
1157 return Ok(head != self.read_tail);
1158 }
1159
1160 Ok(false)
1161 }
1162
1163 /// ## 用于处理带有 OPOST(Output Post-processing)标志的输出块的函数
1164 /// OPOST 是 POSIX 终端驱动器标志之一,用于指定在写入终端设备之前对输出数据进行一些后期处理。
process_output_block( &mut self, core: &TtyCoreData, termios: RwLockReadGuard<Termios>, buf: &[u8], nr: usize, ) -> Result<usize, SystemError>1165 pub fn process_output_block(
1166 &mut self,
1167 core: &TtyCoreData,
1168 termios: RwLockReadGuard<Termios>,
1169 buf: &[u8],
1170 nr: usize,
1171 ) -> Result<usize, SystemError> {
1172 let mut nr = nr;
1173 let tty = self.tty.clone().unwrap().upgrade().unwrap();
1174 let space = tty.write_room(tty.core());
1175
1176 // 如果读取数量大于了可用空间,则取最小的为真正的写入数量
1177 if nr > space {
1178 nr = space
1179 }
1180
1181 let mut cnt = 0;
1182 for i in 0..nr {
1183 cnt = i;
1184 let c = buf[i];
1185 if c as usize == 8 {
1186 // 表示退格
1187 if self.cursor_column > 0 {
1188 self.cursor_column -= 1;
1189 }
1190 continue;
1191 }
1192 match c as char {
1193 '\n' => {
1194 if termios.output_mode.contains(OutputMode::ONLRET) {
1195 // 将回车映射为\n,即将\n换为回车
1196 self.cursor_column = 0;
1197 }
1198 if termios.output_mode.contains(OutputMode::ONLCR) {
1199 // 输出时将\n换为\r\n
1200 break;
1201 }
1202
1203 self.canon_cursor_column = self.cursor_column;
1204 }
1205 '\r' => {
1206 if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 {
1207 // 光标已经在第0列,则不输出回车符
1208 break;
1209 }
1210
1211 if termios.output_mode.contains(OutputMode::OCRNL) {
1212 break;
1213 }
1214 self.canon_cursor_column = self.cursor_column;
1215 }
1216 '\t' => {
1217 break;
1218 }
1219 _ => {
1220 // 判断是否为控制字符
1221 if !(c as char).is_control() {
1222 if termios.output_mode.contains(OutputMode::OLCUC) {
1223 break;
1224 }
1225
1226 // 判断是否为utf8模式下的连续字符
1227 if !(termios.input_mode.contains(InputMode::IUTF8)
1228 && (c as usize) & 0xc0 == 0x80)
1229 {
1230 self.cursor_column += 1;
1231 }
1232 }
1233 }
1234 }
1235 }
1236
1237 drop(termios);
1238 return tty.write(core, buf, cnt);
1239 }
1240
1241 /// ## 处理回显
process_echoes(&mut self, tty: Arc<TtyCore>)1242 pub fn process_echoes(&mut self, tty: Arc<TtyCore>) {
1243 if self.echo_mark == self.echo_tail {
1244 return;
1245 }
1246 self.echo_commit = self.echo_mark;
1247 let echoed = self.echoes(tty.clone());
1248
1249 if echoed.is_ok() && echoed.unwrap() > 0 {
1250 let _ = tty.flush_chars(tty.core());
1251 }
1252 }
1253
1254 #[inline(never)]
echoes(&mut self, tty: Arc<TtyCore>) -> Result<usize, SystemError>1255 pub fn echoes(&mut self, tty: Arc<TtyCore>) -> Result<usize, SystemError> {
1256 let mut space = tty.write_room(tty.core());
1257 let ospace = space;
1258 let termios = tty.core().termios();
1259 let core = tty.core();
1260 let mut tail = self.echo_tail;
1261
1262 while ntty_buf_mask(self.echo_commit) != ntty_buf_mask(tail) {
1263 let c = self.echo_buf[ntty_buf_mask(tail)];
1264
1265 if EchoOperation::from_u8(c) == EchoOperation::Start {
1266 if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 1) {
1267 self.echo_tail = tail;
1268 return Ok(ospace - space);
1269 }
1270
1271 // 获取到start,之后取第一个作为op
1272 let op = EchoOperation::from_u8(self.echo_buf[ntty_buf_mask(tail + 1)]);
1273
1274 match op {
1275 EchoOperation::Start => {
1276 if space == 0 {
1277 break;
1278 }
1279
1280 if tty
1281 .put_char(tty.core(), EchoOperation::Start.to_u8())
1282 .is_err()
1283 {
1284 tty.write(core, &[EchoOperation::Start.to_u8()], 1)?;
1285 }
1286
1287 self.cursor_column += 1;
1288 space -= 1;
1289 tail += 2;
1290 }
1291 EchoOperation::MoveBackCol => {
1292 if self.cursor_column > 0 {
1293 self.cursor_column -= 1;
1294 }
1295 tail += 2;
1296 }
1297 EchoOperation::SetCanonCol => {
1298 self.canon_cursor_column = self.cursor_column;
1299 tail += 2;
1300 }
1301 EchoOperation::EraseTab => {
1302 if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 2) {
1303 self.echo_tail = tail;
1304 return Ok(ospace - space);
1305 }
1306
1307 // 要擦除的制表符所占用的列数
1308 let mut char_num = self.echo_buf[ntty_buf_mask(tail + 2)] as usize;
1309
1310 /*
1311 如果 num_chars 的最高位(0x80)未设置,
1312 表示这是从输入的起始位置而不是从先前的制表符开始计算的列数。
1313 在这种情况下,将 num_chars 与 ldata->canon_column 相加,否则,列数就是正常的制表符列数。
1314 */
1315 if char_num & 0x80 == 0 {
1316 char_num += self.canon_cursor_column as usize;
1317 }
1318
1319 // 计算要回退的列数,即制表符宽度减去实际占用的列数
1320 let mut num_bs = 8 - (char_num & 7);
1321 if num_bs > space {
1322 // 表示左边没有足够空间回退
1323 break;
1324 }
1325
1326 space -= num_bs;
1327 while num_bs != 0 {
1328 num_bs -= 1;
1329 // 8 => '\b'
1330 if tty.put_char(tty.core(), 8).is_err() {
1331 tty.write(core, &[8], 1)?;
1332 }
1333
1334 if self.cursor_column > 0 {
1335 self.cursor_column -= 1;
1336 }
1337 }
1338
1339 // 已经读取了 tail tail+1 tail+2,所以这里偏移加3
1340 tail += 3;
1341 }
1342 EchoOperation::Undefined(ch) => {
1343 match ch {
1344 8 => {
1345 if tty.put_char(tty.core(), 8).is_err() {
1346 tty.write(core, &[8], 1)?;
1347 }
1348 if tty.put_char(tty.core(), ' ' as u8).is_err() {
1349 tty.write(core, &[' ' as u8], 1)?;
1350 }
1351 self.cursor_column -= 1;
1352 space -= 1;
1353 tail += 1;
1354 }
1355 _ => {
1356 // 不是特殊字节码,则表示控制字符 例如 ^C
1357 if space < 2 {
1358 break;
1359 }
1360
1361 if tty.put_char(tty.core(), b'^').is_err() {
1362 tty.write(core, &[b'^'], 1)?;
1363 }
1364
1365 if tty.put_char(tty.core(), ch ^ 0o100).is_err() {
1366 tty.write(core, &[ch ^ 0o100], 1)?;
1367 }
1368
1369 self.cursor_column += 2;
1370 space -= 2;
1371 tail += 2;
1372 }
1373 }
1374 }
1375 }
1376 } else {
1377 if termios.output_mode.contains(OutputMode::OPOST) {
1378 let ret = self.do_output_char(tty.clone(), c, space);
1379
1380 if ret.is_err() {
1381 break;
1382 }
1383 space -= ret.unwrap();
1384 } else {
1385 if space == 0 {
1386 break;
1387 }
1388
1389 if tty.put_char(tty.core(), c).is_err() {
1390 tty.write(core, &[c], 1)?;
1391 }
1392 space -= 1;
1393 }
1394 tail += 1;
1395 }
1396 }
1397
1398 // 如果回显缓冲区接近满(在下一次提交之前可能会发生回显溢出的情况),则丢弃足够的尾部数据以防止随后的溢出。
1399 while self.echo_commit > tail && self.echo_commit - tail >= ECHO_DISCARD_WATERMARK {
1400 if self.echo_buf[ntty_buf_mask(tail)] == EchoOperation::Start.to_u8() {
1401 if self.echo_buf[ntty_buf_mask(tail + 1)] == EchoOperation::EraseTab.to_u8() {
1402 tail += 3;
1403 } else {
1404 tail += 2;
1405 }
1406 } else {
1407 tail += 1;
1408 }
1409 }
1410
1411 self.echo_tail = tail;
1412 return Ok(ospace - space);
1413 }
1414
1415 /// ## 处理输出字符(带有 OPOST 处理)
process_output(&mut self, tty: Arc<TtyCore>, c: u8) -> bool1416 pub fn process_output(&mut self, tty: Arc<TtyCore>, c: u8) -> bool {
1417 let space = tty.write_room(tty.core());
1418
1419 if self.do_output_char(tty, c, space).is_err() {
1420 return false;
1421 }
1422
1423 true
1424 }
1425
1426 // ## 设置带有 OPOST 处理的tty输出一个字符
do_output_char( &mut self, tty: Arc<TtyCore>, c: u8, space: usize, ) -> Result<usize, SystemError>1427 pub fn do_output_char(
1428 &mut self,
1429 tty: Arc<TtyCore>,
1430 c: u8,
1431 space: usize,
1432 ) -> Result<usize, SystemError> {
1433 if space == 0 {
1434 return Err(SystemError::ENOBUFS);
1435 }
1436
1437 let termios = tty.core().termios();
1438 let core = tty.core();
1439 let mut c = c;
1440 if c as usize == 8 {
1441 // 表示退格
1442 if self.cursor_column > 0 {
1443 self.cursor_column -= 1;
1444 }
1445 if tty.put_char(tty.core(), c).is_err() {
1446 tty.write(core, &[c], 1)?;
1447 }
1448 return Ok(1);
1449 }
1450 match c as char {
1451 '\n' => {
1452 if termios.output_mode.contains(OutputMode::ONLRET) {
1453 // 回车符
1454 self.cursor_column = 0;
1455 }
1456 if termios.output_mode.contains(OutputMode::ONLCR) {
1457 // 映射为“\r\n”
1458 if space < 2 {
1459 return Err(SystemError::ENOBUFS);
1460 }
1461 self.cursor_column = 0;
1462 self.canon_cursor_column = 0;
1463
1464 // 通过驱动写入
1465 tty.write(core, "\r\n".as_bytes(), 2)?;
1466 return Ok(2);
1467 }
1468
1469 self.canon_cursor_column = self.cursor_column;
1470 }
1471 '\r' => {
1472 if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 {
1473 // 光标已经在第0列,则不输出回车符
1474 return Ok(0);
1475 }
1476
1477 if termios.output_mode.contains(OutputMode::OCRNL) {
1478 // 输出的\r映射为\n
1479 c = b'\n';
1480 if termios.output_mode.contains(OutputMode::ONLRET) {
1481 // \r映射为\n,但是保留\r特性
1482 self.cursor_column = 0;
1483 self.canon_cursor_column = 0;
1484 }
1485 } else {
1486 self.cursor_column = 0;
1487 self.canon_cursor_column = 0;
1488 }
1489 }
1490 '\t' => {
1491 // 计算输出一个\t需要的空间
1492 let spaces = 8 - (self.cursor_column & 7) as usize;
1493 if termios.output_mode.contains(OutputMode::TABDLY) {
1494 if OutputMode::TABDLY.bits() == OutputMode::XTABS.bits() {
1495 // 配置的tab选项是真正输出空格到驱动
1496 if space < spaces {
1497 // 空间不够
1498 return Err(SystemError::ENOBUFS);
1499 }
1500 self.cursor_column += spaces as u32;
1501 // 写入sapces个空格
1502 tty.write(core, " ".as_bytes(), spaces)?;
1503 return Ok(spaces);
1504 }
1505 }
1506 self.cursor_column += spaces as u32;
1507 }
1508 _ => {
1509 // 判断是否为控制字符
1510 if !(c as char).is_control() {
1511 if termios.output_mode.contains(OutputMode::OLCUC) {
1512 c = c.to_ascii_uppercase();
1513 }
1514
1515 // 判断是否为utf8模式下的连续字符
1516 if !(termios.input_mode.contains(InputMode::IUTF8)
1517 && (c as usize) & 0xc0 == 0x80)
1518 {
1519 self.cursor_column += 1;
1520 }
1521 }
1522 }
1523 }
1524
1525 if tty.put_char(tty.core(), c).is_err() {
1526 tty.write(core, &[c], 1)?;
1527 }
1528 Ok(1)
1529 }
1530 }
1531
1532 impl TtyLineDiscipline for NTtyLinediscipline {
open(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError>1533 fn open(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
1534 // 反向绑定tty到disc
1535 self.disc_data().tty = Some(Arc::downgrade(&tty));
1536 // 特定的tty设备在这里可能需要取消端口节流
1537 return self.set_termios(tty, None);
1538 }
1539
close(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError>1540 fn close(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
1541 todo!()
1542 }
1543
1544 /// ## 重置缓冲区的基本信息
flush_buffer(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError>1545 fn flush_buffer(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
1546 let core = tty.core();
1547 let _ = core.termios();
1548 let mut ldata = self.disc_data();
1549 ldata.read_head = 0;
1550 ldata.canon_head = 0;
1551 ldata.read_tail = 0;
1552 ldata.commit_head = 0;
1553 ldata.line_start = 0;
1554 ldata.erasing = false;
1555 ldata.read_flags.set_all(false);
1556 ldata.pushing = false;
1557 ldata.lookahead_count = 0;
1558
1559 // todo: kick worker?
1560 // todo: packet mode?
1561
1562 Ok(())
1563 }
1564
1565 #[inline(never)]
read( &self, tty: Arc<TtyCore>, buf: &mut [u8], len: usize, cookie: &mut bool, _offset: usize, mode: FileMode, ) -> Result<usize, system_error::SystemError>1566 fn read(
1567 &self,
1568 tty: Arc<TtyCore>,
1569 buf: &mut [u8],
1570 len: usize,
1571 cookie: &mut bool,
1572 _offset: usize,
1573 mode: FileMode,
1574 ) -> Result<usize, system_error::SystemError> {
1575 let mut ldata;
1576 if mode.contains(FileMode::O_NONBLOCK) {
1577 let ret = self.disc_data_try_lock();
1578 if ret.is_err() {
1579 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
1580 }
1581 ldata = ret.unwrap();
1582 } else {
1583 ldata = self.disc_data();
1584 }
1585 let core = tty.core();
1586 let termios = core.termios();
1587 let mut nr = len;
1588
1589 let mut offset = 0;
1590
1591 // 表示接着读
1592 if *cookie {
1593 // 规范且非拓展模式
1594 if ldata.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) {
1595 // 跳过EOF字符
1596 if len == 0 {
1597 ldata.canon_skip_eof();
1598 } else if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? {
1599 return Ok(len - nr);
1600 }
1601 } else {
1602 if ldata.copy_from_read_buf(termios, buf, &mut nr, &mut offset)? {
1603 return Ok(len - nr);
1604 }
1605 }
1606
1607 // 没有数据可读
1608
1609 // todo: kick worker? or 关闭节流?
1610
1611 *cookie = false;
1612 return Ok(len - nr);
1613 }
1614
1615 drop(termios);
1616
1617 TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTIN)?;
1618
1619 let mut minimum: usize = 0;
1620 if !ldata.icanon {
1621 let core = tty.core();
1622 let termios = core.termios();
1623 minimum = termios.control_characters[ControlCharIndex::VMIN] as usize;
1624 if minimum == 0 {
1625 minimum = 1;
1626 }
1627 }
1628
1629 let mut ret: Result<usize, SystemError> = Ok(0);
1630 // 记录读取前 的tail
1631 let tail = ldata.read_tail;
1632 drop(ldata);
1633 while nr != 0 {
1634 // todo: 处理packet模式
1635 let mut ldata = self.disc_data();
1636
1637 let core = tty.core();
1638 if !ldata.input_available(core.termios(), false) {
1639 if core.flags().contains(TtyFlag::OTHER_CLOSED) {
1640 ret = Err(SystemError::EIO);
1641 break;
1642 }
1643
1644 if core.flags().contains(TtyFlag::HUPPED) || core.flags().contains(TtyFlag::HUPPING)
1645 {
1646 break;
1647 }
1648
1649 if mode.contains(FileMode::O_NONBLOCK)
1650 || core.flags().contains(TtyFlag::LDISC_CHANGING)
1651 {
1652 ret = Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
1653 break;
1654 }
1655
1656 if ProcessManager::current_pcb()
1657 .sig_info_irqsave()
1658 .sig_pending()
1659 .has_pending()
1660 {
1661 ret = Err(SystemError::ERESTARTSYS);
1662 break;
1663 }
1664
1665 // 休眠一段时间
1666 // 获取到termios读锁,避免termios被更改导致行为异常
1667 // let termios = core.termios_preempt_enable();
1668 // let helper = WakeUpHelper::new(ProcessManager::current_pcb());
1669 // let wakeup_helper = Timer::new(helper, timeout);
1670 // wakeup_helper.activate();
1671 // drop(termios);
1672 drop(ldata);
1673 core.read_wq()
1674 .sleep((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64);
1675 continue;
1676 }
1677
1678 if ldata.icanon && !core.termios().local_mode.contains(LocalMode::EXTPROC) {
1679 if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? {
1680 *cookie = true;
1681 offset += len - nr;
1682 return Ok(offset);
1683 }
1684 } else {
1685 // 非标准模式
1686 // todo: 处理packet模式
1687
1688 // 拷贝数据
1689 if ldata.copy_from_read_buf(core.termios(), buf, &mut nr, &mut offset)?
1690 && offset >= minimum
1691 {
1692 *cookie = true;
1693 return Ok(offset);
1694 }
1695 }
1696
1697 if offset >= minimum {
1698 break;
1699 }
1700 }
1701 let ldata = self.disc_data();
1702 if tail != ldata.read_tail {
1703 // todo: kick worker?
1704 }
1705
1706 if offset > 0 {
1707 return Ok(offset);
1708 }
1709
1710 ret
1711 }
1712
1713 #[inline(never)]
write( &self, tty: Arc<TtyCore>, buf: &[u8], len: usize, mode: FileMode, ) -> Result<usize, system_error::SystemError>1714 fn write(
1715 &self,
1716 tty: Arc<TtyCore>,
1717 buf: &[u8],
1718 len: usize,
1719 mode: FileMode,
1720 ) -> Result<usize, system_error::SystemError> {
1721 let mut nr = len;
1722 let mut ldata = self.disc_data();
1723 let pcb = ProcessManager::current_pcb();
1724 let binding = tty.clone();
1725 let core = binding.core();
1726 let termios = core.termios().clone();
1727 if termios.local_mode.contains(LocalMode::TOSTOP) {
1728 TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;
1729 }
1730
1731 ldata.process_echoes(tty.clone());
1732 // drop(ldata);
1733 let mut offset = 0;
1734 loop {
1735 if pcb.sig_info_irqsave().sig_pending().has_pending() {
1736 return Err(SystemError::ERESTARTSYS);
1737 }
1738 if core.flags().contains(TtyFlag::HUPPED) {
1739 return Err(SystemError::EIO);
1740 }
1741 if termios.output_mode.contains(OutputMode::OPOST) {
1742 while nr > 0 {
1743 // let mut ldata = self.disc_data();
1744 // 获得一次处理后的数量
1745 let ret = ldata.process_output_block(core, core.termios(), &buf[offset..], nr);
1746 let num = match ret {
1747 Ok(num) => num,
1748 Err(e) => {
1749 if e == SystemError::EAGAIN_OR_EWOULDBLOCK {
1750 break;
1751 } else {
1752 return Err(e);
1753 }
1754 }
1755 };
1756
1757 offset += num;
1758 nr -= num;
1759
1760 if nr == 0 {
1761 break;
1762 }
1763
1764 let c = buf[offset];
1765 if !ldata.process_output(tty.clone(), c) {
1766 break;
1767 }
1768 offset += 1;
1769 nr -= 1;
1770 }
1771
1772 let _ = tty.flush_chars(core);
1773 } else {
1774 while nr > 0 {
1775 let write = tty.write(core, &buf[offset..], nr)?;
1776 if write == 0 {
1777 break;
1778 }
1779 offset += write;
1780 nr -= write;
1781 }
1782 }
1783
1784 if nr == 0 {
1785 break;
1786 }
1787
1788 if mode.contains(FileMode::O_NONBLOCK) || core.flags().contains(TtyFlag::LDISC_CHANGING)
1789 {
1790 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
1791 }
1792
1793 // 到这里表明没位置可写了
1794 // 休眠一段时间
1795 // 获取到termios读锁,避免termios被更改导致行为异常
1796 core.write_wq()
1797 .sleep(EPollEventType::EPOLLOUT.bits() as u64);
1798 }
1799
1800 Ok(offset)
1801 }
1802
ioctl( &self, tty: Arc<TtyCore>, cmd: u32, arg: usize, ) -> Result<usize, system_error::SystemError>1803 fn ioctl(
1804 &self,
1805 tty: Arc<TtyCore>,
1806 cmd: u32,
1807 arg: usize,
1808 ) -> Result<usize, system_error::SystemError> {
1809 match cmd {
1810 TtyIoctlCmd::TIOCOUTQ => {
1811 let mut user_writer = UserBufferWriter::new(
1812 VirtAddr::new(arg).as_ptr::<i32>(),
1813 core::mem::size_of::<i32>(),
1814 true,
1815 )?;
1816
1817 let count = tty.chars_in_buffer();
1818 user_writer.copy_one_to_user::<i32>(&(count as i32), 0)?;
1819 return Ok(0);
1820 }
1821 TtyIoctlCmd::FIONREAD => {
1822 let ldata = self.disc_data();
1823 let termios = tty.core().termios();
1824 let retval;
1825 if termios.local_mode.contains(LocalMode::ICANON)
1826 && !termios.local_mode.contains(LocalMode::EXTPROC)
1827 {
1828 if ldata.canon_head == ldata.read_tail {
1829 retval = 0;
1830 } else {
1831 let head = ldata.canon_head;
1832 let mut tail = ldata.read_tail;
1833 let mut nr = head - tail;
1834
1835 while ntty_buf_mask(head) != ntty_buf_mask(tail) {
1836 if ldata.read_flags.get(ntty_buf_mask(tail)).unwrap()
1837 && ldata.read_buf[ntty_buf_mask(tail)]
1838 == ControlCharIndex::DISABLE_CHAR
1839 {
1840 nr -= 1;
1841 }
1842 tail += 1;
1843 }
1844
1845 retval = nr;
1846 }
1847 } else {
1848 retval = ldata.read_cnt();
1849 }
1850
1851 let mut user_writer = UserBufferWriter::new(
1852 VirtAddr::new(arg).as_ptr::<i32>(),
1853 core::mem::size_of::<i32>(),
1854 true,
1855 )?;
1856
1857 user_writer.copy_one_to_user::<i32>(&(retval as i32), 0)?;
1858 return Ok(0);
1859 }
1860 _ => {
1861 return self.ioctl_helper(tty, cmd, arg);
1862 }
1863 }
1864 }
1865
1866 #[inline(never)]
set_termios( &self, tty: Arc<TtyCore>, old: Option<crate::driver::tty::termios::Termios>, ) -> Result<(), system_error::SystemError>1867 fn set_termios(
1868 &self,
1869 tty: Arc<TtyCore>,
1870 old: Option<crate::driver::tty::termios::Termios>,
1871 ) -> Result<(), system_error::SystemError> {
1872 let core = tty.core();
1873 let termios = core.termios();
1874 let mut ldata = self.disc_data();
1875 let contorl_chars = termios.control_characters;
1876
1877 // 第一次设置或者规范模式 (ICANON) 或者扩展处理 (EXTPROC) 标志发生变化
1878 let mut spec_mode_changed = false;
1879 if old.is_some() {
1880 let local_mode = old.clone().unwrap().local_mode.bitxor(termios.local_mode);
1881 spec_mode_changed =
1882 local_mode.contains(LocalMode::ICANON) || local_mode.contains(LocalMode::EXTPROC);
1883 }
1884 if old.is_none() || spec_mode_changed {
1885 // 重置read_flags
1886 ldata.read_flags.set_all(false);
1887
1888 ldata.line_start = ldata.read_tail;
1889
1890 // 不是规范模式或者有可读数据
1891 if !termios.local_mode.contains(LocalMode::ICANON) || ldata.read_cnt() != 0 {
1892 ldata.canon_head = ldata.read_tail;
1893 ldata.pushing = false;
1894 } else {
1895 let read_head = ldata.read_head;
1896 ldata
1897 .read_flags
1898 .set((read_head - 1) & (NTTY_BUFSIZE - 1), true);
1899 ldata.canon_head = ldata.read_head;
1900 ldata.pushing = true;
1901 }
1902 ldata.commit_head = ldata.read_head;
1903 ldata.erasing = false;
1904 ldata.lnext = false;
1905 }
1906
1907 // 设置模式
1908 ldata.icanon = termios.local_mode.contains(LocalMode::ICANON);
1909
1910 // 设置回显
1911 if termios.local_mode.contains(LocalMode::ECHO) {
1912 ldata.echo = true;
1913 }
1914
1915 if termios.input_mode.contains(InputMode::ISTRIP)
1916 || termios.input_mode.contains(InputMode::IUCLC)
1917 || termios.input_mode.contains(InputMode::IGNCR)
1918 || termios.input_mode.contains(InputMode::IXON)
1919 || termios.local_mode.contains(LocalMode::ISIG)
1920 || termios.local_mode.contains(LocalMode::ECHO)
1921 || termios.input_mode.contains(InputMode::PARMRK)
1922 {
1923 // 非原模式
1924
1925 ldata.char_map.set_all(false);
1926
1927 // 忽略回车符或者将回车映射为换行符
1928 if termios.input_mode.contains(InputMode::IGNCR)
1929 || termios.input_mode.contains(InputMode::ICRNL)
1930 {
1931 ldata.char_map.set('\r' as usize, true);
1932 }
1933
1934 // 将换行映射为回车
1935 if termios.input_mode.contains(InputMode::INLCR) {
1936 ldata.char_map.set('\n' as usize, true);
1937 }
1938
1939 // 规范模式
1940 if termios.local_mode.contains(LocalMode::ICANON) {
1941 ldata
1942 .char_map
1943 .set(contorl_chars[ControlCharIndex::VERASE] as usize, true);
1944 ldata
1945 .char_map
1946 .set(contorl_chars[ControlCharIndex::VKILL] as usize, true);
1947 ldata
1948 .char_map
1949 .set(contorl_chars[ControlCharIndex::VEOF] as usize, true);
1950 ldata.char_map.set('\n' as usize, true);
1951 ldata
1952 .char_map
1953 .set(contorl_chars[ControlCharIndex::VEOL] as usize, true);
1954
1955 if termios.local_mode.contains(LocalMode::IEXTEN) {
1956 ldata
1957 .char_map
1958 .set(contorl_chars[ControlCharIndex::VWERASE] as usize, true);
1959 ldata
1960 .char_map
1961 .set(contorl_chars[ControlCharIndex::VLNEXT] as usize, true);
1962 ldata
1963 .char_map
1964 .set(contorl_chars[ControlCharIndex::VEOL2] as usize, true);
1965 if termios.local_mode.contains(LocalMode::ECHO) {
1966 ldata
1967 .char_map
1968 .set(contorl_chars[ControlCharIndex::VREPRINT] as usize, true);
1969 }
1970 }
1971 }
1972
1973 // 软件流控制
1974 if termios.input_mode.contains(InputMode::IXON) {
1975 ldata
1976 .char_map
1977 .set(contorl_chars[ControlCharIndex::VSTART] as usize, true);
1978 ldata
1979 .char_map
1980 .set(contorl_chars[ControlCharIndex::VSTOP] as usize, true);
1981 }
1982
1983 if termios.local_mode.contains(LocalMode::ISIG) {
1984 ldata
1985 .char_map
1986 .set(contorl_chars[ControlCharIndex::VINTR] as usize, true);
1987 ldata
1988 .char_map
1989 .set(contorl_chars[ControlCharIndex::VQUIT] as usize, true);
1990 ldata
1991 .char_map
1992 .set(contorl_chars[ControlCharIndex::VSUSP] as usize, true);
1993 }
1994
1995 ldata
1996 .char_map
1997 .set(ControlCharIndex::DISABLE_CHAR as usize, true);
1998 ldata.raw = false;
1999 ldata.real_raw = false;
2000 } else {
2001 // 原模式或real_raw
2002 ldata.raw = true;
2003
2004 if termios.input_mode.contains(InputMode::IGNBRK)
2005 || (!termios.input_mode.contains(InputMode::BRKINT)
2006 && !termios.input_mode.contains(InputMode::PARMRK))
2007 && (termios.input_mode.contains(InputMode::IGNPAR)
2008 || !termios.input_mode.contains(InputMode::INPCK))
2009 && (core
2010 .driver()
2011 .flags()
2012 .contains(TtyDriverFlag::TTY_DRIVER_REAL_RAW))
2013 {
2014 ldata.real_raw = true;
2015 } else {
2016 ldata.real_raw = false;
2017 }
2018 }
2019
2020 // if !termios.input_mode.contains(InputMode::IXON)
2021 // && old.is_some()
2022 // && old.unwrap().input_mode.contains(InputMode::IXON) && !
2023 // {}
2024
2025 core.read_wq().wakeup_all();
2026 core.write_wq().wakeup_all();
2027 Ok(())
2028 }
2029
poll(&self, tty: Arc<TtyCore>) -> Result<usize, system_error::SystemError>2030 fn poll(&self, tty: Arc<TtyCore>) -> Result<usize, system_error::SystemError> {
2031 let core = tty.core();
2032 let ldata = self.disc_data();
2033
2034 let mut event = EPollEventType::empty();
2035 if ldata.input_available(core.termios(), true) {
2036 event.insert(EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM)
2037 }
2038
2039 if core.contorl_info_irqsave().packet {
2040 let link = core.link();
2041 if link.is_some() && link.unwrap().core().contorl_info_irqsave().pktstatus != 0 {
2042 event.insert(
2043 EPollEventType::EPOLLPRI
2044 | EPollEventType::EPOLLIN
2045 | EPollEventType::EPOLLRDNORM,
2046 );
2047 }
2048 }
2049
2050 if core.flags().contains(TtyFlag::OTHER_CLOSED) {
2051 event.insert(EPollEventType::EPOLLHUP);
2052 }
2053
2054 if core.driver().driver_funcs().chars_in_buffer() < 256
2055 && core.driver().driver_funcs().write_room(core) > 0
2056 {
2057 event.insert(EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM);
2058 }
2059
2060 Ok(event.bits() as usize)
2061 }
2062
hangup(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError>2063 fn hangup(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> {
2064 todo!()
2065 }
2066
receive_buf( &self, tty: Arc<TtyCore>, buf: &[u8], flags: Option<&[u8]>, count: usize, ) -> Result<usize, SystemError>2067 fn receive_buf(
2068 &self,
2069 tty: Arc<TtyCore>,
2070 buf: &[u8],
2071 flags: Option<&[u8]>,
2072 count: usize,
2073 ) -> Result<usize, SystemError> {
2074 let mut ldata = self.disc_data();
2075 ldata.receive_buf_common(tty, buf, flags, count, false)
2076 }
2077
receive_buf2( &self, tty: Arc<TtyCore>, buf: &[u8], flags: Option<&[u8]>, count: usize, ) -> Result<usize, SystemError>2078 fn receive_buf2(
2079 &self,
2080 tty: Arc<TtyCore>,
2081 buf: &[u8],
2082 flags: Option<&[u8]>,
2083 count: usize,
2084 ) -> Result<usize, SystemError> {
2085 let mut ldata = self.disc_data();
2086 ldata.receive_buf_common(tty, buf, flags, count, true)
2087 }
2088 }
2089