summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock10
-rw-r--r--Cargo.toml1
-rw-r--r--src/main.rs47
3 files changed, 40 insertions, 18 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ade81cc..4527a6f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -51,10 +51,20 @@ dependencies = [
]
[[package]]
+name = "nonblock"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51c7a4f22e5f2e2bd805d6ab56f1ae87eb1815673e1b452048896fb687a8a3d4"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "rustty"
version = "0.1.0"
dependencies = [
"nix",
+ "nonblock",
"vte",
]
diff --git a/Cargo.toml b/Cargo.toml
index f4b7be2..f282520 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,4 +5,5 @@ edition = "2024"
[dependencies]
nix = {default-features = false, features=["term","process","fs"], version="0.30.1"}
+nonblock = "0.2.0"
vte = "0.15.0"
diff --git a/src/main.rs b/src/main.rs
index 05fb64e..6e680f8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,14 +1,16 @@
+use nix::fcntl::{fcntl, F_GETFL, F_SETFL, OFlag};
use nix::pty::{ForkptyResult, forkpty, PtyMaster};
-use nix::unistd::read;
+use nix::unistd::{execv, read, write};
-use std::vec::Vec;
-use std::io::{self, Read, Write};
-use std::process::Command;
-use std::thread;
-use std::time::Duration;
+use nonblock::NonBlockingReader;
+
+use std::vec;
+use std::ffi::CString;
+use std::io;
use vte::{Params, Parser, Perform};
+// yoinked form vte docs
struct Performer;
impl Perform for Performer {
fn print(&mut self, c: char) {
@@ -54,25 +56,35 @@ impl Perform for Performer {
}
fn main() {
-
// TODO get rid of hard coded `sh` path
- let mut pty = spawn_pty("/home/andromeda/.nix-profile/bin/sh").unwrap();
+ let pty = spawn_pty("/home/andromeda/.nix-profile/bin/sh").unwrap();
println!("{:?}", &pty);
+ let pty_flags = fcntl(&pty, F_GETFL).unwrap();
+ fcntl(&pty, F_SETFL(OFlag::from_bits_truncate(pty_flags) | OFlag::O_NONBLOCK)).unwrap();
- let input = io::stdin();
- let mut handle = input.lock();
+ let stdin = io::stdin();
+ let mut nb_stdin = NonBlockingReader::from_fd(stdin).unwrap();
let mut statemachine = Parser::new();
let mut performer = Performer;
let mut buf = [0u8; 2048];
+ let mut vec: Vec<u8> = vec!();
- while true {
+ loop {
match read(&pty, &mut buf) {
- Ok(0) => break,
+ Ok(0) => (),
+ Ok(n) => statemachine.advance(&mut performer, &buf[..n]),
+ Err(_e) => (),
+ };
+ vec.clear();
+ match &nb_stdin.read_available(&mut vec) {
+ Ok(0) => (),
Ok(n) => {
- statemachine.advance(&mut performer, &buf[..n]);
+ let un = *n as usize;
+ buf[..un].copy_from_slice(&vec[..un]);
+ let _ = write(&pty, &buf[..un]);
},
- Err(_e) => break,
+ Err(e) => println!("error: {:?}", e),
};
};
}
@@ -82,14 +94,13 @@ fn spawn_pty(shell: &str) -> Option<PtyMaster> {
// SAFETY safe unless os out of PTYs; incredibly unlikely
match unsafe {forkpty(None, None)} {
Ok(fork_pty_res) => match fork_pty_res {
- ForkptyResult::Parent {master, ..} => {
+ ForkptyResult::Parent {child:_, master} => {
+
// SAFETY `master` is a valid PtyMaster
return Some(unsafe{PtyMaster::from_owned_fd(master)});
}
ForkptyResult::Child =>{
- Command::new(shell).spawn();
- // TODO come up with an elegant solution
- thread::sleep(Duration::MAX);
+ let _ = execv::<CString>(&CString::new(shell).unwrap(), &[]);
return None;
}
},