I'm tring to make a mini ssh interactive shell by use of ssh2 crate, here is my code:
use std::time::Duration;
use {
ssh2::Session,
std::{
io::{stdout, Read, Write},
net::TcpStream,
thread,
},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut sess = Session::new()?;
sess.set_tcp_stream(TcpStream::connect("192.168.1.6:8022")?);
sess.handshake()?;
sess.userauth_password("u0_a36", "asdw123456")?;
let mut channel = sess.channel_session()?;
let mut mode = ssh2::PtyModes::new();
mode.set_u32(ssh2::PtyModeOpcode::TTY_OP_ISPEED, 115200);
mode.set_u32(ssh2::PtyModeOpcode::TTY_OP_OSPEED, 115200);
channel.request_pty("xterm-256color", Some(mode), Some((80, 24, 0, 0)))?;
channel.shell()?;
channel.handle_extended_data(ssh2::ExtendedData::Merge)?;
sess.set_blocking(false);
let mut stream= channel.stream(0);
//open vim
channel.write(b"vim\n")?;
let stdin_thread = thread::spawn(move || {
use crossterm::event::{read, Event, KeyCode, KeyEventKind, KeyModifiers};
loop {
let mut buf = [0; 40960];
let data = {
match read().unwrap() {
Event::Key(e) if matches!(e.kind, KeyEventKind::Press) => match e.code {
KeyCode::Char(c) => match e.modifiers {
KeyModifiers::CONTROL => {
buf[0] = c as u8 - 96;
&buf[..1]
}
KeyModifiers::NONE => c.encode_utf8(&mut buf).as_bytes(),
_ => c.encode_utf8(&mut buf).as_bytes(),
},
_ => match e.code {
KeyCode::Enter => "\n",
KeyCode::Backspace => "\x08",
KeyCode::Tab => "\x09",
KeyCode::Esc => "\x1b",
KeyCode::Home => "\x1b[H",
KeyCode::End => "\x1b[F",
KeyCode::Insert => "\x1b\x5b\x32\x7e",
KeyCode::Delete => "\x1b\x5b\x33\x7e",
KeyCode::Left => "\x1b[D",
KeyCode::Up => "\x1b[A",
KeyCode::Right => "\x1b[C",
KeyCode::Down => "\x1b[B",
_ => todo!(),
}
.as_bytes(),
},
_ => continue,
}
};
stream.write_all(&data).unwrap();
stream.flush().unwrap();
}
});
let stdout_thread = thread::spawn(move || {
loop {
let mut buf = [0; 4096];
match channel.read(&mut buf) {
Ok(c) if c > 0 => {
channel.flush().unwrap();
let string = std::str::from_utf8(&buf[..c]).unwrap();
print!("{}", string);
stdout().flush().unwrap();
}
Ok(0) => break,
_ => thread::sleep(Duration::from_millis(10)),
};
}
channel.close().unwrap();
print!("Exit: {}", channel.exit_status().unwrap());
});
stdin_thread.join().unwrap();
stdout_thread.join().unwrap();
Ok(())
}
This code had a problem, after the b"vim\n"
was sent, the terminal was not correct print vim's content. Instead is print this:
[3;1R[>0;10;1c
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
[No Name] [+] 1,15 All
-- REPLACE --
How to solve this problem?