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