From 6ff33d83fa3360b3dd0ca36470ae6217158fb999 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Fri, 9 Sep 2022 22:32:00 +0400 Subject: [PATCH] Move spawn to Rust --- Makefile | 8 +- config/2-conditionals-bsd.mk | 6 ++ config/2-conditionals-gnu.mk | 6 ++ rust-polytreewm/Cargo.toml | 12 +++ rust-polytreewm/src/api/mod.rs | 1 + rust-polytreewm/src/api/spawn.rs | 35 +++++++ rust-polytreewm/src/lib.rs | 1 + rust-polytreewm/src/spawn.rs | 97 +++++++++++++++++++ src/spawn.c | 158 ------------------------------- 9 files changed, 162 insertions(+), 162 deletions(-) create mode 100644 rust-polytreewm/src/api/spawn.rs create mode 100644 rust-polytreewm/src/spawn.rs delete mode 100644 src/spawn.c diff --git a/Makefile b/Makefile index bba31e4..ce6aa3e 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,8 @@ RUST_APIS = \ src/constraints.h \ src/geom.h \ src/helpers.h \ - src/settings.h + src/settings.h \ + src/spawn.h MODULES_SRC = \ src/drw.c \ @@ -32,7 +33,6 @@ MODULES_SRC = \ src/geom.c \ src/layouts.c \ src/logger.c \ - src/spawn.c \ src/state.c \ src/unit.c \ src/util.c \ @@ -83,7 +83,7 @@ polytreewm: src/main.o $(MODULES_OBJ) target/debug/libpolytreewm.a dwm.o: $(DWM_SRC) $(DWM_HDR) target/debug/libpolytreewm.a: $(RUST_SRC) - $(CARGO) build + $(CARGO) build $(CARGO_FEATURES) ######### # Tasks # @@ -91,7 +91,7 @@ target/debug/libpolytreewm.a: $(RUST_SRC) test: $(TEST_EXE) @echo "$(TEST_EXE)" | awk '{ OFS="\n"; $$1=$$1 } 1' | /bin/sh - $(CARGO) test + $(CARGO) test $(CARGO_FEATURES) $(CARGO) fmt --check $(CARGO) clippy diff --git a/config/2-conditionals-bsd.mk b/config/2-conditionals-bsd.mk index ab9d5b1..b33262c 100644 --- a/config/2-conditionals-bsd.mk +++ b/config/2-conditionals-bsd.mk @@ -5,20 +5,26 @@ PKGS += xinerama .if "$(WITH_LOCKER)" == "i3lock" CPPFLAGS += -DWITH_LOCKER -DWITH_LOCKER_I3LOCK +CARGO_FEATURES += --features locker-i3lock .endif .if "$(WITH_LOCKER)" == "i3lock-color" CPPFLAGS += -DWITH_LOCKER -DWITH_LOCKER_I3LOCK_COLOR +CARGO_FEATURES += --features locker-i3lock-color .endif .if "$(WITH_TERMINAL)" == "alacritty" CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_ALACRITTY +CARGO_FEATURES += --features term-alacritty .endif .if "$(WITH_TERMINAL)" == "gnome" CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_GNOME +CARGO_FEATURES += --features term-gnome .endif .if "$(WITH_TERMINAL)" == "st" CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_ST +CARGO_FEATURES += --features term-st .endif .if "$(WITH_TERMINAL)" == "xterm" CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_XTERM +CARGO_FEATURES += --features term-xterm .endif diff --git a/config/2-conditionals-gnu.mk b/config/2-conditionals-gnu.mk index e8d9aa8..a8fc25e 100644 --- a/config/2-conditionals-gnu.mk +++ b/config/2-conditionals-gnu.mk @@ -5,20 +5,26 @@ endif ifeq (i3lock,$(WITH_LOCKER)) CPPFLAGS += -DWITH_LOCKER -DWITH_LOCKER_I3LOCK +CARGO_FEATURES += --features locker-i3lock endif ifeq (i3lock-color,$(WITH_LOCKER)) CPPFLAGS += -DWITH_LOCKER -DWITH_LOCKER_I3LOCK_COLOR +CARGO_FEATURES += --features locker-i3lock-color endif ifeq (alacritty,$(WITH_TERMINAL)) CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_ALACRITTY +CARGO_FEATURES += --features term-alacritty endif ifeq (gnome,$(WITH_TERMINAL)) CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_GNOME +CARGO_FEATURES += --features term-gnome endif ifeq (st,$(WITH_TERMINAL)) CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_ST +CARGO_FEATURES += --features term-st endif ifeq (xterm,$(WITH_TERMINAL)) CPPFLAGS += -DWITH_TERMINAL -DWITH_TERMINAL_XTERM +CARGO_FEATURES += --features term-xterm endif diff --git a/rust-polytreewm/Cargo.toml b/rust-polytreewm/Cargo.toml index 8c1406c..de27270 100644 --- a/rust-polytreewm/Cargo.toml +++ b/rust-polytreewm/Cargo.toml @@ -16,8 +16,20 @@ publish = false name = "polytreewm" crate-type = ["staticlib"] +[features] +default = [] +locker = [] +locker-i3lock = ["locker"] +locker-i3lock-color = ["locker"] +term = [] +term-alacritty = ["term"] +term-gnome = ["term"] +term-st = ["term"] +term-xterm = ["term"] + [dependencies] ctor = "0.1.23" env_logger = "0.9.0" +libc = "0.2.132" log = "0.4.17" x11 = "2.20.0" diff --git a/rust-polytreewm/src/api/mod.rs b/rust-polytreewm/src/api/mod.rs index 204bb83..e97efed 100644 --- a/rust-polytreewm/src/api/mod.rs +++ b/rust-polytreewm/src/api/mod.rs @@ -2,3 +2,4 @@ mod atoms; mod constraints; mod geom; mod settings; +mod spawn; diff --git a/rust-polytreewm/src/api/spawn.rs b/rust-polytreewm/src/api/spawn.rs new file mode 100644 index 0000000..3cb19d6 --- /dev/null +++ b/rust-polytreewm/src/api/spawn.rs @@ -0,0 +1,35 @@ +use crate::*; + +use std::ffi::{CStr, CString}; +use std::os::raw::*; + +#[no_mangle] +unsafe extern "C" fn spawn_command( + name: *const c_char, + callback: unsafe extern "C" fn(), + monitor: c_int, +) { + if name.is_null() || !(0..=9).contains(&monitor) { + return; + } + let name = CStr::from_ptr(name).to_str().unwrap(); + let command = spawn::command(name); + let mut args: Vec = + command.args.iter().map(|arg| arg.to_string()).collect(); + if command.monitor_arg_index != 0 { + args[command.monitor_arg_index] = format!("{}", monitor); + } + let arg_cstrs: Vec = args + .iter() + .map(|arg| CString::new(arg.as_str()).unwrap()) + .collect(); + let arg_ptrs: Vec<*const c_char> = + arg_cstrs.iter().map(|arg| arg.as_ptr()).collect(); + + if libc::fork() != 0 { + callback(); + libc::setsid(); + libc::execvp(arg_ptrs[0], arg_ptrs.as_ptr()); + libc::exit(libc::EXIT_SUCCESS); + } +} diff --git a/rust-polytreewm/src/lib.rs b/rust-polytreewm/src/lib.rs index 39948a3..01e49fa 100644 --- a/rust-polytreewm/src/lib.rs +++ b/rust-polytreewm/src/lib.rs @@ -1,6 +1,7 @@ mod api; mod atoms; mod constraints; +mod spawn; pub mod geom; pub mod settings; diff --git a/rust-polytreewm/src/spawn.rs b/rust-polytreewm/src/spawn.rs new file mode 100644 index 0000000..e0d5fd0 --- /dev/null +++ b/rust-polytreewm/src/spawn.rs @@ -0,0 +1,97 @@ +pub fn command + std::fmt::Debug>(name: S) -> &'static Command { + let name = name.as_ref(); + for command in COMMANDS { + if command.name == name { + return command; + } + } + panic!("unknown command: {:?}", name); +} + +pub struct Command { + pub name: &'static str, + pub monitor_arg_index: usize, + pub args: &'static [&'static str], +} + +static COMMANDS: &[&Command] = &[ + &MENU_COMMAND, + &FIREFOX_COMMAND, + #[cfg(feature = "term")] + &TERM_COMMAND, + #[cfg(feature = "locker")] + &LOCK_COMMAND, +]; + +static MENU_COMMAND: Command = Command { + name: "menu", + monitor_arg_index: 6, + args: &[ + "rofi", + "-modi", + "drun", + "-show", + "drun", + "-monitor", + "-1", // monitor arg + "-show-icons", + ], +}; + +static FIREFOX_COMMAND: Command = Command { + name: "firefox", + monitor_arg_index: 0, + args: &["firefox"], +}; + +#[cfg(feature = "term")] +static TERM_COMMAND: Command = Command { + name: "term", + monitor_arg_index: 0, + #[cfg(feature = "term-alacritty")] + args: &["alacritty"], + #[cfg(feature = "term-gnome")] + args: &["gnome-terminal", "--wait"], + #[cfg(feature = "term-st")] + args: &["st"], + #[cfg(feature = "term-xterm")] + args: &["xterm"], +}; + +#[cfg(feature = "locker")] +static LOCK_COMMAND: Command = Command { + name: "lock", + monitor_arg_index: 0, + #[cfg(feature = "locker-i3lock")] + args: &["i3lock"], + #[cfg(feature = "locker-i3lock-color")] + args: &[ + "i3lock", + "--insidever-color=#ffffff22", + "--ringver-color=#bb00bbbb", + // + "--insidewrong-color=#ffffff22", + "--ringwrong-color=#880000bb", + // + "--inside-color=#00000000", + "--ring-color=#ff00ffcc", + "--line-color=#00000000", + "--separator-color=#ff00ffcc", + // + "--verif-color=#ee00eeee", + "--wrong-color=#ee00eeee", + "--time-color=#ee00eeee", + "--date-color=#ee00eeee", + "--layout-color=#ee00eeee", + "--keyhl-color=#880000bb", + "--bshl-color=#880000bb", + // + "--screen=1", + "--blur=5", + "--clock", + "--indicator", + "--time-str=%H:%M:%S", + "--date-str=%a, %e %b %Y", + "--keylayout=1", + ], +}; diff --git a/src/spawn.c b/src/spawn.c deleted file mode 100644 index d8d776d..0000000 --- a/src/spawn.c +++ /dev/null @@ -1,158 +0,0 @@ -#include "spawn.h" - -#include -#include -#include -#include -#include - -#define MAX_ARGS_COUNT 25 -#define ARGS_SIZE (MAX_ARGS_COUNT + 1) -#define MON_ARG_SIZE 2 - -#ifdef WITH_LOCKER_I3LOCK_COLOR -#define COLOR_BLANK "#00000000" -#define COLOR_CLEAR "#ffffff22" -#define COLOR_DEFAULT "#ff00ffcc" -#define COLOR_TEXT "#ee00eeee" -#define COLOR_WRONG "#880000bb" -#define COLOR_VERIFYING "#bb00bbbb" -#endif // WITH_LOCKER_I3LOCK_COLOR - -struct Command { - const char *name; - size_t monitor_arg_index; - const char *args[ARGS_SIZE]; -}; - -static struct Command commands[] = { -#ifdef WITH_LOCKER - { - .name = "lock", - .monitor_arg_index = 0, -#ifdef WITH_LOCKER_I3LOCK - .args = { "i3lock", NULL }, -#endif // WITH_LOCKER_I3LOCK -#ifdef WITH_LOCKER_I3LOCK_COLOR - .args = { - "i3lock", - "--insidever-color="COLOR_CLEAR, - "--ringver-color="COLOR_VERIFYING, - - "--insidewrong-color="COLOR_CLEAR, - "--ringwrong-color="COLOR_WRONG, - - "--inside-color="COLOR_BLANK, - "--ring-color="COLOR_DEFAULT, - "--line-color="COLOR_BLANK, - "--separator-color="COLOR_DEFAULT, - - "--verif-color="COLOR_TEXT, - "--wrong-color="COLOR_TEXT, - "--time-color="COLOR_TEXT, - "--date-color="COLOR_TEXT, - "--layout-color="COLOR_TEXT, - "--keyhl-color="COLOR_WRONG, - "--bshl-color="COLOR_WRONG, - - "--screen=1", - "--blur=5", - "--clock", - "--indicator", - "--time-str=%H:%M:%S", - "--date-str=%a, %e %b %Y", - "--keylayout=1", - NULL, - }, -#endif // WITH_LOCKER_I3LOCK_COLOR - }, -#endif // WITH_LOCKER - { - .name = "menu", - .monitor_arg_index = 6, - .args = { - "rofi", - "-modi", - "drun", - "-show", - "drun", - "-monitor", - "-1", - "-show-icons", - NULL, - }, - }, -#ifdef WITH_TERMINAL - { - .name = "term", - .monitor_arg_index = 0, -#ifdef WITH_TERMINAL_ALACRITTY - .args = { "alacritty", NULL }, -#endif // WITH_TERMINAL_ALACRITTY -#ifdef WITH_TERMINAL_GNOME - .args = { "gnome-terminal", "--wait", NULL }, -#endif // WITH_TERMINAL_GNOME -#ifdef WITH_TERMINAL_ST - .args = { "st", NULL }, -#endif // WITH_TERMINAL_ST -#ifdef WITH_TERMINAL_XTERM - .args = { "xterm", NULL }, -#endif // WITH_TERMINAL_XTERM - }, -#endif // WITH_TERMINAL - { - .name = "firefox", - .monitor_arg_index = 0, - .args = { "firefox", NULL }, - }, -}; - -void spawn_command( - const char *const name, - void (*const callback)(), - const int monitor -) { - // TODO: maybe we should assert here - if (name == NULL || monitor < 0 || monitor > 9) return; - - for ( - size_t command_index = 0; - command_index < sizeof(commands) / sizeof(struct Command); - ++command_index - ) { - const struct Command *const command = &commands[command_index]; - if (strcmp(name, command->name) != 0) continue; - - // We discard const modifier - // because we will only change newly allocated version. - char **args = (char**)command->args; - char monitor_buffer[2] = { '0' + monitor, '\0' }; - - if (command->monitor_arg_index != 0) { - args = malloc(sizeof(char*) * ARGS_SIZE); - if (args == NULL) return; - - for (size_t arg_index = 0;; ++arg_index) { - // We discard const modifier - // because we will only change newly allocated version. - args[arg_index] = (char*)command->args[arg_index]; - if (args[arg_index] == NULL) break; - } - - args[command->monitor_arg_index] = monitor_buffer; - } - - if (fork() == 0) { - callback(); - setsid(); - execvp(args[0], args); - fprintf(stderr, "polytreewm: execvp %s", args[0]); - perror(" failed"); - exit(EXIT_SUCCESS); - } - - if (command->monitor_arg_index != 0) free(args); - - return; - } -}