nonblocking, good stuff w/ vte :)
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -50,11 +50,21 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nonblock"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51c7a4f22e5f2e2bd805d6ab56f1ae87eb1815673e1b452048896fb687a8a3d4"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustty"
|
name = "rustty"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix",
|
"nix",
|
||||||
|
"nonblock",
|
||||||
"vte",
|
"vte",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nix = {default-features = false, features=["term","process","fs"], version="0.30.1"}
|
nix = {default-features = false, features=["term","process","fs"], version="0.30.1"}
|
||||||
|
nonblock = "0.2.0"
|
||||||
vte = "0.15.0"
|
vte = "0.15.0"
|
||||||
|
|||||||
47
src/main.rs
47
src/main.rs
@@ -1,14 +1,16 @@
|
|||||||
|
use nix::fcntl::{fcntl, F_GETFL, F_SETFL, OFlag};
|
||||||
use nix::pty::{ForkptyResult, forkpty, PtyMaster};
|
use nix::pty::{ForkptyResult, forkpty, PtyMaster};
|
||||||
use nix::unistd::read;
|
use nix::unistd::{execv, read, write};
|
||||||
|
|
||||||
use std::vec::Vec;
|
use nonblock::NonBlockingReader;
|
||||||
use std::io::{self, Read, Write};
|
|
||||||
use std::process::Command;
|
use std::vec;
|
||||||
use std::thread;
|
use std::ffi::CString;
|
||||||
use std::time::Duration;
|
use std::io;
|
||||||
|
|
||||||
use vte::{Params, Parser, Perform};
|
use vte::{Params, Parser, Perform};
|
||||||
|
|
||||||
|
// yoinked form vte docs
|
||||||
struct Performer;
|
struct Performer;
|
||||||
impl Perform for Performer {
|
impl Perform for Performer {
|
||||||
fn print(&mut self, c: char) {
|
fn print(&mut self, c: char) {
|
||||||
@@ -54,25 +56,35 @@ impl Perform for Performer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
// TODO get rid of hard coded `sh` path
|
// 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);
|
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 stdin = io::stdin();
|
||||||
let mut handle = input.lock();
|
let mut nb_stdin = NonBlockingReader::from_fd(stdin).unwrap();
|
||||||
|
|
||||||
let mut statemachine = Parser::new();
|
let mut statemachine = Parser::new();
|
||||||
let mut performer = Performer;
|
let mut performer = Performer;
|
||||||
let mut buf = [0u8; 2048];
|
let mut buf = [0u8; 2048];
|
||||||
|
let mut vec: Vec<u8> = vec!();
|
||||||
|
|
||||||
while true {
|
loop {
|
||||||
match read(&pty, &mut buf) {
|
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) => {
|
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
|
// SAFETY safe unless os out of PTYs; incredibly unlikely
|
||||||
match unsafe {forkpty(None, None)} {
|
match unsafe {forkpty(None, None)} {
|
||||||
Ok(fork_pty_res) => match fork_pty_res {
|
Ok(fork_pty_res) => match fork_pty_res {
|
||||||
ForkptyResult::Parent {master, ..} => {
|
ForkptyResult::Parent {child:_, master} => {
|
||||||
|
|
||||||
// SAFETY `master` is a valid PtyMaster
|
// SAFETY `master` is a valid PtyMaster
|
||||||
return Some(unsafe{PtyMaster::from_owned_fd(master)});
|
return Some(unsafe{PtyMaster::from_owned_fd(master)});
|
||||||
}
|
}
|
||||||
ForkptyResult::Child =>{
|
ForkptyResult::Child =>{
|
||||||
Command::new(shell).spawn();
|
let _ = execv::<CString>(&CString::new(shell).unwrap(), &[]);
|
||||||
// TODO come up with an elegant solution
|
|
||||||
thread::sleep(Duration::MAX);
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user