Skip to content

Instantly share code, notes, and snippets.

@ctaggart
Created August 22, 2020 02:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ctaggart/83e63170c66850bbb8d8f0dc73cfd87a to your computer and use it in GitHub Desktop.
Save ctaggart/83e63170c66850bbb8d8f0dc73cfd87a to your computer and use it in GitHub Desktop.
cmdproxy
[package]
name = "cmdproxy"
version = "0.1.0"
authors = ["Cameron Taggart <cameron.taggart@gmail.com>"]
edition = "2018"
[dependencies]
# tokio = { version = "0.2", features = ["macros", "io-std", "io-util", "fs", "process"] }
tokio = { version = "0.2", features = ["full"] }
bytes = "*"
futures = "*"
use bytes::Bytes;
use std::process::Stdio;
use tokio::{
fs::File,
io::{self, AsyncBufReadExt, BufReader},
prelude::*,
process::Command,
sync::mpsc::{self, Receiver, Sender},
};
use futures::future::join_all;
use tokio::task::JoinHandle;
const CRLF: &[u8; 2] = &[b'\r', b'\n'];
const LF: &[u8; 1] = &[b'\n'];
pub type Error = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T> = std::result::Result<T, Error>;
#[tokio::main]
// async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn main() -> Result<()> {
let mut dbgout = File::create("cmdproxy.log").await?;
let mut child = Command::new("dotnet")
.current_dir("/Users/cameron/.autorest/@microsoft.azure_autorest.go@2.1.153/node_modules/@microsoft.azure/autorest.go")
.arg("src/bin/netcoreapp2.0/autorest.go.dll")
.arg("--server")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()?;
let stdin = io::stdin();
let mut stdin_reader = BufReader::new(stdin).lines();
let mut childin = child.stdin.take().expect("child did not have a handle to stdin");
let childout = child.stdout.take().expect("child did not have a handle to stdout");
let mut childout_reader = BufReader::new(childout).lines();
let mut stdout = io::stdout();
let (mut dbgout_tx, mut dbgout_rx): (Sender<Bytes>, Receiver<Bytes>) = mpsc::channel(128);
let mut dbgout_tx2 = dbgout_tx.clone();
let mut dbgout_tx3 = dbgout_tx.clone();
let task_child: JoinHandle<Result<()>> = tokio::spawn(async move {
let status = child.await?; //.expect("child process encountered an error");
let msg = Bytes::from(format!("exit {}", status));
dbgout_tx.send(msg).await?; //.expect("send dbgout");
Ok(())
});
let _task_dbg: JoinHandle<Result<()>> = tokio::spawn( async move {
while let Some(msg) = dbgout_rx.recv().await {
dbgout.write_all(&msg).await?;
dbgout.write_all(LF).await?;
}
Ok(())
});
// println!("stdin_reader");
// write stdin to log & childin
let task_in: JoinHandle<Result<()>> = tokio::spawn( async move {
while let Some(line) = stdin_reader.next_line().await? {
dbgout_tx2.send(Bytes::from(format!("in {}", &line))).await?;
// let line = ;
// dbgout_tx2.send(line.clone()).await?;
childin.write_all(&line.into_bytes()).await?;
childin.write_all(CRLF).await?;
}
Ok(())
});
// println!("childout_reader");
// write childout to log & stdout
let task_out: JoinHandle<Result<()>> = tokio::spawn( async move {
while let Some(line) = childout_reader.next_line().await? {
// let line = Bytes::from(line);
// dbgout_tx3.send(line.clone()).await?;
dbgout_tx3.send(Bytes::from(format!("out {}", &line))).await?;
stdout.write_all(&line.into_bytes()).await?;
stdout.write_all(CRLF).await?;
}
Ok(())
});
join_all(vec![task_child, task_in, task_out]).await;
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment