summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs71
1 files changed, 40 insertions, 31 deletions
diff --git a/src/main.rs b/src/main.rs
index 95fa2b1..8a6a33b 100644
--- a/src/main.rs
+++ b/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;
}
},