| 124 | |
| 125 | impl SerialManager { |
| 126 | pub fn new( |
| 127 | #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] serial: Arc<Mutex<Serial>>, |
| 128 | #[cfg(target_arch = "aarch64")] serial: Arc<Mutex<Pl011>>, |
| 129 | mut transport: ConsoleTransport, |
| 130 | socket: Option<PathBuf>, |
| 131 | ) -> Result<Option<Self>> { |
| 132 | let epoll_fd = epoll::create(true).map_err(Error::Epoll)?; |
| 133 | let kill_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFd)?; |
| 134 | |
| 135 | epoll::ctl( |
| 136 | epoll_fd, |
| 137 | epoll::ControlOptions::EPOLL_CTL_ADD, |
| 138 | kill_evt.as_raw_fd(), |
| 139 | epoll::Event::new(epoll::Events::EPOLLIN, EpollDispatch::Kill as u64), |
| 140 | ) |
| 141 | .map_err(Error::Epoll)?; |
| 142 | |
| 143 | let mut socket_path: Option<PathBuf> = None; |
| 144 | |
| 145 | let in_fd = match transport { |
| 146 | ConsoleTransport::Pty(ref fd) => fd.as_raw_fd(), |
| 147 | ConsoleTransport::Tty(_) |
| 148 | // If running on an interactive TTY then accept input |
| 149 | // SAFETY: trivially safe |
| 150 | if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } => |
| 151 | { |
| 152 | // SAFETY: STDIN_FILENO is a valid fd |
| 153 | let fd = unsafe { libc::dup(libc::STDIN_FILENO) }; |
| 154 | if fd == -1 { |
| 155 | return Err(Error::DupFd(std::io::Error::last_os_error())); |
| 156 | } |
| 157 | // SAFETY: fd is valid and owned by us |
| 158 | let stdin_clone = unsafe { File::from_raw_fd(fd) }; |
| 159 | // SAFETY: FFI calls with correct arguments |
| 160 | let ret = unsafe { |
| 161 | let mut flags = libc::fcntl(stdin_clone.as_raw_fd(), libc::F_GETFL); |
| 162 | flags |= libc::O_NONBLOCK; |
| 163 | libc::fcntl(stdin_clone.as_raw_fd(), libc::F_SETFL, flags) |
| 164 | }; |
| 165 | |
| 166 | if ret < 0 { |
| 167 | return Err(Error::SetNonBlocking(std::io::Error::last_os_error())); |
| 168 | } |
| 169 | |
| 170 | transport = ConsoleTransport::Tty(Arc::new(stdin_clone)); |
| 171 | fd |
| 172 | } |
| 173 | ConsoleTransport::Tty(_) => { |
| 174 | return Ok(None); |
| 175 | } |
| 176 | ConsoleTransport::Socket(ref listener) => { |
| 177 | if let Some(path_in_socket) = socket { |
| 178 | socket_path = Some(path_in_socket.clone()); |
| 179 | } |
| 180 | listener.as_raw_fd() |
| 181 | } |
| 182 | _ => return Ok(None), |
| 183 | }; |