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