fmt, use waitpid to exit
This commit is contained in:
71
src/main.rs
71
src/main.rs
@@ -1,6 +1,7 @@
|
||||
use nix::fcntl::{fcntl, OFlag, F_GETFL, F_SETFL};
|
||||
use nix::pty::{forkpty, ForkptyResult, PtyMaster};
|
||||
use nix::unistd::{execve, read, write};
|
||||
use nix::fcntl::{F_GETFL, F_SETFL, OFlag, fcntl};
|
||||
use nix::pty::{ForkptyResult, PtyMaster, forkpty};
|
||||
use nix::sys::wait::{WaitPidFlag, WaitStatus, waitpid};
|
||||
use nix::unistd::{Pid, execve, read, write};
|
||||
|
||||
use minifb::{Key, KeyRepeat, Window, WindowOptions};
|
||||
|
||||
@@ -74,20 +75,20 @@ impl Perform for Model {
|
||||
// draw a character to the screen and update states
|
||||
fn print(&mut self, c: char) {
|
||||
if self.cursor.col < self.buffer.width {
|
||||
// scrolls
|
||||
while self.cursor.row >= self.buffer.height {
|
||||
for row in 0..(self.buffer.height - 1) {
|
||||
// scrolls
|
||||
while self.cursor.row >= self.buffer.height {
|
||||
for row in 0..(self.buffer.height - 1) {
|
||||
for col in 0..self.buffer.width {
|
||||
self.buffer.set(col, row, self.buffer.get(col, row + 1));
|
||||
}
|
||||
}
|
||||
for col in 0..self.buffer.width {
|
||||
self.buffer.set(col, row, self.buffer.get(col, row + 1));
|
||||
};
|
||||
};
|
||||
for col in 0..self.buffer.width {
|
||||
self.buffer.set(col, self.buffer.height - 1, None);
|
||||
self.buffer.set(col, self.buffer.height - 1, None);
|
||||
}
|
||||
self.cursor.row -= 1;
|
||||
}
|
||||
self.cursor.row -= 1;
|
||||
};
|
||||
self.buffer.set(self.cursor.col, self.cursor.row, Some(c));
|
||||
self.cursor.col += 1;
|
||||
self.buffer.set(self.cursor.col, self.cursor.row, Some(c));
|
||||
self.cursor.col += 1;
|
||||
}
|
||||
println!("[print] {:?}", c);
|
||||
}
|
||||
@@ -100,7 +101,7 @@ impl Perform for Model {
|
||||
0x08 => {
|
||||
self.cursor.col = self.cursor.col - 1;
|
||||
self.buffer.set(self.cursor.col, self.cursor.row, None);
|
||||
},
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
println!("[execute] {:02x}", byte);
|
||||
@@ -193,7 +194,7 @@ fn main() {
|
||||
|
||||
// initialize window and its buffer
|
||||
let mut window = Window::new(
|
||||
"rust-term",
|
||||
"rustty",
|
||||
model.screenbuffer.width,
|
||||
model.screenbuffer.height,
|
||||
WindowOptions::default(),
|
||||
@@ -201,7 +202,7 @@ fn main() {
|
||||
.unwrap();
|
||||
window.set_target_fps(60);
|
||||
|
||||
let pty = spawn_pty().unwrap();
|
||||
let (pty, child) = spawn_pty().unwrap();
|
||||
fcntl(
|
||||
&pty,
|
||||
F_SETFL(OFlag::from_bits_truncate(fcntl(&pty, F_GETFL).unwrap()) | OFlag::O_NONBLOCK),
|
||||
@@ -211,7 +212,10 @@ fn main() {
|
||||
let mut statemachine = Parser::new();
|
||||
|
||||
let mut buf = [0u8; 2048];
|
||||
while window.is_open() && !window.is_key_down(Key::Escape) {
|
||||
while window.is_open()
|
||||
&& !window.is_key_down(Key::Escape)
|
||||
&& waitpid(child, Some(WaitPidFlag::WNOHANG)) == Ok(WaitStatus::StillAlive)
|
||||
{
|
||||
// mask to render into
|
||||
let mut mask = vec![0u8; model.screenbuffer.width * model.screenbuffer.height];
|
||||
|
||||
@@ -260,17 +264,20 @@ fn main() {
|
||||
};
|
||||
|
||||
let keys = window.get_keys_pressed(KeyRepeat::Yes);
|
||||
let shift = window.is_key_down(Key::LeftShift) || window.is_key_down(Key::RightShift) || window.is_key_down(Key::CapsLock);
|
||||
let shift = window.is_key_down(Key::LeftShift)
|
||||
|| window.is_key_down(Key::RightShift)
|
||||
|| window.is_key_down(Key::CapsLock);
|
||||
let ctrl = window.is_key_down(Key::LeftCtrl) || window.is_key_down(Key::RightCtrl);
|
||||
if !keys.is_empty() {
|
||||
let bytes: Vec<u8> = keys
|
||||
.iter()
|
||||
// TODO apply modifiers
|
||||
.map(|key| key_to_u8(
|
||||
.map(|key| {
|
||||
key_to_u8(
|
||||
*key, // key
|
||||
shift,
|
||||
ctrl
|
||||
))
|
||||
shift, ctrl,
|
||||
)
|
||||
})
|
||||
.filter(|v| *v != 0u8)
|
||||
.collect();
|
||||
write(&pty, bytes.as_slice());
|
||||
@@ -279,24 +286,26 @@ fn main() {
|
||||
}
|
||||
|
||||
// forks a new pty and returns file descriptor of the master
|
||||
fn spawn_pty() -> Option<PtyMaster> {
|
||||
fn spawn_pty() -> Option<(PtyMaster, Pid)> {
|
||||
// SAFETY safe unless os out of PTYs; incredibly unlikely
|
||||
match unsafe { forkpty(None, None) } {
|
||||
Ok(fork_pty_res) => match fork_pty_res {
|
||||
ForkptyResult::Parent { child: _, master } => {
|
||||
ForkptyResult::Parent { child, master } => {
|
||||
// SAFETY `master` is a valid PtyMaster
|
||||
return Some(unsafe { PtyMaster::from_owned_fd(master) });
|
||||
return Some((unsafe { PtyMaster::from_owned_fd(master) }, child));
|
||||
}
|
||||
ForkptyResult::Child => {
|
||||
let _ = execve::<CString, CString>(
|
||||
&CString::new("/usr/bin/env").unwrap(),
|
||||
&[ CString::new("/usr/bin/env").unwrap(),
|
||||
&[
|
||||
CString::new("/usr/bin/env").unwrap(),
|
||||
CString::new("-i").unwrap(),
|
||||
CString::new("sh").unwrap(),
|
||||
CString::new("--norc").unwrap(),
|
||||
CString::new("--noprofile").unwrap() ],
|
||||
&[ CString::new("TERM=dumb").unwrap() ],
|
||||
);
|
||||
CString::new("--noprofile").unwrap(),
|
||||
],
|
||||
&[CString::new("TERM=dumb").unwrap()],
|
||||
);
|
||||
return None;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user