2021-10-16 23:11:50 +00:00
|
|
|
|
|
|
|
use std::thread;
|
2021-10-23 02:36:05 +00:00
|
|
|
use std::sync::mpsc;
|
2021-10-16 23:11:50 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
use std::io::{Read, Write};
|
2021-12-13 20:00:24 +00:00
|
|
|
use std::os::unix::io::AsRawFd;
|
2021-10-16 23:11:50 +00:00
|
|
|
|
|
|
|
use nix::fcntl::OFlag;
|
|
|
|
use nix::pty::{self, PtyMaster};
|
|
|
|
use nix::fcntl::{fcntl, FcntlArg};
|
|
|
|
|
2021-12-07 03:52:04 +00:00
|
|
|
use moa::error::Error;
|
|
|
|
use moa::host::traits::Tty;
|
2021-10-16 23:11:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
pub struct SimplePty {
|
|
|
|
pub name: String,
|
2021-10-23 02:36:05 +00:00
|
|
|
input: mpsc::Receiver<u8>,
|
|
|
|
output: mpsc::Sender<u8>,
|
2021-10-16 23:11:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SimplePty {
|
2021-10-23 02:36:05 +00:00
|
|
|
pub fn new(name: String, input: mpsc::Receiver<u8>, output: mpsc::Sender<u8>) -> SimplePty {
|
|
|
|
SimplePty {
|
2021-10-16 23:11:50 +00:00
|
|
|
name,
|
2021-10-23 02:36:05 +00:00
|
|
|
input,
|
|
|
|
output,
|
|
|
|
}
|
2021-10-16 23:11:50 +00:00
|
|
|
}
|
|
|
|
|
2021-10-23 02:36:05 +00:00
|
|
|
pub fn open() -> Result<SimplePty, Error> {
|
2021-10-16 23:11:50 +00:00
|
|
|
let pty = pty::posix_openpt(OFlag::O_RDWR).and_then(|pty| {
|
|
|
|
pty::grantpt(&pty)?;
|
|
|
|
pty::unlockpt(&pty)?;
|
|
|
|
Ok(pty)
|
|
|
|
}).map_err(|_| Error::new("Error opening new pseudoterminal"))?;
|
|
|
|
|
|
|
|
let name = unsafe { pty::ptsname(&pty).map_err(|_| Error::new("Unable to get pty name"))? };
|
2021-10-23 02:36:05 +00:00
|
|
|
let (input_tx, input_rx) = mpsc::channel();
|
|
|
|
let (output_tx, output_rx) = mpsc::channel();
|
|
|
|
let shared = SimplePty::new(name.clone(), input_rx, output_tx);
|
2021-10-16 23:11:50 +00:00
|
|
|
|
2021-10-23 02:36:05 +00:00
|
|
|
SimplePty::spawn_poller(pty, name, input_tx, output_rx);
|
|
|
|
Ok(shared)
|
2021-10-16 23:11:50 +00:00
|
|
|
}
|
|
|
|
|
2021-10-23 02:36:05 +00:00
|
|
|
fn spawn_poller(mut pty: PtyMaster, name: String, input_tx: mpsc::Sender<u8>, output_rx: mpsc::Receiver<u8>) {
|
2021-10-16 23:11:50 +00:00
|
|
|
thread::spawn(move || {
|
2021-10-23 02:36:05 +00:00
|
|
|
println!("pty: spawned reader for {}", name);
|
|
|
|
|
|
|
|
fcntl(pty.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).unwrap();
|
2021-10-16 23:11:50 +00:00
|
|
|
|
|
|
|
let mut buf = [0; 1];
|
|
|
|
loop {
|
2021-10-23 02:36:05 +00:00
|
|
|
match pty.read(&mut buf) {
|
|
|
|
Ok(_) => {
|
2021-11-13 19:39:20 +00:00
|
|
|
input_tx.send(buf[0]).unwrap();
|
2021-10-23 02:36:05 +00:00
|
|
|
},
|
|
|
|
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { },
|
|
|
|
Err(err) => { println!("ERROR: {:?}", err); }
|
|
|
|
}
|
|
|
|
|
|
|
|
while let Ok(data) = output_rx.try_recv() {
|
|
|
|
pty.write_all(&[data]).unwrap();
|
2021-10-16 23:11:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
thread::sleep(Duration::from_millis(10));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-23 02:36:05 +00:00
|
|
|
impl Tty for SimplePty {
|
|
|
|
fn device_name(&self) -> String {
|
|
|
|
self.name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read(&mut self) -> Option<u8> {
|
|
|
|
match self.input.try_recv() {
|
|
|
|
Ok(data) => Some(data),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write(&mut self, output: u8) -> bool {
|
2021-11-13 19:39:20 +00:00
|
|
|
self.output.send(output).unwrap();
|
2021-10-23 02:36:05 +00:00
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|