From c1afd3f33e61092057c8a8bcd77ccc87cb407d78 Mon Sep 17 00:00:00 2001 From: stjet <49297268+stjet@users.noreply.github.com> Date: Wed, 30 Apr 2025 04:50:11 +0000 Subject: [PATCH] inhouse pty --- Cargo.toml | 6 +-- bmps/nimbus-romono/{-8.bmp => -6.bmp} | Bin bmps/nimbus-romono/{<2.bmp => <3.bmp} | Bin bmps/nimbus-romono/{>2.bmp => >3.bmp} | Bin docs/philosophy.md | 9 ++++- docs/system/integration.md | 3 ++ {wm/linux => linux}/Cargo.toml | 0 {wm/linux => linux}/src/fb.rs | 0 {wm/linux => linux}/src/keys.rs | 0 {wm/linux => linux}/src/lib.rs | 1 + linux/src/pty.rs | 55 ++++++++++++++++++++++++++ {wm/linux => linux}/src/raw.rs | 0 src/bin/terminal.rs | 15 ++++--- src/bin/wm.rs | 6 +-- wm/Cargo.toml | 2 +- 15 files changed, 82 insertions(+), 15 deletions(-) rename bmps/nimbus-romono/{-8.bmp => -6.bmp} (100%) rename bmps/nimbus-romono/{<2.bmp => <3.bmp} (100%) rename bmps/nimbus-romono/{>2.bmp => >3.bmp} (100%) create mode 100644 docs/system/integration.md rename {wm/linux => linux}/Cargo.toml (100%) rename {wm/linux => linux}/src/fb.rs (100%) rename {wm/linux => linux}/src/keys.rs (100%) rename {wm/linux => linux}/src/lib.rs (75%) create mode 100644 linux/src/pty.rs rename {wm/linux => linux}/src/raw.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index fea1aeb..51518bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ default-run = "ming" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members = [ "wm", "wm/linux" ] +members = [ "wm", "linux" ] [build-dependencies] bmp-rust = "0.5.0" @@ -18,16 +18,16 @@ bitcoin_hashes = { version = "0.16.0", default-features = false } [dependencies] ming-wm-lib = { path = "ming-wm-lib" } wm = { path = "wm", optional = true } +linux = { path = "linux", optional = true } rodio = { version = "0.19.0", default-features = false, features = [ "flac", "mp3", "symphonia-vorbis", "wav" ], optional = true } rand = { version = "0.9.0", default-features = false, features = [ "small_rng" ], optional = true } id3 = { version = "1.10.0", optional = true } mp4ameta = { version = "0.11.0", optional = true } metaflac = { version = "0.2.5", optional = true } -pty-process = { version = "0.5.1", optional = true } [features] default = [ "wm", "terminal" ] -terminal = [ "pty-process" ] +terminal = [ "linux" ] audio_player = [ "id3", "mp4ameta", "metaflac", "rand", "rodio" ] [profile.release] diff --git a/bmps/nimbus-romono/-8.bmp b/bmps/nimbus-romono/-6.bmp similarity index 100% rename from bmps/nimbus-romono/-8.bmp rename to bmps/nimbus-romono/-6.bmp diff --git a/bmps/nimbus-romono/<2.bmp b/bmps/nimbus-romono/<3.bmp similarity index 100% rename from bmps/nimbus-romono/<2.bmp rename to bmps/nimbus-romono/<3.bmp diff --git a/bmps/nimbus-romono/>2.bmp b/bmps/nimbus-romono/>3.bmp similarity index 100% rename from bmps/nimbus-romono/>2.bmp rename to bmps/nimbus-romono/>3.bmp diff --git a/docs/philosophy.md b/docs/philosophy.md index f7d9d5e..2534d37 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -69,5 +69,10 @@ More often than not, not relying on dependencies removes unnecessary bloat and c Expect to see more dependencies in Cargo.toml eliminated soon. PS: -1. `rodio` is unlikely to ever be eliminated (simply because audio is *complex*), and it's optional (if the audio player is not wanted) -2.`bmp-rust` is written by me and so isn't technically an external dependency +1. `rodio` is unlikely to ever be eliminated (simply because audio is *complex*), and it's optional (if the audio player is not wanted). The dependency which provides hashing will also not be removed as I am not a cryptographer and not (quite) stupid enough to pretend being one +2. `bmp-rust` is written by me and so isn't technically an external dependency + +> ### Update +> Ignoring the audio player dependencies and `bmp-rust`, the only dependencies not written by me are now `libc` for libc Rust bindings and `bitcoin-hashes` for SHA-512 password hashing (yes, I know SHA-512 is not the greatest password hash function, but it is lightweight, relatively). +> +> Prior dependencies like `termion`, `linux_framebuffer`, `pty-process`, have been removed and replaced by a me-written version in the `linux` crate. As of v1.1, the dependency removing goal has been achieved. Huzzah! diff --git a/docs/system/integration.md b/docs/system/integration.md new file mode 100644 index 0000000..e9a2119 --- /dev/null +++ b/docs/system/integration.md @@ -0,0 +1,3 @@ +## Launch on Login + +To launch on user login, simply add `ming` as the last line of `~/.profile`. This should work for most shells. diff --git a/wm/linux/Cargo.toml b/linux/Cargo.toml similarity index 100% rename from wm/linux/Cargo.toml rename to linux/Cargo.toml diff --git a/wm/linux/src/fb.rs b/linux/src/fb.rs similarity index 100% rename from wm/linux/src/fb.rs rename to linux/src/fb.rs diff --git a/wm/linux/src/keys.rs b/linux/src/keys.rs similarity index 100% rename from wm/linux/src/keys.rs rename to linux/src/keys.rs diff --git a/wm/linux/src/lib.rs b/linux/src/lib.rs similarity index 75% rename from wm/linux/src/lib.rs rename to linux/src/lib.rs index 83eaee7..45ae7c0 100644 --- a/wm/linux/src/lib.rs +++ b/linux/src/lib.rs @@ -1,3 +1,4 @@ pub mod fb; pub mod raw; pub mod keys; +pub mod pty; diff --git a/linux/src/pty.rs b/linux/src/pty.rs new file mode 100644 index 0000000..922f8a4 --- /dev/null +++ b/linux/src/pty.rs @@ -0,0 +1,55 @@ +use std::ptr; +use std::process::{ Command, Child }; +use std::fs::File; +use std::os::fd::{ OwnedFd, FromRawFd }; + +use libc::openpty; + +//basically the master and slave are linked? slave behaves just like normal terminal +//I don't totally get it, I guess just attach the command's stdout and stderr to ptyslave for reading? + +pub struct PtyMaster { + pub file: File, +} + +impl PtyMaster { + pub fn new(fd: OwnedFd) -> Self { + Self { + file: File::from(fd), + } + } +} + +pub struct PtySlave { + pub file: File, + fd: OwnedFd, +} + +impl PtySlave { + pub fn new(fd: OwnedFd) -> Self { + Self { + file: File::from(fd.try_clone().unwrap()), + fd, + } + } + + //assume stdin is piped + pub fn attach_and_spawn(&self, command: &mut Command) -> std::io::Result { + command.stdout(self.fd.try_clone().unwrap()); + command.stderr(self.fd.try_clone().unwrap()); + command.spawn() + } +} + +pub fn open_pty() -> Result<(PtyMaster, PtySlave), ()> { + let mut master_fd = 0; + let mut slave_fd = 0; + let result = unsafe { openpty(&mut master_fd, &mut slave_fd, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()) }; + if result == -1 { + Err(()) + } else { + let master_fd = unsafe { OwnedFd::from_raw_fd(master_fd) }; + let slave_fd = unsafe { OwnedFd::from_raw_fd(slave_fd) }; + Ok((PtyMaster::new(master_fd), PtySlave::new(slave_fd))) + } +} diff --git a/wm/linux/src/raw.rs b/linux/src/raw.rs similarity index 100% rename from wm/linux/src/raw.rs rename to linux/src/raw.rs diff --git a/src/bin/terminal.rs b/src/bin/terminal.rs index 4a79753..2e27db1 100644 --- a/src/bin/terminal.rs +++ b/src/bin/terminal.rs @@ -3,12 +3,13 @@ use std::vec; use std::sync::mpsc::{ channel, Receiver, Sender }; use std::thread; use std::process::{ Child, Stdio }; +use std::process::Command; use std::io::{ Read, Write }; use std::time::Duration; use std::path::PathBuf; use std::fmt; -use pty_process::blocking; +use linux::pty::open_pty; use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType }; use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType }; @@ -160,8 +161,8 @@ impl WindowLike for Terminal { //for now, ignore // } else if char::from(ci) == '\t' { - //for now, ignore - // + //for now, interpret as space + self.process_current_line.push(b' '); } else { self.process_current_line.push(ci); } @@ -358,11 +359,13 @@ impl Terminal { } Mode::Input } else { - let (pty, pts) = blocking::open().unwrap(); - self.running_process = Some(blocking::Command::new("sh").arg("-c").arg(&self.current_input).current_dir(&self.current_path).stdin(Stdio::piped()).spawn(pts).unwrap()); + let (pty, pts) = open_pty().unwrap(); + let mut cmd = Command::new("sh"); + let cmd = cmd.arg("-c").arg(&self.current_input).current_dir(&self.current_path).stdin(Stdio::piped()); + self.running_process = Some(pts.attach_and_spawn(cmd).unwrap()); let (tx1, rx1) = channel(); thread::spawn(move || { - for ci in pty.bytes() { + for ci in pty.file.bytes() { if let Ok(ci) = ci { tx1.send(ci).unwrap(); } else { diff --git a/src/bin/wm.rs b/src/bin/wm.rs index 4327cdc..d12c63b 100644 --- a/src/bin/wm.rs +++ b/src/bin/wm.rs @@ -6,9 +6,9 @@ use std::io::{ stdin, stdout, BufReader, BufRead, Write }; use std::process::exit; use std::env; -use wm::linux::fb::Framebuffer; -use wm::linux::raw::RawStdout; -use wm::linux::keys::{ RawStdin, Key }; +use linux::fb::Framebuffer; +use linux::raw::RawStdout; +use linux::keys::{ RawStdin, Key }; use wm::framebuffer::{ FramebufferWriter, FramebufferInfo }; use wm::window_manager::WindowManager; diff --git a/wm/Cargo.toml b/wm/Cargo.toml index 97a13d9..c5a1f46 100644 --- a/wm/Cargo.toml +++ b/wm/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" [dependencies] ming-wm-lib = { path = "../ming-wm-lib" } -linux = { path = "linux" } +linux = { path = "../linux" } bitcoin_hashes = { version = "0.16.0", default-features = false } bmp-rust = "0.5.0"