Я хочу получить доступ к терминалу, используя веб -сокет в ржавчине, я реализовал этот код, но не могу использовать Top и Nano (интерактивные команды).
Пожалуйста, помогите мне сделать это.
Я пытался использовать ящик NIX.
Код уже дает правильный выход для обычных команд LS, PWD и т. Д.
Я хочу получить доступ к терминалу, используя веб -сокет в ржавчине, я реализовал этот код, но не могу использовать Top и Nano (интерактивные команды). Пожалуйста, помогите мне сделать это. Я пытался использовать ящик NIX. Код уже дает правильный выход для обычных команд LS, PWD и т. Д.[code]use actix::{Actor, AsyncContext, StreamHandler}; use actix_web::{Error, HttpRequest}; use actix_web_actors::ws; use nix::fcntl::{FcntlArg, OFlag}; use nix::libc::{O_NONBLOCK, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO, TIOCSCTTY}; use nix::pty::openpty; use nix::sys::wait::{waitpid, WaitStatus}; use nix::unistd::{dup2, fork, setsid, ForkResult}; use std::io::{Read, Write}; use std::os::fd::IntoRawFd;
impl Actor for TerminalSession { type Context = ws::WebsocketContext; }
impl StreamHandler for TerminalSession { fn handle(&mut self, msg: Result, ctx: &mut Self::Context) { if let Ok(ws::Message::Text(command)) = msg { let mut sessions = self.store.lock().unwrap();
if let Some(current_dir) = sessions.get_mut(&self.session_id) { let pty = openpty(None, None).unwrap(); let master_fd = pty.master.into_raw_fd(); // Prevent Rust from closing it early let slave_fd = pty.slave.into_raw_fd();
// Handle Child Process Cleanup actix_rt::spawn(async move { match waitpid(child, None) { Ok(WaitStatus::Exited(_, status)) => { println!("Child process exited with status: {}", status); } Ok(WaitStatus::Signaled(_, signal, _)) => { println!("Child process terminated by signal: {:?}", signal); } Ok(_) => println!("Child process exited."), Err(e) => eprintln!("waitpid error: {}", e), } }); } Ok(ForkResult::Child) => { // Child Process: Configure PTY and Execute Command unsafe { setsid().expect("Failed to create new session"); libc::ioctl(slave_fd, TIOCSCTTY, 0); // Set PTY as controlling terminal dup2(slave_fd, STDIN_FILENO).expect("dup2 stdin failed"); dup2(slave_fd, STDOUT_FILENO).expect("dup2 stdout failed"); dup2(slave_fd, STDERR_FILENO).expect("dup2 stderr failed"); // Set PTY to Raw Mode for `nano`, `top`, etc. use nix::sys::termios::{tcsetattr, LocalFlags, SetArg, Termios}; let termios = Termios::from_fd(slave_fd).expect("Failed to get termios"); let mut new_termios = termios; new_termios .local_flags .remove(LocalFlags::ICANON | LocalFlags::ECHO); tcsetattr(slave_fd, SetArg::TCSANOW, &new_termios) .expect("Failed to set raw mode");
libc::close(slave_fd); }
std::env::set_current_dir(current_dir).unwrap_or_else(|e| { eprintln!("Failed to set current directory: {}", e); }); std::env::set_var("TERM", "xterm-256color");
let shell = CString::new("bash").unwrap(); let args = CString::new("-c").unwrap(); let command = CString::new(command.to_string()).unwrap();
/// WebSocket message handler for streaming PTY output struct WsOutput(String);
impl actix::Message for WsOutput { type Result = (); }
impl actix::Handler for TerminalSession { type Result = ();
fn handle(&mut self, msg: WsOutput, ctx: &mut Self::Context) { ctx.text(msg.0); // Send output to WebSocket client } } [/code] Я попытался ко всем возможным способам, но все еще оставался, чтобы найти решение.