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