fix: fixed stdin for processes
started work on upload file command
This commit is contained in:
@@ -6,13 +6,29 @@ use crate::commands::connect::shell::SparseCommands;
|
||||
pub fn print_help(arg: Option<SparseCommands>) {
|
||||
match arg {
|
||||
Some(SparseCommands::Exit) => println!(
|
||||
"Exits from the shell and disconnects from the binary"
|
||||
"exit\n\
|
||||
\n\
|
||||
Exits from the shell and disconnects from the remote server"
|
||||
),
|
||||
Some(SparseCommands::SysInfo) => println!(
|
||||
"Prints system information from the system you are connecting to"
|
||||
"#sysinfo\n\
|
||||
\n\
|
||||
Prints system information from the system you are connecting to"
|
||||
),
|
||||
Some(SparseCommands::Cd { .. }) => println!(
|
||||
"Changes the current working directory you are in"
|
||||
"cd [directory]\n\
|
||||
\n\
|
||||
Changes the current working directory you are in"
|
||||
),
|
||||
Some(SparseCommands::UploadFile { .. }) => println!(
|
||||
"#uploadfile [local file path] [remote file path]\n\
|
||||
\n\
|
||||
Uploads the file at the local file path, overwriting the file at the remote file path"
|
||||
),
|
||||
Some(SparseCommands::DownloadFile { .. }) => println!(
|
||||
"#uploadfile [local file path] [remote file path]\n\
|
||||
\n\
|
||||
Uploads the file at the local file path, overwriting the file at the remote file path"
|
||||
),
|
||||
None => println!(
|
||||
"\n{}{}\n\
|
||||
@@ -21,7 +37,7 @@ pub fn print_help(arg: Option<SparseCommands>) {
|
||||
\n\
|
||||
- #sysinfo\t\tprint information about the system you are connecting to
|
||||
- #help\t\tprints this help page, or alternatively prints info about a command passed as an argument\n\
|
||||
- #exit\t\texit from the shell and disconnect from the binary\n\
|
||||
- #exit\t\texit from the shell and disconnect from the remote server\n\
|
||||
",
|
||||
Style::new().bold().paint("SHELL COMMANDS"),
|
||||
Style::new().paint(""),
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
pub mod download;
|
||||
pub mod help;
|
||||
pub mod sysinfo;
|
||||
pub mod upload;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use crate::commands::connect::Connection;
|
||||
|
||||
pub async fn upload_file(
|
||||
conn: Arc<Connection>,
|
||||
local_path: PathBuf,
|
||||
remote_path: PathBuf,
|
||||
) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
@@ -17,7 +17,7 @@ use crate::configs::ClientConfig;
|
||||
mod commands;
|
||||
mod shell;
|
||||
|
||||
struct Connection {
|
||||
pub struct Connection {
|
||||
config: ClientConfig,
|
||||
foreign_sign_pubkey: ed25519_dalek::PublicKey,
|
||||
foreign_enc_pubkey: ecies_ed25519::PublicKey,
|
||||
@@ -26,7 +26,7 @@ struct Connection {
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
fn decrypt_and_verify(&self, data: &[u8]) -> anyhow::Result<Response> {
|
||||
pub fn decrypt_and_verify(&self, data: &[u8]) -> anyhow::Result<Response> {
|
||||
if data.len() < 65 {
|
||||
bail!("unable to parse out signature from message");
|
||||
}
|
||||
@@ -40,7 +40,7 @@ impl Connection {
|
||||
Ok(rmp_serde::from_slice(&data)?)
|
||||
}
|
||||
|
||||
fn encrypt_and_sign(&self, data: &[u8]) -> anyhow::Result<Vec<u8>> {
|
||||
pub fn encrypt_and_sign(&self, data: &[u8]) -> anyhow::Result<Vec<u8>> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let data = ecies_ed25519::encrypt(&self.foreign_enc_pubkey, data, &mut rng)?;
|
||||
|
||||
@@ -49,7 +49,7 @@ impl Connection {
|
||||
Ok([&signature.to_bytes(), &*data].concat())
|
||||
}
|
||||
|
||||
async fn send_command(&self, command: Command) -> anyhow::Result<()> {
|
||||
pub async fn send_command(&self, command: Command) -> anyhow::Result<()> {
|
||||
let cmd = rmp_serde::to_vec(&command)?;
|
||||
|
||||
self.socket
|
||||
@@ -59,7 +59,7 @@ impl Connection {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_response(&self) -> anyhow::Result<Response> {
|
||||
pub async fn get_response(&self) -> anyhow::Result<Response> {
|
||||
let mut buffer = [0u8; 2000];
|
||||
let (read, from) = self.socket.recv_from(&mut buffer).await?;
|
||||
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
use std::{
|
||||
io::{self, stdin, Read, Stdin, Write},
|
||||
io::{self, Read, Write},
|
||||
os::fd::AsRawFd,
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
mpsc::{channel, TryRecvError},
|
||||
Arc,
|
||||
},
|
||||
sync::Arc,
|
||||
thread::{self, scope},
|
||||
};
|
||||
|
||||
use sparse_05_common::messages::{Capabilities, Command, Response};
|
||||
use structopt::StructOpt;
|
||||
use tokio::{
|
||||
io::{stderr, stdout, AsyncWriteExt},
|
||||
io::{stderr, stdout, AsyncReadExt, AsyncWriteExt},
|
||||
runtime::Handle,
|
||||
sync::mpsc,
|
||||
sync::mpsc::{channel, Receiver},
|
||||
};
|
||||
|
||||
use super::{commands, Connection};
|
||||
@@ -29,6 +26,16 @@ pub enum SparseCommands {
|
||||
Cd {
|
||||
folder: PathBuf,
|
||||
},
|
||||
#[structopt(name = "#upload")]
|
||||
UploadFile {
|
||||
local_file: PathBuf,
|
||||
remote_path: PathBuf,
|
||||
},
|
||||
#[structopt(name = "#download")]
|
||||
DownloadFile {
|
||||
remote_file: PathBuf,
|
||||
local_path: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
macro_rules! libc_try {
|
||||
@@ -58,7 +65,11 @@ fn convert_termios_raw(attrs: &mut libc::termios) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run_command(command: String, connection: Arc<Connection>) -> anyhow::Result<()> {
|
||||
async fn run_command(
|
||||
stdin: &mut Receiver<Vec<u8>>,
|
||||
command: String,
|
||||
connection: Arc<Connection>,
|
||||
) -> anyhow::Result<()> {
|
||||
connection
|
||||
.send_command(Command::RunCommand(command))
|
||||
.await?;
|
||||
@@ -70,38 +81,6 @@ async fn run_command(command: String, connection: Arc<Connection>) -> anyhow::Re
|
||||
}
|
||||
};
|
||||
|
||||
let (kill, handle_kill) = channel();
|
||||
let (send_message, mut handle_send_message) = mpsc::channel(16);
|
||||
let handle = Handle::current();
|
||||
|
||||
let stdin_thread = thread::spawn({
|
||||
let mut stdin = stdin();
|
||||
let connection = Arc::clone(&connection);
|
||||
|
||||
move || {
|
||||
let mut stdin_buffer = [0u8; 1024];
|
||||
|
||||
loop {
|
||||
let Ok(amount) = stdin.read(&mut stdin_buffer) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
handle.spawn({
|
||||
let message = stdin_buffer[..amount].to_vec();
|
||||
let send_message = send_message.clone();
|
||||
async move { send_message.send(message).await }
|
||||
});
|
||||
|
||||
match handle_kill.try_recv() {
|
||||
Ok(()) | Err(TryRecvError::Disconnected) => {
|
||||
break;
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
loop {
|
||||
enum Event {
|
||||
Stdin(Vec<u8>),
|
||||
@@ -110,7 +89,7 @@ async fn run_command(command: String, connection: Arc<Connection>) -> anyhow::Re
|
||||
|
||||
let Some(event) = tokio::select! {
|
||||
v = connection.get_response() => v.ok().map(Event::Remote),
|
||||
v = handle_send_message.recv() => v.map(Event::Stdin)
|
||||
v = stdin.recv() => v.map(Event::Stdin)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
@@ -122,8 +101,9 @@ async fn run_command(command: String, connection: Arc<Connection>) -> anyhow::Re
|
||||
Event::Remote(Response::SendStderr(bytes, cid)) if cid == id => {
|
||||
stderr().write(&bytes).await?;
|
||||
}
|
||||
Event::Remote(Response::CommandDone(cid, code)) if cid == id => break,
|
||||
Event::Remote(Response::CommandDone(cid, _)) if cid == id => break,
|
||||
Event::Stdin(stdin) => {
|
||||
println!("here");
|
||||
let _ = connection
|
||||
.send_command(Command::SendStdin(stdin, id))
|
||||
.await?;
|
||||
@@ -132,20 +112,17 @@ async fn run_command(command: String, connection: Arc<Connection>) -> anyhow::Re
|
||||
}
|
||||
}
|
||||
|
||||
let _ = kill.send(());
|
||||
let _ = stdin_thread.join();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) async fn shell(
|
||||
connection: Arc<Connection>,
|
||||
mut capabilities: Capabilities,
|
||||
capabilities: Capabilities,
|
||||
) -> anyhow::Result<()> {
|
||||
println!("Source code available at https://github.com/r-a303931/sparse (feel free to give it a star!)");
|
||||
println!("Type #help to view a list of sparse commands\n");
|
||||
|
||||
let mut stdin = io::stdin();
|
||||
let mut stdin = tokio::io::stdin();
|
||||
let mut stdout = io::stdout();
|
||||
let backup_term_attrs = get_term_attrs(&stdin)?;
|
||||
let mut raw_term_attrs = get_term_attrs(&stdin)?;
|
||||
@@ -153,6 +130,24 @@ pub(super) async fn shell(
|
||||
|
||||
let mut cwd = "/".to_string();
|
||||
|
||||
let (stdin_sender, mut stdin_receiver) = channel(64);
|
||||
|
||||
let handle = Handle::current();
|
||||
thread::spawn(move || {
|
||||
let mut stdin_buf = [0u8; 1024];
|
||||
loop {
|
||||
let mut stdin = std::io::stdin();
|
||||
let Ok(amount) = stdin.read(&mut stdin_buf) else {
|
||||
continue;
|
||||
};
|
||||
let stdin_buf = stdin_buf[..amount].to_vec();
|
||||
let stdin_sender = stdin_sender.clone();
|
||||
handle.spawn(async move {
|
||||
_ = stdin_sender.send(stdin_buf).await;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
loop {
|
||||
print!(
|
||||
"{}@{}:{} {} ",
|
||||
@@ -166,14 +161,15 @@ pub(super) async fn shell(
|
||||
);
|
||||
stdout.flush().unwrap();
|
||||
|
||||
let mut cmd = [0u8; 1024];
|
||||
let amount = stdin.read(&mut cmd)?;
|
||||
let Some(cmd) = stdin_receiver.recv().await else {
|
||||
break;
|
||||
};
|
||||
|
||||
if amount == 0 {
|
||||
if cmd.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let Ok(input) = std::str::from_utf8(&cmd[..amount]) else {
|
||||
let Ok(input) = std::str::from_utf8(&cmd) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -198,8 +194,28 @@ pub(super) async fn shell(
|
||||
(Ok(SparseCommands::Exit), _) => {
|
||||
break;
|
||||
}
|
||||
(
|
||||
Ok(SparseCommands::UploadFile {
|
||||
local_file,
|
||||
remote_path,
|
||||
}),
|
||||
_,
|
||||
) => {
|
||||
if let Err(e) =
|
||||
commands::upload::upload_file(Arc::clone(&connection), local_file, remote_path)
|
||||
.await
|
||||
{
|
||||
eprintln!("{e:?}")
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Err(e) = run_command(input.to_string(), Arc::clone(&connection)).await {
|
||||
if let Err(e) = run_command(
|
||||
&mut stdin_receiver,
|
||||
input.to_string(),
|
||||
Arc::clone(&connection),
|
||||
)
|
||||
.await
|
||||
{
|
||||
eprintln!("{e:?}");
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user