feat: added the ability to send commands
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use std::{
|
||||
io::{Read, Write},
|
||||
process::{Command, Stdio},
|
||||
sync::{
|
||||
atomic::AtomicU64,
|
||||
mpsc::{channel, Sender},
|
||||
@@ -6,6 +8,8 @@ use std::{
|
||||
thread::Scope,
|
||||
};
|
||||
|
||||
use sparse_05_common::messages::Response;
|
||||
|
||||
use super::ConnectionInformation;
|
||||
|
||||
const CURRENT_COMMAND_ID: AtomicU64 = AtomicU64::new(0);
|
||||
@@ -22,8 +26,78 @@ pub(super) fn spawn_command<'a, 'b: 'a>(
|
||||
) -> anyhow::Result<CommandHandler> {
|
||||
let (data_sender, data_receiver) = channel();
|
||||
|
||||
Ok(CommandHandler {
|
||||
id: CURRENT_COMMAND_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
|
||||
data_sender,
|
||||
})
|
||||
let id = CURRENT_COMMAND_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
dbg!(&command);
|
||||
|
||||
let mut command = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&command)
|
||||
.env("TERM", "screen")
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?;
|
||||
|
||||
let resp = Response::AckRunCommand(id);
|
||||
conninfo.send(conninfo.encrypt_and_sign_resp(resp)?)?;
|
||||
|
||||
s.spawn(move || -> anyhow::Result<()> {
|
||||
if let Some(mut stdout) = command.stdout.take() {
|
||||
s.spawn(move || {
|
||||
let mut stdout_buffer = [0u8; 1024];
|
||||
|
||||
loop {
|
||||
let Ok(count) = stdout.read(&mut stdout_buffer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let resp = Response::SendStdout(stdout_buffer[..count].to_vec(), id);
|
||||
let Ok(packet) = conninfo.encrypt_and_sign_resp(resp) else {
|
||||
continue;
|
||||
};
|
||||
_ = conninfo.send(packet);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(mut stderr) = command.stderr.take() {
|
||||
s.spawn(move || {
|
||||
let mut stderr_buffer = [0u8; 1024];
|
||||
|
||||
loop {
|
||||
let Ok(count) = stderr.read(&mut stderr_buffer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let resp = Response::SendStderr(stderr_buffer[..count].to_vec(), id);
|
||||
let Ok(packet) = conninfo.encrypt_and_sign_resp(resp) else {
|
||||
continue;
|
||||
};
|
||||
_ = conninfo.send(packet);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(mut stdin) = command.stdin.take() {
|
||||
s.spawn(move || loop {
|
||||
let Ok(input): Result<Vec<u8>, _> = data_receiver.recv() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
_ = stdin.write(&input);
|
||||
});
|
||||
}
|
||||
|
||||
let code = match command.wait() {
|
||||
Ok(status) => status.code().unwrap_or(-1),
|
||||
Err(_) => -1,
|
||||
};
|
||||
let resp = Response::CommandDone(id, code);
|
||||
let resp = conninfo.encrypt_and_sign_resp(resp)?;
|
||||
conninfo.send(resp)?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
Ok(CommandHandler { id, data_sender })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user