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, TtyPacketStatus}, 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: 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: Weak::default(), 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 ((c as usize) < self.char_map.size()) && 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 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 if !termios.local_mode.contains(LocalMode::NOFLSH) { 795 // 重置 796 self.echo_head = 0; 797 self.echo_tail = 0; 798 self.echo_mark = 0; 799 self.echo_commit = 0; 800 801 let _ = tty.flush_buffer(tty.core()); 802 803 self.read_head = 0; 804 self.canon_head = 0; 805 self.read_tail = 0; 806 self.line_start = 0; 807 808 self.erasing = false; 809 self.read_flags.set_all(false); 810 self.pushing = false; 811 self.lookahead_count = 0; 812 813 if tty.core().link().is_some() { 814 self.packet_mode_flush(tty.core()); 815 } 816 } 817 } 818 819 pub fn receive_char(&mut self, c: u8, tty: Arc<TtyCore>) { 820 let termios = tty.core().termios(); 821 822 if termios.local_mode.contains(LocalMode::ECHO) { 823 if self.erasing { 824 self.add_echo_byte(b'/'); 825 self.erasing = false; 826 } 827 828 if self.canon_head == self.read_head { 829 self.add_echo_byte(EchoOperation::Start.to_u8()); 830 self.add_echo_byte(EchoOperation::SetCanonCol.to_u8()); 831 } 832 833 self.echo_char(c, &termios); 834 self.commit_echoes(tty.clone()); 835 } 836 837 if c == 0o377 && tty.core().termios().input_mode.contains(InputMode::PARMRK) { 838 self.add_read_byte(c); 839 } 840 self.add_read_byte(c); 841 } 842 843 pub fn echo_char(&mut self, c: u8, termios: &RwLockReadGuard<Termios>) { 844 if c == EchoOperation::Start.to_u8() { 845 self.add_echo_byte(EchoOperation::Start.to_u8()); 846 self.add_echo_byte(EchoOperation::Start.to_u8()); 847 } else { 848 if termios.local_mode.contains(LocalMode::ECHOCTL) 849 && (c as char).is_control() 850 && c != b'\t' 851 { 852 self.add_echo_byte(EchoOperation::Start.to_u8()); 853 } 854 self.add_echo_byte(c); 855 } 856 } 857 858 pub fn echo_char_raw(&mut self, c: u8) { 859 if c == EchoOperation::Start.to_u8() { 860 self.add_echo_byte(EchoOperation::Start.to_u8()); 861 self.add_echo_byte(EchoOperation::Start.to_u8()); 862 } else { 863 self.add_echo_byte(c); 864 } 865 } 866 867 /// ## 提交echobuf里的数据显示 868 pub fn commit_echoes(&mut self, tty: Arc<TtyCore>) { 869 let head = self.echo_head; 870 self.echo_mark = head; 871 let old = self.echo_commit - self.echo_tail; 872 873 // 需要echo的字符个数 874 let nr = head - self.echo_tail; 875 876 if nr < ECHO_COMMIT_WATERMARK || nr % ECHO_BLOCK > old % ECHO_BLOCK { 877 return; 878 } 879 880 self.echo_commit = head; 881 let echoed = self.echoes(tty.clone()); 882 883 if echoed.is_ok() && echoed.unwrap() > 0 { 884 tty.flush_chars(tty.core()); 885 } 886 } 887 888 pub fn add_echo_byte(&mut self, c: u8) { 889 self.echo_buf[ntty_buf_mask(self.echo_head)] = c; 890 self.echo_head += 1; 891 } 892 893 pub fn add_read_byte(&mut self, c: u8) { 894 self.read_buf[ntty_buf_mask(self.read_head)] = c; 895 self.read_head += 1; 896 } 897 898 /// ### 将read_buffer的部分值置0 899 /// 900 /// 只会在规范模式和禁用echo下执行 901 #[inline] 902 pub fn zero_buffer(&mut self, offset: usize, size: usize) { 903 let offset = offset & (NTTY_BUFSIZE - 1); 904 if self.icanon && !self.echo { 905 let n = offset + size; 906 if n > NTTY_BUFSIZE { 907 for c in &mut self.read_buf[offset..NTTY_BUFSIZE] { 908 *c = 0 909 } 910 911 for c in &mut self.read_buf[0..(n - NTTY_BUFSIZE)] { 912 *c = 0 913 } 914 } else { 915 for c in &mut self.read_buf[offset..n] { 916 *c = 0 917 } 918 }; 919 } 920 } 921 922 /// ## 从ntty中拷贝数据 923 /// 924 /// ### 参数 925 /// 926 /// ### to: 存储数据 927 /// ### tail: 读取尾 928 pub fn ntty_copy( 929 &mut self, 930 to: &mut [u8], 931 tail: usize, 932 n: &mut usize, 933 ) -> Result<(), SystemError> { 934 if to.len() < *n { 935 *n = to.len(); 936 // return Err(SystemError::EINVAL); 937 } 938 if tail > NTTY_BUFSIZE { 939 return Err(SystemError::EINVAL); 940 } 941 942 let size = NTTY_BUFSIZE - tail; 943 944 if size < *n { 945 // 有一部分数据在头部,则先拷贝后面部分,再拷贝头部 946 // TODO: tty审计? 947 to[0..size].copy_from_slice(&self.read_buf[tail..(tail + size)]); 948 to[size..(*n)].copy_from_slice(&self.read_buf[0..(*n - size)]); 949 } else { 950 to[..*n].copy_from_slice(&self.read_buf[tail..(tail + *n)]) 951 } 952 953 self.zero_buffer(tail, *n); 954 955 Ok(()) 956 } 957 958 /// ## 规范模式下跳过EOF 959 pub fn canon_skip_eof(&mut self) { 960 // 没有数据 961 if self.read_tail == self.canon_head { 962 return; 963 } 964 965 let tail = self.read_tail & (NTTY_BUFSIZE - 1); 966 967 // 查看read_flags是否读取位置为特殊字符 968 if !self.read_flags.get(tail).unwrap() { 969 return; 970 } 971 972 // 确保读取位置是'\0'字符 973 if self.read_buf[tail] != ControlCharIndex::DISABLE_CHAR { 974 return; 975 } 976 977 // 处理该字符,将read_flagsw该位清除 978 self.read_flags.set(tail, false); 979 // 读取位置+1,即跳过该字符不做处理 980 self.read_tail += 1; 981 } 982 983 /// ## 在规范模式(canonical mode)下从读缓冲中复制一行 984 /// 985 /// 一次只拷贝一行 986 /// 987 /// ## 参数 988 /// ### dst: 存放数据 989 /// ### nr: 需要拷贝的数据大小 990 /// 991 /// ## 返回值 992 /// ### true: 表示一行未结束并且还有数据可读 993 /// ### false: 一行已结束或者没有数据可读 994 pub fn canon_copy_from_read_buf( 995 &mut self, 996 dst: &mut [u8], 997 nr: &mut usize, 998 offset: &mut usize, 999 ) -> Result<bool, SystemError> { 1000 if *nr == 0 { 1001 return Ok(false); 1002 } 1003 1004 let canon_head = self.canon_head; 1005 1006 // 取得能够读到的字符数,即canon_head - self.read_tail和nr最小值 1007 let mut n = (*nr).min(canon_head - self.read_tail); 1008 1009 // 获得读尾index 1010 let tail = self.read_tail & (NTTY_BUFSIZE - 1); 1011 1012 // 避免越界,这个size才是实际读取大小 1013 let size = if tail + n > NTTY_BUFSIZE { 1014 NTTY_BUFSIZE 1015 } else { 1016 tail + n 1017 }; 1018 1019 // 找到eol的坐标 1020 let tmp = self.read_flags.next_index(tail); 1021 // 找到的话即为坐标,未找到的话即为NTTY_BUFSIZE 1022 let mut eol = if let Some(tmp) = tmp { tmp } else { size }; 1023 if eol > size { 1024 eol = size 1025 } 1026 1027 // 是否需要绕回缓冲区头部 1028 let more = n - (size - tail); 1029 1030 // 是否找到eol 1031 let found = if eol == NTTY_BUFSIZE && more > 0 { 1032 // 需要返回头部 1033 let ret = self.read_flags.first_index(); 1034 if let Some(tmp) = ret { 1035 // 在头部范围内找到eol 1036 if tmp < more { 1037 eol = tmp; 1038 } 1039 } else { 1040 eol = more; 1041 } 1042 eol != more 1043 } else { 1044 // 不需要返回头部 1045 eol != size 1046 }; 1047 1048 n = eol - tail; 1049 if n > NTTY_BUFSIZE { 1050 // 减法溢出则加上BUFSIZE即可限制在0-NTTY_BUFSIZE内 1051 n += NTTY_BUFSIZE; 1052 } 1053 1054 // 规范模式下实际扫描过的字符数,需要将eol计算在内 1055 let count = if found { n + 1 } else { n }; 1056 1057 // 表示这一行未结束 1058 if !found || self.read_at(eol) != ControlCharIndex::DISABLE_CHAR { 1059 n = count; 1060 } 1061 1062 self.ntty_copy(&mut dst[*offset..], tail, &mut n)?; 1063 *nr -= n; 1064 *offset += n; 1065 1066 if found { 1067 self.read_flags.set(eol, false); 1068 } 1069 1070 self.read_tail += count; 1071 1072 if found { 1073 if !self.pushing { 1074 self.line_start = self.read_tail; 1075 } else { 1076 self.pushing = false; 1077 } 1078 1079 // todo: 审计? 1080 return Ok(false); 1081 } 1082 1083 // 这里是表示没有找到eol,根据是否还有数据可读返回 1084 Ok(self.read_tail != canon_head) 1085 } 1086 1087 /// ## 根据终端的模式和输入缓冲区中的数据量,判断是否可读字符 1088 pub fn input_available(&self, termios: RwLockReadGuard<Termios>, poll: bool) -> bool { 1089 // 计算最小字符数 1090 let amt = if poll 1091 && termios.control_characters[ControlCharIndex::VTIME] as u32 == 0 1092 && termios.control_characters[ControlCharIndex::VMIN] as u32 != 0 1093 { 1094 termios.control_characters[ControlCharIndex::VMIN] as usize 1095 } else { 1096 1 1097 }; 1098 1099 // 规范模式且非拓展 1100 if self.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) { 1101 return self.canon_head != self.read_tail; 1102 } else { 1103 return (self.commit_head - self.read_tail) >= amt; 1104 } 1105 } 1106 1107 /// ## 非规范模式下从read_buf读取数据 1108 /// 1109 /// ## 参数 1110 /// ### termios: tty对应的termioss读锁守卫 1111 /// ### dst: 存储读取数据 1112 /// ### nr: 读取长度 1113 /// 1114 /// ## 返回值 1115 /// ### true: 还有更多数据可读 1116 /// ### false: 无更多数据可读 1117 pub fn copy_from_read_buf( 1118 &mut self, 1119 termios: RwLockReadGuard<Termios>, 1120 dst: &mut [u8], 1121 nr: &mut usize, 1122 offset: &mut usize, 1123 ) -> Result<bool, SystemError> { 1124 let head = self.commit_head; 1125 let tail = self.read_tail & (NTTY_BUFSIZE - 1); 1126 1127 // 计算出可读的字符数 1128 let mut n = (NTTY_BUFSIZE - tail).min(head - self.read_tail); 1129 n = n.min(*nr); 1130 1131 if n > 0 { 1132 // 拷贝数据 1133 self.ntty_copy(&mut dst[*offset..], tail, &mut n)?; 1134 // todo:审计? 1135 self.read_tail += n; 1136 1137 // 是否只读取了eof 1138 let eof = 1139 n == 1 && self.read_buf[tail] == termios.control_characters[ControlCharIndex::VEOF]; 1140 1141 if termios.local_mode.contains(LocalMode::EXTPROC) 1142 && self.icanon 1143 && eof 1144 && head == self.read_tail 1145 { 1146 return Ok(false); 1147 } 1148 1149 *nr -= n; 1150 *offset += n; 1151 1152 return Ok(head != self.read_tail); 1153 } 1154 1155 Ok(false) 1156 } 1157 1158 /// ## 用于处理带有 OPOST(Output Post-processing)标志的输出块的函数 1159 /// OPOST 是 POSIX 终端驱动器标志之一,用于指定在写入终端设备之前对输出数据进行一些后期处理。 1160 pub fn process_output_block( 1161 &mut self, 1162 core: &TtyCoreData, 1163 termios: RwLockReadGuard<Termios>, 1164 buf: &[u8], 1165 nr: usize, 1166 ) -> Result<usize, SystemError> { 1167 let mut nr = nr; 1168 let tty = self.tty.upgrade().unwrap(); 1169 let space = tty.write_room(tty.core()); 1170 1171 // 如果读取数量大于了可用空间,则取最小的为真正的写入数量 1172 if nr > space { 1173 nr = space 1174 } 1175 1176 let mut cnt = 0; 1177 for (i, c) in buf.iter().enumerate().take(nr) { 1178 cnt = i; 1179 let c = *c; 1180 if c as usize == 8 { 1181 // 表示退格 1182 if self.cursor_column > 0 { 1183 self.cursor_column -= 1; 1184 } 1185 continue; 1186 } 1187 match c as char { 1188 '\n' => { 1189 if termios.output_mode.contains(OutputMode::ONLRET) { 1190 // 将回车映射为\n,即将\n换为回车 1191 self.cursor_column = 0; 1192 } 1193 if termios.output_mode.contains(OutputMode::ONLCR) { 1194 // 输出时将\n换为\r\n 1195 break; 1196 } 1197 1198 self.canon_cursor_column = self.cursor_column; 1199 } 1200 '\r' => { 1201 if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 { 1202 // 光标已经在第0列,则不输出回车符 1203 break; 1204 } 1205 1206 if termios.output_mode.contains(OutputMode::OCRNL) { 1207 break; 1208 } 1209 self.cursor_column = 0; 1210 self.canon_cursor_column = 0; 1211 } 1212 '\t' => { 1213 break; 1214 } 1215 _ => { 1216 // 判断是否为控制字符 1217 if !(c as char).is_control() { 1218 if termios.output_mode.contains(OutputMode::OLCUC) { 1219 break; 1220 } 1221 1222 // 判断是否为utf8模式下的连续字符 1223 if !(termios.input_mode.contains(InputMode::IUTF8) 1224 && (c as usize) & 0xc0 == 0x80) 1225 { 1226 self.cursor_column += 1; 1227 } 1228 } 1229 } 1230 } 1231 } 1232 1233 drop(termios); 1234 return tty.write(core, buf, cnt); 1235 } 1236 1237 /// ## 处理回显 1238 pub fn process_echoes(&mut self, tty: Arc<TtyCore>) { 1239 if self.echo_mark == self.echo_tail { 1240 return; 1241 } 1242 self.echo_commit = self.echo_mark; 1243 let echoed = self.echoes(tty.clone()); 1244 1245 if echoed.is_ok() && echoed.unwrap() > 0 { 1246 tty.flush_chars(tty.core()); 1247 } 1248 } 1249 1250 #[inline(never)] 1251 pub fn echoes(&mut self, tty: Arc<TtyCore>) -> Result<usize, SystemError> { 1252 let mut space = tty.write_room(tty.core()); 1253 let ospace = space; 1254 let termios = tty.core().termios(); 1255 let core = tty.core(); 1256 let mut tail = self.echo_tail; 1257 1258 while ntty_buf_mask(self.echo_commit) != ntty_buf_mask(tail) { 1259 let c = self.echo_buf[ntty_buf_mask(tail)]; 1260 1261 if EchoOperation::from_u8(c) == EchoOperation::Start { 1262 if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 1) { 1263 self.echo_tail = tail; 1264 return Ok(ospace - space); 1265 } 1266 1267 // 获取到start,之后取第一个作为op 1268 let op = EchoOperation::from_u8(self.echo_buf[ntty_buf_mask(tail + 1)]); 1269 1270 match op { 1271 EchoOperation::Start => { 1272 if space == 0 { 1273 break; 1274 } 1275 1276 if tty 1277 .put_char(tty.core(), EchoOperation::Start.to_u8()) 1278 .is_err() 1279 { 1280 tty.write(core, &[EchoOperation::Start.to_u8()], 1)?; 1281 } 1282 1283 self.cursor_column += 1; 1284 space -= 1; 1285 tail += 2; 1286 } 1287 EchoOperation::MoveBackCol => { 1288 if self.cursor_column > 0 { 1289 self.cursor_column -= 1; 1290 } 1291 tail += 2; 1292 } 1293 EchoOperation::SetCanonCol => { 1294 self.canon_cursor_column = self.cursor_column; 1295 tail += 2; 1296 } 1297 EchoOperation::EraseTab => { 1298 if ntty_buf_mask(self.echo_commit) == ntty_buf_mask(tail + 2) { 1299 self.echo_tail = tail; 1300 return Ok(ospace - space); 1301 } 1302 1303 // 要擦除的制表符所占用的列数 1304 let mut char_num = self.echo_buf[ntty_buf_mask(tail + 2)] as usize; 1305 1306 /* 1307 如果 num_chars 的最高位(0x80)未设置, 1308 表示这是从输入的起始位置而不是从先前的制表符开始计算的列数。 1309 在这种情况下,将 num_chars 与 ldata->canon_column 相加,否则,列数就是正常的制表符列数。 1310 */ 1311 if char_num & 0x80 == 0 { 1312 char_num += self.canon_cursor_column as usize; 1313 } 1314 1315 // 计算要回退的列数,即制表符宽度减去实际占用的列数 1316 let mut num_bs = 8 - (char_num & 7); 1317 if num_bs > space { 1318 // 表示左边没有足够空间回退 1319 break; 1320 } 1321 1322 space -= num_bs; 1323 while num_bs != 0 { 1324 num_bs -= 1; 1325 // 8 => '\b' 1326 if tty.put_char(tty.core(), 8).is_err() { 1327 tty.write(core, &[8], 1)?; 1328 } 1329 1330 if self.cursor_column > 0 { 1331 self.cursor_column -= 1; 1332 } 1333 } 1334 1335 // 已经读取了 tail tail+1 tail+2,所以这里偏移加3 1336 tail += 3; 1337 } 1338 EchoOperation::Undefined(ch) => { 1339 match ch { 1340 8 => { 1341 if tty.put_char(tty.core(), 8).is_err() { 1342 tty.write(core, &[8], 1)?; 1343 } 1344 if tty.put_char(tty.core(), b' ').is_err() { 1345 tty.write(core, b" ", 1)?; 1346 } 1347 self.cursor_column -= 1; 1348 space -= 1; 1349 tail += 1; 1350 } 1351 _ => { 1352 // 不是特殊字节码,则表示控制字符 例如 ^C 1353 if space < 2 { 1354 break; 1355 } 1356 1357 if tty.put_char(tty.core(), b'^').is_err() { 1358 tty.write(core, b"^", 1)?; 1359 } 1360 1361 if tty.put_char(tty.core(), ch ^ 0o100).is_err() { 1362 tty.write(core, &[ch ^ 0o100], 1)?; 1363 } 1364 1365 self.cursor_column += 2; 1366 space -= 2; 1367 tail += 2; 1368 } 1369 } 1370 } 1371 } 1372 } else { 1373 if termios.output_mode.contains(OutputMode::OPOST) { 1374 let ret = self.do_output_char(tty.clone(), c, space); 1375 1376 if ret.is_err() { 1377 break; 1378 } 1379 space -= ret.unwrap(); 1380 } else { 1381 if space == 0 { 1382 break; 1383 } 1384 1385 if tty.put_char(tty.core(), c).is_err() { 1386 tty.write(core, &[c], 1)?; 1387 } 1388 space -= 1; 1389 } 1390 tail += 1; 1391 } 1392 } 1393 1394 // 如果回显缓冲区接近满(在下一次提交之前可能会发生回显溢出的情况),则丢弃足够的尾部数据以防止随后的溢出。 1395 while self.echo_commit > tail && self.echo_commit - tail >= ECHO_DISCARD_WATERMARK { 1396 if self.echo_buf[ntty_buf_mask(tail)] == EchoOperation::Start.to_u8() { 1397 if self.echo_buf[ntty_buf_mask(tail + 1)] == EchoOperation::EraseTab.to_u8() { 1398 tail += 3; 1399 } else { 1400 tail += 2; 1401 } 1402 } else { 1403 tail += 1; 1404 } 1405 } 1406 1407 self.echo_tail = tail; 1408 return Ok(ospace - space); 1409 } 1410 1411 /// ## 处理输出字符(带有 OPOST 处理) 1412 pub fn process_output(&mut self, tty: Arc<TtyCore>, c: u8) -> bool { 1413 let space = tty.write_room(tty.core()); 1414 1415 if self.do_output_char(tty, c, space).is_err() { 1416 return false; 1417 } 1418 1419 true 1420 } 1421 1422 // ## 设置带有 OPOST 处理的tty输出一个字符 1423 pub fn do_output_char( 1424 &mut self, 1425 tty: Arc<TtyCore>, 1426 c: u8, 1427 space: usize, 1428 ) -> Result<usize, SystemError> { 1429 if space == 0 { 1430 return Err(SystemError::ENOBUFS); 1431 } 1432 1433 let termios = tty.core().termios(); 1434 let core = tty.core(); 1435 let mut c = c; 1436 if c as usize == 8 { 1437 // 表示退格 1438 if self.cursor_column > 0 { 1439 self.cursor_column -= 1; 1440 } 1441 if tty.put_char(tty.core(), c).is_err() { 1442 tty.write(core, &[c], 1)?; 1443 } 1444 return Ok(1); 1445 } 1446 match c as char { 1447 '\n' => { 1448 if termios.output_mode.contains(OutputMode::ONLRET) { 1449 // 回车符 1450 self.cursor_column = 0; 1451 } 1452 if termios.output_mode.contains(OutputMode::ONLCR) { 1453 // 映射为“\r\n” 1454 if space < 2 { 1455 return Err(SystemError::ENOBUFS); 1456 } 1457 self.cursor_column = 0; 1458 self.canon_cursor_column = 0; 1459 1460 // 通过驱动写入 1461 tty.write(core, "\r\n".as_bytes(), 2)?; 1462 return Ok(2); 1463 } 1464 1465 self.canon_cursor_column = self.cursor_column; 1466 } 1467 '\r' => { 1468 if termios.output_mode.contains(OutputMode::ONOCR) && self.cursor_column == 0 { 1469 // 光标已经在第0列,则不输出回车符 1470 return Ok(0); 1471 } 1472 1473 if termios.output_mode.contains(OutputMode::OCRNL) { 1474 // 输出的\r映射为\n 1475 c = b'\n'; 1476 if termios.output_mode.contains(OutputMode::ONLRET) { 1477 // \r映射为\n,但是保留\r特性 1478 self.cursor_column = 0; 1479 self.canon_cursor_column = 0; 1480 } 1481 } else { 1482 self.cursor_column = 0; 1483 self.canon_cursor_column = 0; 1484 } 1485 } 1486 '\t' => { 1487 // 计算输出一个\t需要的空间 1488 let spaces = 8 - (self.cursor_column & 7) as usize; 1489 if termios.output_mode.contains(OutputMode::TABDLY) 1490 && OutputMode::TABDLY.bits() == OutputMode::XTABS.bits() 1491 { 1492 // 配置的tab选项是真正输出空格到驱动 1493 if space < spaces { 1494 // 空间不够 1495 return Err(SystemError::ENOBUFS); 1496 } 1497 self.cursor_column += spaces as u32; 1498 // 写入sapces个空格 1499 tty.write(core, " ".as_bytes(), spaces)?; 1500 return Ok(spaces); 1501 } 1502 self.cursor_column += spaces as u32; 1503 } 1504 _ => { 1505 // 判断是否为控制字符 1506 if !(c as char).is_control() { 1507 if termios.output_mode.contains(OutputMode::OLCUC) { 1508 c = c.to_ascii_uppercase(); 1509 } 1510 1511 // 判断是否为utf8模式下的连续字符 1512 if !(termios.input_mode.contains(InputMode::IUTF8) 1513 && (c as usize) & 0xc0 == 0x80) 1514 { 1515 self.cursor_column += 1; 1516 } 1517 } 1518 } 1519 } 1520 1521 if tty.put_char(tty.core(), c).is_err() { 1522 tty.write(core, &[c], 1)?; 1523 } 1524 Ok(1) 1525 } 1526 1527 fn packet_mode_flush(&self, tty: &TtyCoreData) { 1528 let link = tty.link().unwrap(); 1529 if link.core().contorl_info_irqsave().packet { 1530 tty.contorl_info_irqsave() 1531 .pktstatus 1532 .insert(TtyPacketStatus::TIOCPKT_FLUSHREAD); 1533 1534 link.core().read_wq().wakeup_all(); 1535 } 1536 } 1537 } 1538 1539 impl TtyLineDiscipline for NTtyLinediscipline { 1540 fn open(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> { 1541 // 反向绑定tty到disc 1542 self.disc_data().tty = Arc::downgrade(&tty); 1543 // 特定的tty设备在这里可能需要取消端口节流 1544 return self.set_termios(tty, None); 1545 } 1546 1547 fn close(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> { 1548 todo!() 1549 } 1550 1551 /// ## 重置缓冲区的基本信息 1552 fn flush_buffer(&self, tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> { 1553 let core = tty.core(); 1554 let _ = core.termios(); 1555 let mut ldata = self.disc_data(); 1556 ldata.read_head = 0; 1557 ldata.canon_head = 0; 1558 ldata.read_tail = 0; 1559 ldata.commit_head = 0; 1560 ldata.line_start = 0; 1561 ldata.erasing = false; 1562 ldata.read_flags.set_all(false); 1563 ldata.pushing = false; 1564 ldata.lookahead_count = 0; 1565 1566 // todo: kick worker? 1567 // packet mode? 1568 if core.link().is_some() { 1569 ldata.packet_mode_flush(core); 1570 } 1571 1572 Ok(()) 1573 } 1574 1575 #[inline(never)] 1576 fn read( 1577 &self, 1578 tty: Arc<TtyCore>, 1579 buf: &mut [u8], 1580 len: usize, 1581 cookie: &mut bool, 1582 _offset: usize, 1583 mode: FileMode, 1584 ) -> Result<usize, system_error::SystemError> { 1585 let mut ldata; 1586 if mode.contains(FileMode::O_NONBLOCK) { 1587 let ret = self.disc_data_try_lock(); 1588 if ret.is_err() { 1589 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 1590 } 1591 ldata = ret.unwrap(); 1592 } else { 1593 ldata = self.disc_data(); 1594 } 1595 let core = tty.core(); 1596 let termios = core.termios(); 1597 let mut nr = len; 1598 1599 let mut offset = 0; 1600 1601 // 表示接着读 1602 if *cookie { 1603 // 规范且非拓展模式 1604 if ldata.icanon && !termios.local_mode.contains(LocalMode::EXTPROC) { 1605 // 跳过EOF字符 1606 if len == 0 { 1607 ldata.canon_skip_eof(); 1608 } else if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? { 1609 return Ok(len - nr); 1610 } 1611 } else if ldata.copy_from_read_buf(termios, buf, &mut nr, &mut offset)? { 1612 return Ok(len - nr); 1613 } 1614 1615 // 没有数据可读 1616 1617 // todo: kick worker? or 关闭节流? 1618 1619 *cookie = false; 1620 return Ok(len - nr); 1621 } 1622 1623 drop(termios); 1624 1625 TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTIN)?; 1626 1627 let mut minimum: usize = 0; 1628 if !ldata.icanon { 1629 let core = tty.core(); 1630 let termios = core.termios(); 1631 minimum = termios.control_characters[ControlCharIndex::VMIN] as usize; 1632 if minimum == 0 { 1633 minimum = 1; 1634 } 1635 } 1636 1637 let packet = core.contorl_info_irqsave().packet; 1638 let mut ret: Result<usize, SystemError> = Ok(0); 1639 // 记录读取前 的tail 1640 let tail = ldata.read_tail; 1641 drop(ldata); 1642 while nr != 0 { 1643 // todo: 处理packet模式 1644 if packet { 1645 let link = core.link().unwrap(); 1646 let link = link.core(); 1647 let mut ctrl = link.contorl_info_irqsave(); 1648 if !ctrl.pktstatus.is_empty() { 1649 if offset != 0 { 1650 break; 1651 } 1652 let cs = ctrl.pktstatus; 1653 ctrl.pktstatus = TtyPacketStatus::empty(); 1654 1655 buf[offset] = cs.bits(); 1656 offset += 1; 1657 // nr -= 1; 1658 break; 1659 } 1660 } 1661 1662 let mut ldata = self.disc_data(); 1663 1664 let core = tty.core(); 1665 if !ldata.input_available(core.termios(), false) { 1666 if core.flags().contains(TtyFlag::OTHER_CLOSED) { 1667 ret = Err(SystemError::EIO); 1668 break; 1669 } 1670 1671 if core.flags().contains(TtyFlag::HUPPED) || core.flags().contains(TtyFlag::HUPPING) 1672 { 1673 break; 1674 } 1675 1676 if mode.contains(FileMode::O_NONBLOCK) 1677 || core.flags().contains(TtyFlag::LDISC_CHANGING) 1678 { 1679 ret = Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 1680 break; 1681 } 1682 1683 if ProcessManager::current_pcb() 1684 .sig_info_irqsave() 1685 .sig_pending() 1686 .has_pending() 1687 { 1688 ret = Err(SystemError::ERESTARTSYS); 1689 break; 1690 } 1691 1692 // 休眠一段时间 1693 // 获取到termios读锁,避免termios被更改导致行为异常 1694 // let termios = core.termios_preempt_enable(); 1695 // let helper = WakeUpHelper::new(ProcessManager::current_pcb()); 1696 // let wakeup_helper = Timer::new(helper, timeout); 1697 // wakeup_helper.activate(); 1698 // drop(termios); 1699 drop(ldata); 1700 core.read_wq() 1701 .sleep((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as u64); 1702 continue; 1703 } 1704 1705 if ldata.icanon && !core.termios().local_mode.contains(LocalMode::EXTPROC) { 1706 if ldata.canon_copy_from_read_buf(buf, &mut nr, &mut offset)? { 1707 *cookie = true; 1708 offset += len - nr; 1709 return Ok(offset); 1710 } 1711 } else { 1712 // 非标准模式 1713 // todo: 处理packet模式 1714 if packet && offset == 0 { 1715 buf[offset] = TtyPacketStatus::TIOCPKT_DATA.bits(); 1716 offset += 1; 1717 nr -= 1; 1718 } 1719 // 拷贝数据 1720 if ldata.copy_from_read_buf(core.termios(), buf, &mut nr, &mut offset)? 1721 && offset >= minimum 1722 { 1723 *cookie = true; 1724 return Ok(offset); 1725 } 1726 } 1727 1728 if offset >= minimum { 1729 break; 1730 } 1731 } 1732 let ldata = self.disc_data(); 1733 if tail != ldata.read_tail { 1734 // todo: kick worker? 1735 } 1736 1737 if offset > 0 { 1738 return Ok(offset); 1739 } 1740 1741 ret 1742 } 1743 1744 #[inline(never)] 1745 fn write( 1746 &self, 1747 tty: Arc<TtyCore>, 1748 buf: &[u8], 1749 len: usize, 1750 mode: FileMode, 1751 ) -> Result<usize, system_error::SystemError> { 1752 let mut nr = len; 1753 let mut ldata = self.disc_data(); 1754 let pcb = ProcessManager::current_pcb(); 1755 let binding = tty.clone(); 1756 let core = binding.core(); 1757 let termios = *core.termios(); 1758 if termios.local_mode.contains(LocalMode::TOSTOP) { 1759 TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?; 1760 } 1761 1762 ldata.process_echoes(tty.clone()); 1763 // drop(ldata); 1764 let mut offset = 0; 1765 loop { 1766 if pcb.sig_info_irqsave().sig_pending().has_pending() { 1767 return Err(SystemError::ERESTARTSYS); 1768 } 1769 if core.flags().contains(TtyFlag::HUPPED) { 1770 return Err(SystemError::EIO); 1771 } 1772 if termios.output_mode.contains(OutputMode::OPOST) { 1773 while nr > 0 { 1774 // let mut ldata = self.disc_data(); 1775 // 获得一次处理后的数量 1776 let ret = ldata.process_output_block(core, core.termios(), &buf[offset..], nr); 1777 let num = match ret { 1778 Ok(num) => num, 1779 Err(e) => { 1780 if e == SystemError::EAGAIN_OR_EWOULDBLOCK { 1781 break; 1782 } else { 1783 return Err(e); 1784 } 1785 } 1786 }; 1787 1788 offset += num; 1789 nr -= num; 1790 1791 if nr == 0 { 1792 break; 1793 } 1794 1795 let c = buf[offset]; 1796 if !ldata.process_output(tty.clone(), c) { 1797 break; 1798 } 1799 offset += 1; 1800 nr -= 1; 1801 } 1802 1803 tty.flush_chars(core); 1804 } else { 1805 while nr > 0 { 1806 let write = tty.write(core, &buf[offset..], nr)?; 1807 if write == 0 { 1808 break; 1809 } 1810 offset += write; 1811 nr -= write; 1812 } 1813 } 1814 1815 if nr == 0 { 1816 break; 1817 } 1818 1819 if mode.contains(FileMode::O_NONBLOCK) || core.flags().contains(TtyFlag::LDISC_CHANGING) 1820 { 1821 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 1822 } 1823 1824 // 到这里表明没位置可写了 1825 // 休眠一段时间 1826 // 获取到termios读锁,避免termios被更改导致行为异常 1827 core.write_wq() 1828 .sleep(EPollEventType::EPOLLOUT.bits() as u64); 1829 } 1830 1831 Ok(offset) 1832 } 1833 1834 fn ioctl( 1835 &self, 1836 tty: Arc<TtyCore>, 1837 cmd: u32, 1838 arg: usize, 1839 ) -> Result<usize, system_error::SystemError> { 1840 match cmd { 1841 TtyIoctlCmd::TIOCOUTQ => { 1842 let mut user_writer = UserBufferWriter::new( 1843 VirtAddr::new(arg).as_ptr::<i32>(), 1844 core::mem::size_of::<i32>(), 1845 true, 1846 )?; 1847 1848 let count = tty.chars_in_buffer(); 1849 user_writer.copy_one_to_user::<i32>(&(count as i32), 0)?; 1850 return Ok(0); 1851 } 1852 TtyIoctlCmd::FIONREAD => { 1853 let ldata = self.disc_data(); 1854 let termios = tty.core().termios(); 1855 let retval; 1856 if termios.local_mode.contains(LocalMode::ICANON) 1857 && !termios.local_mode.contains(LocalMode::EXTPROC) 1858 { 1859 if ldata.canon_head == ldata.read_tail { 1860 retval = 0; 1861 } else { 1862 let head = ldata.canon_head; 1863 let mut tail = ldata.read_tail; 1864 let mut nr = head - tail; 1865 1866 while ntty_buf_mask(head) != ntty_buf_mask(tail) { 1867 if ldata.read_flags.get(ntty_buf_mask(tail)).unwrap() 1868 && ldata.read_buf[ntty_buf_mask(tail)] 1869 == ControlCharIndex::DISABLE_CHAR 1870 { 1871 nr -= 1; 1872 } 1873 tail += 1; 1874 } 1875 1876 retval = nr; 1877 } 1878 } else { 1879 retval = ldata.read_cnt(); 1880 } 1881 1882 let mut user_writer = UserBufferWriter::new( 1883 VirtAddr::new(arg).as_ptr::<i32>(), 1884 core::mem::size_of::<i32>(), 1885 true, 1886 )?; 1887 1888 user_writer.copy_one_to_user::<i32>(&(retval as i32), 0)?; 1889 return Ok(0); 1890 } 1891 _ => { 1892 return self.ioctl_helper(tty, cmd, arg); 1893 } 1894 } 1895 } 1896 1897 #[inline(never)] 1898 fn set_termios( 1899 &self, 1900 tty: Arc<TtyCore>, 1901 old: Option<crate::driver::tty::termios::Termios>, 1902 ) -> Result<(), system_error::SystemError> { 1903 let core = tty.core(); 1904 let termios = core.termios(); 1905 let mut ldata = self.disc_data(); 1906 let contorl_chars = termios.control_characters; 1907 1908 // 第一次设置或者规范模式 (ICANON) 或者扩展处理 (EXTPROC) 标志发生变化 1909 let mut spec_mode_changed = false; 1910 if let Some(old) = old { 1911 let local_mode = old.local_mode.bitxor(termios.local_mode); 1912 spec_mode_changed = 1913 local_mode.contains(LocalMode::ICANON) || local_mode.contains(LocalMode::EXTPROC); 1914 } 1915 if old.is_none() || spec_mode_changed { 1916 // 重置read_flags 1917 ldata.read_flags.set_all(false); 1918 1919 ldata.line_start = ldata.read_tail; 1920 1921 // 不是规范模式或者有可读数据 1922 if !termios.local_mode.contains(LocalMode::ICANON) || ldata.read_cnt() != 0 { 1923 ldata.canon_head = ldata.read_tail; 1924 ldata.pushing = false; 1925 } else { 1926 let read_head = ldata.read_head; 1927 ldata 1928 .read_flags 1929 .set((read_head - 1) & (NTTY_BUFSIZE - 1), true); 1930 ldata.canon_head = ldata.read_head; 1931 ldata.pushing = true; 1932 } 1933 ldata.commit_head = ldata.read_head; 1934 ldata.erasing = false; 1935 ldata.lnext = false; 1936 } 1937 1938 // 设置模式 1939 ldata.icanon = termios.local_mode.contains(LocalMode::ICANON); 1940 1941 // 设置回显 1942 if termios.local_mode.contains(LocalMode::ECHO) { 1943 ldata.echo = true; 1944 } 1945 1946 if termios.input_mode.contains(InputMode::ISTRIP) 1947 || termios.input_mode.contains(InputMode::IUCLC) 1948 || termios.input_mode.contains(InputMode::IGNCR) 1949 || termios.input_mode.contains(InputMode::IXON) 1950 || termios.local_mode.contains(LocalMode::ISIG) 1951 || termios.local_mode.contains(LocalMode::ECHO) 1952 || termios.input_mode.contains(InputMode::PARMRK) 1953 { 1954 // 非原模式 1955 1956 ldata.char_map.set_all(false); 1957 1958 // 忽略回车符或者将回车映射为换行符 1959 if termios.input_mode.contains(InputMode::IGNCR) 1960 || termios.input_mode.contains(InputMode::ICRNL) 1961 { 1962 ldata.char_map.set('\r' as usize, true); 1963 } 1964 1965 // 将换行映射为回车 1966 if termios.input_mode.contains(InputMode::INLCR) { 1967 ldata.char_map.set('\n' as usize, true); 1968 } 1969 1970 // 规范模式 1971 if termios.local_mode.contains(LocalMode::ICANON) { 1972 ldata 1973 .char_map 1974 .set(contorl_chars[ControlCharIndex::VERASE] as usize, true); 1975 ldata 1976 .char_map 1977 .set(contorl_chars[ControlCharIndex::VKILL] as usize, true); 1978 ldata 1979 .char_map 1980 .set(contorl_chars[ControlCharIndex::VEOF] as usize, true); 1981 ldata.char_map.set('\n' as usize, true); 1982 ldata 1983 .char_map 1984 .set(contorl_chars[ControlCharIndex::VEOL] as usize, true); 1985 1986 if termios.local_mode.contains(LocalMode::IEXTEN) { 1987 ldata 1988 .char_map 1989 .set(contorl_chars[ControlCharIndex::VWERASE] as usize, true); 1990 ldata 1991 .char_map 1992 .set(contorl_chars[ControlCharIndex::VLNEXT] as usize, true); 1993 ldata 1994 .char_map 1995 .set(contorl_chars[ControlCharIndex::VEOL2] as usize, true); 1996 if termios.local_mode.contains(LocalMode::ECHO) { 1997 ldata 1998 .char_map 1999 .set(contorl_chars[ControlCharIndex::VREPRINT] as usize, true); 2000 } 2001 } 2002 } 2003 2004 // 软件流控制 2005 if termios.input_mode.contains(InputMode::IXON) { 2006 ldata 2007 .char_map 2008 .set(contorl_chars[ControlCharIndex::VSTART] as usize, true); 2009 ldata 2010 .char_map 2011 .set(contorl_chars[ControlCharIndex::VSTOP] as usize, true); 2012 } 2013 2014 if termios.local_mode.contains(LocalMode::ISIG) { 2015 ldata 2016 .char_map 2017 .set(contorl_chars[ControlCharIndex::VINTR] as usize, true); 2018 ldata 2019 .char_map 2020 .set(contorl_chars[ControlCharIndex::VQUIT] as usize, true); 2021 ldata 2022 .char_map 2023 .set(contorl_chars[ControlCharIndex::VSUSP] as usize, true); 2024 } 2025 2026 ldata 2027 .char_map 2028 .set(ControlCharIndex::DISABLE_CHAR as usize, true); 2029 ldata.raw = false; 2030 ldata.real_raw = false; 2031 } else { 2032 // 原模式或real_raw 2033 ldata.raw = true; 2034 2035 ldata.real_raw = termios.input_mode.contains(InputMode::IGNBRK) 2036 || (!termios.input_mode.contains(InputMode::BRKINT) 2037 && !termios.input_mode.contains(InputMode::PARMRK)) 2038 && (termios.input_mode.contains(InputMode::IGNPAR) 2039 || !termios.input_mode.contains(InputMode::INPCK)) 2040 && (core 2041 .driver() 2042 .flags() 2043 .contains(TtyDriverFlag::TTY_DRIVER_REAL_RAW)); 2044 } 2045 2046 // if !termios.input_mode.contains(InputMode::IXON) 2047 // && old.is_some() 2048 // && old.unwrap().input_mode.contains(InputMode::IXON) && ! 2049 // {} 2050 2051 core.read_wq().wakeup_all(); 2052 core.write_wq().wakeup_all(); 2053 Ok(()) 2054 } 2055 2056 fn poll(&self, tty: Arc<TtyCore>) -> Result<usize, system_error::SystemError> { 2057 let core = tty.core(); 2058 let ldata = self.disc_data(); 2059 2060 let mut event = EPollEventType::empty(); 2061 if ldata.input_available(core.termios(), true) { 2062 event.insert(EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM) 2063 } 2064 2065 if core.contorl_info_irqsave().packet { 2066 let link = core.link(); 2067 if link.is_some() 2068 && !link 2069 .unwrap() 2070 .core() 2071 .contorl_info_irqsave() 2072 .pktstatus 2073 .is_empty() 2074 { 2075 event.insert( 2076 EPollEventType::EPOLLPRI 2077 | EPollEventType::EPOLLIN 2078 | EPollEventType::EPOLLRDNORM, 2079 ); 2080 } 2081 } 2082 2083 if core.flags().contains(TtyFlag::OTHER_CLOSED) { 2084 event.insert(EPollEventType::EPOLLHUP); 2085 } 2086 2087 if core.driver().driver_funcs().chars_in_buffer() < 256 2088 && core.driver().driver_funcs().write_room(core) > 0 2089 { 2090 event.insert(EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM); 2091 } 2092 2093 Ok(event.bits() as usize) 2094 } 2095 2096 fn hangup(&self, _tty: Arc<TtyCore>) -> Result<(), system_error::SystemError> { 2097 todo!() 2098 } 2099 2100 fn receive_buf( 2101 &self, 2102 tty: Arc<TtyCore>, 2103 buf: &[u8], 2104 flags: Option<&[u8]>, 2105 count: usize, 2106 ) -> Result<usize, SystemError> { 2107 let mut ldata = self.disc_data(); 2108 ldata.receive_buf_common(tty, buf, flags, count, false) 2109 } 2110 2111 fn receive_buf2( 2112 &self, 2113 tty: Arc<TtyCore>, 2114 buf: &[u8], 2115 flags: Option<&[u8]>, 2116 count: usize, 2117 ) -> Result<usize, SystemError> { 2118 let mut ldata = self.disc_data(); 2119 ldata.receive_buf_common(tty, buf, flags, count, true) 2120 } 2121 } 2122