tty_job_control.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. use alloc::sync::Arc;
  2. use system_error::SystemError;
  3. use crate::{
  4. arch::ipc::signal::{SigSet, Signal},
  5. mm::VirtAddr,
  6. process::{Pid, ProcessFlags, ProcessManager},
  7. syscall::{
  8. user_access::{UserBufferReader, UserBufferWriter},
  9. Syscall,
  10. },
  11. };
  12. use super::tty_core::{TtyCore, TtyIoctlCmd};
  13. pub struct TtyJobCtrlManager;
  14. impl TtyJobCtrlManager {
  15. /// ### 设置当前进程的tty
  16. pub fn proc_set_tty(tty: Arc<TtyCore>) {
  17. let core = tty.core();
  18. let mut ctrl = core.contorl_info_irqsave();
  19. let pcb = ProcessManager::current_pcb();
  20. ctrl.session = Some(pcb.basic().sid());
  21. assert!(pcb.sig_info_irqsave().tty().is_none());
  22. let mut singal = pcb.sig_info_mut();
  23. drop(ctrl);
  24. singal.set_tty(Some(tty.clone()));
  25. }
  26. /// ### 检查tty
  27. pub fn tty_check_change(tty: Arc<TtyCore>, sig: Signal) -> Result<(), SystemError> {
  28. let pcb = ProcessManager::current_pcb();
  29. if pcb.sig_info_irqsave().tty().is_none()
  30. || !Arc::ptr_eq(&pcb.sig_info_irqsave().tty().unwrap(), &tty)
  31. {
  32. return Ok(());
  33. }
  34. let core = tty.core();
  35. let ctrl = core.contorl_info_irqsave();
  36. // todo pgid
  37. let pgid = pcb.pid();
  38. let tty_pgid = ctrl.pgid;
  39. if tty_pgid.is_some() && tty_pgid.unwrap() != pgid {
  40. if pcb
  41. .sig_info_irqsave()
  42. .sig_blocked()
  43. .contains(SigSet::from_bits_truncate(1 << sig as u64))
  44. || pcb.sig_struct_irqsave().handlers[sig as usize - 1].is_ignore()
  45. {
  46. // 忽略该信号
  47. if sig == Signal::SIGTTIN {
  48. return Err(SystemError::EIO);
  49. }
  50. } else {
  51. // 暂时使用kill而不是killpg
  52. Syscall::kill(pgid, sig as i32)?;
  53. ProcessManager::current_pcb()
  54. .flags()
  55. .insert(ProcessFlags::HAS_PENDING_SIGNAL);
  56. return Err(SystemError::ERESTARTSYS);
  57. }
  58. }
  59. Ok(())
  60. }
  61. pub fn job_ctrl_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
  62. match cmd {
  63. TtyIoctlCmd::TIOCSPGRP => {
  64. match Self::tty_check_change(tty.clone(), Signal::SIGTTOU) {
  65. Ok(_) => {}
  66. Err(e) => {
  67. if e == SystemError::EIO {
  68. return Err(SystemError::ENOTTY);
  69. }
  70. return Err(e);
  71. }
  72. };
  73. let user_reader = UserBufferReader::new(
  74. VirtAddr::new(arg).as_ptr::<i32>(),
  75. core::mem::size_of::<i32>(),
  76. true,
  77. )?;
  78. let pgrp = user_reader.read_one_from_user::<i32>(0)?;
  79. let current = ProcessManager::current_pcb();
  80. let mut ctrl = tty.core().contorl_info_irqsave();
  81. if current.sig_info_irqsave().tty().is_none()
  82. || !Arc::ptr_eq(&current.sig_info_irqsave().tty().clone().unwrap(), &tty)
  83. || ctrl.session.is_none()
  84. || ctrl.session.unwrap() != current.basic().sid()
  85. {
  86. return Err(SystemError::ENOTTY);
  87. }
  88. ctrl.pgid = Some(Pid::new(*pgrp as usize));
  89. return Ok(0);
  90. }
  91. TtyIoctlCmd::TIOCGPGRP => {
  92. let current = ProcessManager::current_pcb();
  93. if current.sig_info_irqsave().tty().is_some()
  94. && !Arc::ptr_eq(&current.sig_info_irqsave().tty().unwrap(), &tty)
  95. {
  96. return Err(SystemError::ENOTTY);
  97. }
  98. let mut user_writer = UserBufferWriter::new(
  99. VirtAddr::new(arg).as_ptr::<i32>(),
  100. core::mem::size_of::<i32>(),
  101. true,
  102. )?;
  103. user_writer.copy_one_to_user(
  104. &(tty
  105. .core()
  106. .contorl_info_irqsave()
  107. .pgid
  108. .unwrap_or(Pid::new(0))
  109. .data() as i32),
  110. 0,
  111. )?;
  112. return Ok(0);
  113. }
  114. _ => {
  115. return Err(SystemError::ENOIOCTLCMD);
  116. }
  117. }
  118. }
  119. }