Rust rewrite
This commit is contained in:
parent
dc7f72f6ef
commit
35cb20545c
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,4 +1,3 @@
|
|||
modules/*
|
||||
.cache/
|
||||
dim
|
||||
compile_commands.json
|
||||
/target
|
||||
/plugins
|
||||
/.cache
|
||||
|
|
388
Cargo.lock
generated
Normal file
388
Cargo.lock
generated
Normal file
|
@ -0,0 +1,388 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2 1.0.85",
|
||||
"quote 1.0.36",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||
|
||||
[[package]]
|
||||
name = "dim"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"clap",
|
||||
"dlopen",
|
||||
"dlopen_derive",
|
||||
"libc",
|
||||
"x11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dim_plugin_helper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlopen"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937"
|
||||
dependencies = [
|
||||
"dlopen_derive",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlopen_derive"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"quote 0.6.13",
|
||||
"syn 0.15.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example_rust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dim_plugin_helper",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.85",
|
||||
"quote 1.0.36",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "x11"
|
||||
version = "2.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
workspace = { members = [ "dim_plugin_helper","dim_plugins/example_rust"] }
|
||||
[package]
|
||||
name = "dim"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
camino = "1.1.7"
|
||||
clap = { version = "4.5.7", features = ["derive"] }
|
||||
dlopen = "0.1.8"
|
||||
dlopen_derive = "0.1.4"
|
||||
libc = "0.2.155"
|
||||
x11 = { version = "2.21.0", features = ["xlib"] }
|
38
Makefile
38
Makefile
|
@ -1,21 +1,33 @@
|
|||
BIN=./dim
|
||||
CC=gcc
|
||||
CCARGS=-Isrc/include -Wall -pedantic
|
||||
|
||||
MODULES= \
|
||||
modules/clock.dim \
|
||||
modules/battery.dim \
|
||||
modules/timesince.dim
|
||||
CWD := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
|
||||
all: $(BIN) $(MODULES) compile_commands.json
|
||||
PLUGIN_DIR = ${CWD}plugins
|
||||
OBJECT_DIR = $(CWD)target/objects
|
||||
BUILD_DIR = $(CWD)target
|
||||
DIM_CC_FLAGS = -I$(CWD)include -rdynamic -shared -fPIC
|
||||
DIM_CC = gcc
|
||||
|
||||
$(BIN): src/main.c src/plug.c src/socket.c src/util.c
|
||||
$(CC) -o $@ $^ $(CCARGS) -lX11 -ldl
|
||||
BIN=$(BUILD_DIR)/dim
|
||||
|
||||
PLUGINS=$(wildcard dim_plugins/**/Makefile)
|
||||
|
||||
|
||||
modules/%.dim: src/modules/%.c
|
||||
$(CC) -o $@ $^ -rdynamic -shared -fPIC $(CCARGS)
|
||||
all: $(BIN) $(PLUGINS) compile_commands.json
|
||||
|
||||
$(BIN): target/release/dim
|
||||
cp $< $@
|
||||
|
||||
target/release/dim:
|
||||
cargo build --release
|
||||
|
||||
dim_plugins/%/Makefile:
|
||||
$(MAKE) -C $(dir $@) \
|
||||
-E "PLUGIN_DIR=$(PLUGIN_DIR)" \
|
||||
-E "OBJECT_DIR=$(OBJECT_DIR)" \
|
||||
-E "BUILD_DIR=$(BUILD_DIR)" \
|
||||
-E "DIM_CC_FLAGS=$(DIM_CC_FLAGS)" \
|
||||
-E "DIM_CC=$(DIM_CC)"
|
||||
|
||||
|
||||
compile_commands.json:
|
||||
compiledb -n make
|
||||
|
|
15
compile_commands.json
Normal file
15
compile_commands.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
[
|
||||
{
|
||||
"directory": "/home/mcorange/@Projects/xor64/dim/dim_plugins/example_c",
|
||||
"arguments": [
|
||||
"gcc",
|
||||
"-c",
|
||||
"-o",
|
||||
"/home/mcorange/@Projects/xor64/dim/target/objects/example_c/main.o",
|
||||
"src/main.c",
|
||||
"-fPIC",
|
||||
"-pie"
|
||||
],
|
||||
"file": "src/main.c"
|
||||
}
|
||||
]
|
12
dim_plugin_helper/Cargo.toml
Normal file
12
dim_plugin_helper/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "dim_plugin_helper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name="dim_plugin_helper"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.6.0"
|
||||
lazy_static = { version = "1.4.0", features = ["spin"] }
|
||||
libc = "0.2.155"
|
111
dim_plugin_helper/src/lib.rs
Normal file
111
dim_plugin_helper/src/lib.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use std::{ffi::{c_char, c_void, CStr, CString}, io::Write};
|
||||
|
||||
pub use libc::snprintf;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct PluginInfo {
|
||||
ptrs: PluginInfoPtrs,
|
||||
c_name: CString,
|
||||
c_version: CString,
|
||||
c_license: CString
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct PluginInfoPtrs {
|
||||
name: *const c_char,
|
||||
version: *const c_char,
|
||||
license: *const c_char,
|
||||
}
|
||||
|
||||
impl PluginInfo {
|
||||
// pub fn new() -> Self {
|
||||
// Self {
|
||||
// name: std::ptr::null(),
|
||||
// version: std::ptr::null(),
|
||||
// license: std::ptr::null(),
|
||||
// c_name: Default::default(),
|
||||
// c_version: Default::default(),
|
||||
// c_license: Default::default()
|
||||
// }
|
||||
//}
|
||||
pub fn new(name: &str, version: &str, license: &str) -> Self {
|
||||
|
||||
let c_name = CString::new(name).unwrap();
|
||||
let c_version = CString::new(version).unwrap();
|
||||
let c_license = CString::new(license).unwrap();
|
||||
let name = c_name.as_ptr();
|
||||
let version = if c_version.is_empty() {
|
||||
std::ptr::null()
|
||||
} else {c_version.as_ptr()};
|
||||
let license = if c_license.is_empty() {
|
||||
std::ptr::null()
|
||||
} else {c_license.as_ptr()};
|
||||
|
||||
Self { ptrs: PluginInfoPtrs{ name, version, license }, c_name, c_version, c_license }
|
||||
}
|
||||
|
||||
pub fn get(&self) -> *const c_void {
|
||||
&self.ptrs as *const _ as *const c_void
|
||||
}
|
||||
}
|
||||
unsafe impl Sync for PluginInfo {}
|
||||
|
||||
|
||||
// Lord have mercy on me
|
||||
#[macro_export]
|
||||
macro_rules! plugin_info {
|
||||
($name:literal, $version:literal, $license:literal) => {
|
||||
|
||||
lazy_static::lazy_static!(
|
||||
static ref PLUGIN_INFO: PluginInfo = PluginInfo::new($name, $version, $license);
|
||||
);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CBuffer {
|
||||
inner: *mut i8,
|
||||
count: usize,
|
||||
capacity: usize
|
||||
}
|
||||
|
||||
impl CBuffer {
|
||||
pub fn from_raw_parts_mut(buf: *mut i8, capacity: usize) -> Self {
|
||||
Self {
|
||||
inner: buf,
|
||||
capacity,
|
||||
count: 0,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Write for CBuffer {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let mut count = 0;
|
||||
|
||||
for c in buf {
|
||||
unsafe {
|
||||
if self.count + count >= self.capacity - 1 {
|
||||
return Err(std::io::ErrorKind::OutOfMemory.into());
|
||||
}
|
||||
(*self.inner.add(self.count + count)) = *c as i8;
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
unsafe {
|
||||
(*self.inner.add(self.count + count)) = 0;
|
||||
}
|
||||
self.count += count;
|
||||
|
||||
Ok(count as usize)
|
||||
}
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
19
dim_plugins/example_c/Makefile
Normal file
19
dim_plugins/example_c/Makefile
Normal file
|
@ -0,0 +1,19 @@
|
|||
PLUGIN_NAME=example_c
|
||||
|
||||
|
||||
CC_FLAGS = $(DIM_CC_FLAGS)
|
||||
|
||||
SOURCES=$(wildcard src/*.c)
|
||||
OBJECTS=$(patsubst src/%.c,$(OBJECT_DIR)/$(PLUGIN_NAME)/%.o,$(SOURCES))
|
||||
|
||||
$(info $(SOURCES))
|
||||
|
||||
build: $(PLUGIN_DIR)/$(PLUGIN_NAME).dim
|
||||
|
||||
$(PLUGIN_DIR)/$(PLUGIN_NAME).dim: $(OBJECTS)
|
||||
@mkdir -p $(dir $@)
|
||||
$(DIM_CC) -o $@ $^ $(CC_FLAGS)
|
||||
|
||||
$(OBJECT_DIR)/$(PLUGIN_NAME)/%.o: src/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(DIM_CC) -c -o $@ $< -fPIC -pie
|
39
dim_plugins/example_c/src/main.c
Normal file
39
dim_plugins/example_c/src/main.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../../../include/plug.h"
|
||||
|
||||
PLUG_INFO("Example plugin", "0.0.0", "GPLv3")
|
||||
|
||||
typedef struct plug_t {
|
||||
char* some_data;
|
||||
int count;
|
||||
} plug_t;
|
||||
|
||||
plug_t* p = {0};
|
||||
|
||||
void plug_init() {
|
||||
p = malloc(sizeof(plug_t));
|
||||
assert(p != NULL && "Buy more ram KEKW");
|
||||
p->some_data = "hi :3";
|
||||
p->count = 0;
|
||||
|
||||
printf("Hello from plugin");
|
||||
}
|
||||
|
||||
void* plug_pre_reload() {
|
||||
return p;
|
||||
}
|
||||
|
||||
void plug_post_reload(void *state) {
|
||||
p = state;
|
||||
}
|
||||
|
||||
void plug_poll(char *buf, size_t len) {
|
||||
snprintf(buf, len, "%s (%d)", p->some_data, p->count++);
|
||||
}
|
||||
|
||||
void plug_free() {
|
||||
free(p);
|
||||
}
|
12
dim_plugins/example_rust/Cargo.toml
Normal file
12
dim_plugins/example_rust/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "example_rust"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type=["cdylib"]
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dim_plugin_helper = {path="../../dim_plugin_helper"}
|
||||
lazy_static = "1.4.0"
|
15
dim_plugins/example_rust/Makefile
Normal file
15
dim_plugins/example_rust/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Must match package name in Cargo.toml
|
||||
PLUGIN_NAME=example_rust
|
||||
|
||||
|
||||
build: $(PLUGIN_DIR)/$(PLUGIN_NAME).dim
|
||||
|
||||
$(PLUGIN_DIR)/$(PLUGIN_NAME).dim: $(OBJECT_DIR)/$(PLUGIN_NAME)/release/lib$(PLUGIN_NAME).so
|
||||
cp $(OBJECT_DIR)/$(PLUGIN_NAME)/release/lib$(PLUGIN_NAME).so $(PLUGIN_DIR)/$(PLUGIN_NAME).dim
|
||||
|
||||
$(OBJECT_DIR)/$(PLUGIN_NAME)/release/lib$(PLUGIN_NAME).so:
|
||||
mkdir -p $(OBJECT_DIR)/$(PLUGIN_NAME)
|
||||
cargo build --release --target-dir $(OBJECT_DIR)/$(PLUGIN_NAME)
|
||||
|
||||
|
||||
|
67
dim_plugins/example_rust/src/lib.rs
Normal file
67
dim_plugins/example_rust/src/lib.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
use std::ffi::c_void;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::io::BufWriter;
|
||||
use std::io::Write;
|
||||
use dim_plugin_helper::{plugin_info, PluginInfo};
|
||||
|
||||
plugin_info!("Example rust project", "owo", "nyaaa");
|
||||
|
||||
struct Plug {
|
||||
pub some_data: String,
|
||||
}
|
||||
|
||||
impl Plug {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
some_data: String::from("OwO")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static mut PLUG: *mut Plug = std::ptr::null_mut();
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn plug_get_info() -> *const c_void {
|
||||
PLUGIN_INFO.get()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn plug_init() {
|
||||
unsafe {
|
||||
PLUG = (&mut Plug::new()) as *mut Plug;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn plug_pre_reload() -> *const () {
|
||||
unsafe {
|
||||
return PLUG as *const ();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn plug_post_reload(state: *mut ()) {
|
||||
unsafe {
|
||||
PLUG = state as *mut Plug;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn plug_poll(buf: *mut i8, len: usize) {
|
||||
let mut buf = dim_plugin_helper::CBuffer::from_raw_parts_mut(buf, len);
|
||||
// let mut buf = StringBuffer::from_raw_parts_mut(buf, len);
|
||||
|
||||
let data = unsafe {(*PLUG).some_data.clone()};
|
||||
|
||||
let _ = write!(buf, "{}", data);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn plug_free() {
|
||||
|
||||
}
|
||||
|
||||
|
37
examples/example.c
Normal file
37
examples/example.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../include/plug.h"
|
||||
|
||||
PLUG_NAME("Example plugin")
|
||||
PLUG_VERSION("0.0.0")
|
||||
PLUG_LICENSE("GPLv3")
|
||||
|
||||
typedef struct plug_t {
|
||||
char* some_data;
|
||||
} plug_t;
|
||||
|
||||
static plug_t* p = {0};
|
||||
|
||||
void plug_init() {
|
||||
p = malloc(sizeof(plug_t));
|
||||
assert(p != NULL && "Buy more ram KEKW");
|
||||
p->some_data = "hi :3";
|
||||
}
|
||||
|
||||
void* plug_pre_reload() {
|
||||
return p;
|
||||
}
|
||||
|
||||
void plug_post_reload(void *state) {
|
||||
p = state;
|
||||
}
|
||||
|
||||
void plug_poll(char *buf, size_t len) {
|
||||
snprintf(buf, len, "%s", p->some_data);
|
||||
}
|
||||
|
||||
void plug_free() {
|
||||
free(p);
|
||||
}
|
31
include/plug.h
Normal file
31
include/plug.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
#ifndef _H_PLUG
|
||||
#define _H_PLUG
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct plug_info_t {
|
||||
char* name;
|
||||
char* version;
|
||||
char* license;
|
||||
} plug_info_t;
|
||||
|
||||
#define PLUG_INFO(_name, _version, _license) \
|
||||
static plug_info_t PLUG_INFO_VAR = { .name=(_name), .version=(_version), .license=(_license)}; \
|
||||
void* plug_get_info() { \
|
||||
return &PLUG_INFO_VAR; \
|
||||
}
|
||||
|
||||
|
||||
#define PLUG_NAME(s) volatile char* PLUG_NAME = (s);
|
||||
#define PLUG_VERSION(s) volatile char* PLUG_VERSION = (s);
|
||||
#define PLUG_LICENSE(s) volatile char* PLUG_LICENSE = (s);
|
||||
|
||||
|
||||
void plug_init(); // Loads when DIM initialises
|
||||
void* plug_pre_reload(); // Return a pointer to save state
|
||||
void plug_post_reload(void*); // returns the same pointer after reload
|
||||
void plug_poll(char*, size_t); // Write the message to `buf` with max `size` characters
|
||||
void plug_free(); // Free everything before being killed
|
||||
|
||||
#endif
|
44
src/display.rs
Normal file
44
src/display.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use std::ffi::{CString, NulError};
|
||||
|
||||
use x11::xlib;
|
||||
|
||||
|
||||
|
||||
pub struct Display {
|
||||
window: u64,
|
||||
display: *mut xlib::Display
|
||||
|
||||
}
|
||||
|
||||
impl Display {
|
||||
pub fn new() -> Result<Self, ()> {
|
||||
let (window, display) = unsafe {
|
||||
let display = xlib::XOpenDisplay(std::ptr::null());
|
||||
|
||||
if display.is_null() {
|
||||
eprintln!("ERROR: Could not open x11 display");
|
||||
return Err(());
|
||||
}
|
||||
|
||||
(
|
||||
xlib::XDefaultRootWindow(display),
|
||||
display
|
||||
)
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
window,
|
||||
display
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_display_name(&mut self, name: &str) -> Result<(), NulError> {
|
||||
let cstr = CString::new(name)?;
|
||||
unsafe {
|
||||
xlib::XStoreName(self.display, self.window, cstr.as_ptr() as *const i8);
|
||||
xlib::XFlush(self.display);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
|
||||
#ifndef _H_PLUG
|
||||
#define _H_PLUG
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef void* (*plug_init_f) (void);
|
||||
typedef void* (*plug_pre_reload_f) (void);
|
||||
typedef void (*plug_post_reload_f) (void*);
|
||||
typedef void (*plug_poll_f) (char*, size_t);
|
||||
typedef void (*plug_free_f) (void);
|
||||
|
||||
typedef struct plug_t {
|
||||
char* name;
|
||||
char* version;
|
||||
} plug_t;
|
||||
|
||||
typedef struct plug_int_t {
|
||||
char* path;
|
||||
plug_init_f f_init;
|
||||
plug_pre_reload_f f_pre_reload;
|
||||
plug_post_reload_f f_post_reload;
|
||||
plug_poll_f f_poll;
|
||||
plug_free_f f_free;
|
||||
plug_t* state;
|
||||
} plug_int_t;
|
||||
|
||||
void setup_plugins(char* plugin_path);
|
||||
char* poll_plugins(char* sep);
|
||||
void free_plugins(void);
|
||||
void reload_plugins(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
#ifndef _H_SOCKET
|
||||
#define _H_SOCKET
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
typedef enum sock_msg_t{
|
||||
SM_NONE = 0,
|
||||
SM_RELOAD = 1,
|
||||
} sock_msg_t;
|
||||
|
||||
int socket_init(void);
|
||||
sock_msg_t socket_poll(void);
|
||||
void socket_close(void);
|
||||
void socket_send(char*);
|
||||
|
||||
#endif
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
#ifndef _H_UTIL
|
||||
#define _H_UTIL
|
||||
|
||||
void to_lowercase(char* str);
|
||||
void to_uppercase(char* str);
|
||||
|
||||
#endif
|
||||
|
79
src/main.c
79
src/main.c
|
@ -1,79 +0,0 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "plug.h"
|
||||
#include "socket.h"
|
||||
|
||||
void interrupt_handler(int);
|
||||
void print_help(void);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
signal(SIGINT, interrupt_handler);
|
||||
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "send") == 0) {
|
||||
if (argc == 3) {
|
||||
socket_send(argv[2]);
|
||||
return 0;
|
||||
} else {
|
||||
print_help();
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
print_help();
|
||||
printf("ERROR: Unknown subcommand\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (socket_init() != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
setup_plugins("./modules");
|
||||
char* buffer;
|
||||
|
||||
Display *display = XOpenDisplay(NULL);
|
||||
Window window = DefaultRootWindow(display);
|
||||
|
||||
while (1) {
|
||||
sock_msg_t msg = socket_poll();
|
||||
|
||||
switch (msg) {
|
||||
case SM_RELOAD: {
|
||||
reload_plugins();
|
||||
} break;
|
||||
case SM_NONE: break;
|
||||
}
|
||||
|
||||
buffer = poll_plugins("|");
|
||||
XStoreName(display, window, buffer);
|
||||
XFlush(display);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
||||
XCloseDisplay(display);
|
||||
free_plugins();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void interrupt_handler(int sig) {
|
||||
(void) sig;
|
||||
printf("\nCaught SIGINT, exiting\n");
|
||||
free_plugins();
|
||||
socket_close();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void print_help(void) {
|
||||
printf("Usage: dim [command]\n");
|
||||
printf("Commands:\n");
|
||||
printf(" send [MESSAGE] - Sends a message, available messages: [reload]\n");
|
||||
}
|
42
src/main.rs
Normal file
42
src/main.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
#![feature(core_intrinsics)]
|
||||
use std::{path::PathBuf, process::ExitCode, time::Duration};
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
mod display;
|
||||
mod plugman;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct CliArgs {
|
||||
#[arg(long, short, default_value="./plugins")]
|
||||
plugin_dir: camino::Utf8PathBuf,
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
// let ca = CliArgs::parse();
|
||||
let Ok(mut disp) = display::Display::new() else {
|
||||
return ExitCode::from(1);
|
||||
};
|
||||
|
||||
|
||||
let mut pm = plugman::PlugMan::new(1024); // idk tbh
|
||||
if let Err(e) = pm.load(PathBuf::from("./plugins")
|
||||
//ca.plugin_dir.as_std_path().to_path_buf()
|
||||
){
|
||||
eprintln!("ERROR: Failed to load plugins: {e:?}");
|
||||
}
|
||||
|
||||
pm.init_plugins();
|
||||
|
||||
let mut buf = String::new();
|
||||
|
||||
loop {
|
||||
buf.clear();
|
||||
let values = pm.poll_plugins();
|
||||
for (_plug_name, val) in values {
|
||||
buf.push_str(val.as_str());
|
||||
}
|
||||
let _ = disp.write_display_name(&buf);
|
||||
std::thread::sleep(Duration::from_millis(250));
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct plug_t {
|
||||
char* name;
|
||||
char* version;
|
||||
FILE* fp;
|
||||
} plug_t;
|
||||
|
||||
|
||||
static plug_t* p = {0};
|
||||
|
||||
|
||||
char* batt_files[] = {
|
||||
"/sys/class/power_supply/BAT0/capacity",
|
||||
"/sys/class/power_supply/BAT1/capacity"
|
||||
};
|
||||
|
||||
void* plug_init(void) {
|
||||
p = malloc(sizeof(plug_t));
|
||||
assert(p);
|
||||
p->name = "Battery";
|
||||
p->version = "0.0.1";
|
||||
|
||||
for (size_t i = 0; i < sizeof(batt_files)/sizeof(batt_files[0]); i++) {
|
||||
if (access(batt_files[i], F_OK) == 0) {
|
||||
p->fp = fopen(batt_files[i], "r");
|
||||
if (p->fp) {
|
||||
printf("Opened %s\n", batt_files[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!p->fp) {
|
||||
printf("MODULE: ERROR: Unable to find battery\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void* plug_pre_reload(void) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void plug_post_reload(void* pp) {
|
||||
p = pp;
|
||||
}
|
||||
|
||||
void plug_poll(char* buf, size_t len) {
|
||||
if (!p->fp) return;
|
||||
int perc = 0;
|
||||
fseek(p->fp, 0, SEEK_SET);
|
||||
fscanf(p->fp, "%d", &perc);
|
||||
snprintf(buf, len, "Batt: %d%%", perc);
|
||||
}
|
||||
|
||||
void plug_free(void) {}
|
|
@ -1,42 +0,0 @@
|
|||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct plug_t {
|
||||
char* name;
|
||||
char* version;
|
||||
int i;
|
||||
} plug_t;
|
||||
|
||||
|
||||
plug_t* p = {0};
|
||||
|
||||
void* plug_init(void) {
|
||||
p = malloc(sizeof(plug_t));
|
||||
p->name = "time";
|
||||
p->version = "0.0.1";
|
||||
p->i = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
void* plug_pre_reload(void) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void plug_post_reload(void* pp) {
|
||||
p = pp;
|
||||
p->i += 1;
|
||||
}
|
||||
|
||||
void plug_poll(char* buf, size_t len) {
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(buf, len, "Time: %H:%M (%Y-%m-%d)", timeinfo);
|
||||
}
|
||||
|
||||
void plug_free(void) {}
|
|
@ -1,36 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef struct plug_t {
|
||||
char* name; // Always keep these on top
|
||||
char* version;
|
||||
} plug_t;
|
||||
|
||||
|
||||
static plug_t* p = {0};
|
||||
|
||||
|
||||
void* plug_init(void) {
|
||||
p = malloc(sizeof(plug_t));
|
||||
assert(p);
|
||||
p->name = "example";
|
||||
p->version = "0.0.1";
|
||||
// Return NULL if error
|
||||
return p;
|
||||
}
|
||||
|
||||
void* plug_pre_reload(void) {
|
||||
return p; // send state to dim
|
||||
}
|
||||
|
||||
void plug_post_reload(void* pp) {
|
||||
p = pp; // get back state
|
||||
}
|
||||
|
||||
void plug_poll(char* buf, size_t len) {
|
||||
// print text to `buf` with max len `len`
|
||||
}
|
||||
|
||||
void plug_free(void) {
|
||||
free(p); // free state
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef struct plug_t {
|
||||
char* name; // Always keep these on top
|
||||
char* version;
|
||||
} plug_t;
|
||||
|
||||
|
||||
static plug_t* p = {0};
|
||||
|
||||
|
||||
void* plug_init(void) {
|
||||
p = malloc(sizeof(plug_t));
|
||||
assert(p);
|
||||
p->name = "time-since";
|
||||
p->version = "0.0.1";
|
||||
return p;
|
||||
}
|
||||
|
||||
void* plug_pre_reload(void) {
|
||||
return p; // send state to dim
|
||||
}
|
||||
|
||||
void plug_post_reload(void* pp) {
|
||||
p = pp; // get back state
|
||||
}
|
||||
|
||||
void plug_poll(char* buf, size_t len) {
|
||||
struct tm t = {0};
|
||||
t.tm_year = 2024 - 1900;
|
||||
t.tm_mon = 2;
|
||||
t.tm_mday = 8;
|
||||
|
||||
time_t diff = difftime(time(0), mktime(&t)) / (60 * 60 * 24);
|
||||
|
||||
snprintf(buf, len, " %ld days <3", diff);
|
||||
}
|
||||
|
||||
void plug_free(void) {
|
||||
free(p); // free state
|
||||
}
|
214
src/plug.c
214
src/plug.c
|
@ -1,214 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include "plug.h"
|
||||
|
||||
|
||||
#define PLUG_PATH_MAX 255
|
||||
#define PLUG_MAX_COUNT (PLUG_PATH_MAX+255)
|
||||
#define PLUG_POLL_BUF_SZ 1024
|
||||
|
||||
typedef struct PlugMan {
|
||||
plug_int_t* plugs[PLUG_MAX_COUNT];
|
||||
size_t plug_count;
|
||||
void* plug_objs[PLUG_MAX_COUNT];
|
||||
size_t plug_obj_count;
|
||||
} plugman_t;
|
||||
|
||||
|
||||
static plugman_t PLUGMAN = {0};
|
||||
|
||||
void* load_plug_sym(void* plug_f, char* fn_name);
|
||||
plug_int_t* load_plugin(char* path, bool);
|
||||
|
||||
void load_plugins(const char* mod_dir_p) {
|
||||
DIR* dir = {0};
|
||||
|
||||
dir = opendir(mod_dir_p);
|
||||
|
||||
if (!dir) {
|
||||
printf("ERROR: Failed to open dir %s\n", mod_dir_p);
|
||||
}
|
||||
|
||||
struct dirent* dir_entry;
|
||||
|
||||
while ((dir_entry = readdir(dir)) != NULL) {
|
||||
if (!(dir_entry->d_type == DT_REG ||
|
||||
dir_entry->d_type == DT_LNK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(dir_entry->d_name, ".") == 0 ||
|
||||
strcmp(dir_entry->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char* dot = strchr(dir_entry->d_name, '.');
|
||||
|
||||
if (!dot || dot == dir_entry->d_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char* ext = dot+1;
|
||||
if (strcmp(ext, "dim") != 0) continue;
|
||||
|
||||
printf("INFO: Found plugin: %s/%s\n", mod_dir_p, dir_entry->d_name);
|
||||
|
||||
char* full_path = (char*)malloc(sizeof(char)*1028);
|
||||
snprintf(full_path, PLUG_MAX_COUNT, "%s/%s", mod_dir_p, dir_entry->d_name);
|
||||
plug_int_t* plug = load_plugin(full_path, true);
|
||||
|
||||
if (!plug) {
|
||||
continue;
|
||||
}
|
||||
PLUGMAN.plugs[PLUGMAN.plug_count++] = plug;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
plug_int_t* load_plugin(char* path, bool check_duplicates) {
|
||||
if (check_duplicates) {
|
||||
for (size_t i = 0; i < PLUGMAN.plug_count; i++) {
|
||||
plug_int_t* plug = PLUGMAN.plugs[i];
|
||||
if (strcmp(plug->path, path) == 0) {
|
||||
return NULL; // plugin exists
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plug_int_t* plug = malloc(sizeof(plug_int_t));
|
||||
plug->path = path;
|
||||
|
||||
void* plug_f = dlopen(path, RTLD_NOW);
|
||||
|
||||
if (!plug_f) {
|
||||
printf("ERROR: Failed to load plugin %s\n", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// "technically" couldnt run on very niche platforms but idc
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
|
||||
plug->f_init = (plug_init_f) load_plug_sym(plug_f, "plug_init");
|
||||
plug->f_pre_reload = (plug_pre_reload_f) load_plug_sym(plug_f, "plug_pre_reload");
|
||||
plug->f_post_reload = (plug_post_reload_f) load_plug_sym(plug_f, "plug_post_reload");
|
||||
plug->f_poll = (plug_poll_f) load_plug_sym(plug_f, "plug_poll");
|
||||
plug->f_free = (plug_free_f) load_plug_sym(plug_f, "plug_free");
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
if (!plug->f_init || !plug->f_pre_reload ||
|
||||
!plug->f_poll || !plug->f_free ||
|
||||
!plug->f_post_reload) {
|
||||
dlclose(plug_f);
|
||||
printf("ERROR: Failed to find all functions in plugin");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PLUGMAN.plug_objs[PLUGMAN.plug_obj_count++] = plug_f;
|
||||
return plug;
|
||||
}
|
||||
|
||||
|
||||
void* load_plug_sym(void* plug_f, char* fn_name) {
|
||||
void* f = dlsym(plug_f, fn_name);
|
||||
char* err = dlerror();
|
||||
|
||||
if (err){
|
||||
printf("ERROR: Could not load plug symbol '%s': %s\n", fn_name, err);
|
||||
return NULL;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void setup_plugins(char* plugin_path) {
|
||||
load_plugins(plugin_path);
|
||||
printf("INFO: Loaded %zu plugins:\n", PLUGMAN.plug_count);
|
||||
for (size_t i = 0; i < PLUGMAN.plug_count; i++) {
|
||||
plug_int_t* plug = PLUGMAN.plugs[i];
|
||||
|
||||
plug->state = (plug->f_init)();
|
||||
|
||||
if (!plug->state) {
|
||||
printf("Plugin '%s' did not initialise, skipping\n", plug->path);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf(" - %s (%s)\n", plug->state->name, plug->state->version);
|
||||
}
|
||||
}
|
||||
|
||||
void free_plugins(void) {
|
||||
for (size_t i = 0; i < PLUGMAN.plug_count; i++) {
|
||||
plug_int_t* plug = PLUGMAN.plugs[i];
|
||||
(plug->f_free)();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < PLUGMAN.plug_obj_count; i++) {
|
||||
dlclose(PLUGMAN.plug_objs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char* poll_plugins(char* sep) {
|
||||
char* buf = malloc(PLUG_POLL_BUF_SZ * sizeof(char));
|
||||
|
||||
if (!buf) {
|
||||
printf("Unable to allocate buffer for polling\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < PLUGMAN.plug_count; i++) {
|
||||
plug_int_t* plug = PLUGMAN.plugs[i];
|
||||
if (!plug->state) continue;
|
||||
|
||||
|
||||
// printf("Polling plug id %zu\n", i);
|
||||
size_t len = strlen(buf);
|
||||
(plug->f_poll)(buf + len, PLUG_POLL_BUF_SZ - len);
|
||||
|
||||
if (i < PLUGMAN.plug_count - 1) {
|
||||
size_t len_post = strlen(buf);
|
||||
snprintf(buf + len_post, PLUG_POLL_BUF_SZ - len_post, " %s ", sep);
|
||||
}
|
||||
}
|
||||
|
||||
// printf("Setting title: '%s'\n", buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void reload_plugins(void) {
|
||||
void* plug_states[PLUG_MAX_COUNT];
|
||||
size_t plug_count = 0;
|
||||
|
||||
printf("INFO: Reloading plugins\n");
|
||||
// save states
|
||||
for (size_t i = 0; i < PLUGMAN.plug_count; i++) {
|
||||
plug_int_t* plug = PLUGMAN.plugs[i];
|
||||
void* state = (plug->f_pre_reload)();
|
||||
plug_states[plug_count++] = state;
|
||||
}
|
||||
|
||||
// unload plugins
|
||||
for (size_t i = 0; i < PLUGMAN.plug_obj_count; i++) {
|
||||
dlclose(PLUGMAN.plug_objs[i]);
|
||||
}
|
||||
|
||||
PLUGMAN.plug_obj_count = 0;
|
||||
|
||||
for (size_t i = 0; i < PLUGMAN.plug_count; i++) {
|
||||
plug_int_t* plug = PLUGMAN.plugs[i];
|
||||
plug = load_plugin(plug->path, false);
|
||||
(plug->f_post_reload)(plug_states[i]);
|
||||
}
|
||||
|
||||
load_plugins("./modules");
|
||||
}
|
||||
|
||||
|
98
src/plugman/mod.rs
Normal file
98
src/plugman/mod.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use self::plugin::Plugin;
|
||||
|
||||
|
||||
mod plugin;
|
||||
|
||||
pub struct PlugMan {
|
||||
plugins: Vec<Plugin>,
|
||||
len_cap: usize,
|
||||
}
|
||||
|
||||
|
||||
impl PlugMan {
|
||||
pub fn new(len_cap: usize) -> Self {
|
||||
Self {
|
||||
plugins: Vec::new(),
|
||||
len_cap
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(&mut self, dir: PathBuf) -> Result<(), PluginError>{
|
||||
let files = std::fs::read_dir(dir)?;
|
||||
|
||||
for file in files {
|
||||
let entry = file?;
|
||||
if entry.file_type()?.is_file() {
|
||||
let plugin = Plugin::load(entry.path().to_path_buf())?;
|
||||
println!("INFO: Loaded plugin {} {} licensed with {}",
|
||||
plugin.name().clone(),
|
||||
plugin.version().clone().unwrap_or("None".to_string()),
|
||||
plugin.license().clone().unwrap_or("None".to_string())
|
||||
);
|
||||
self.plugins.push(plugin);
|
||||
} else
|
||||
if entry.file_type()?.is_dir() {
|
||||
self.load(entry.path().to_path_buf())?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init_plugins(&mut self) {
|
||||
for plugin in &self.plugins {
|
||||
plugin.init();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn reload_plugins(&mut self) {
|
||||
for plugin in &mut self.plugins {
|
||||
if let Err(e) = plugin.reload() {
|
||||
eprintln!("ERROR: Failed to reload plugin {:?}: {e}", plugin.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn unload_plugins(&mut self) {
|
||||
while let Some(plug) = self.plugins.pop() {
|
||||
plug.free();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll_plugins(&mut self) -> Vec<(String, String)> {
|
||||
let mut answers = Vec::new();
|
||||
let len = self.len_cap / self.plugins.len();
|
||||
for plugin in &self.plugins {
|
||||
if !plugin.enabled() {
|
||||
continue;
|
||||
}
|
||||
match plugin.poll(len) {
|
||||
Ok(v) => answers.push((plugin.name().clone(), v)),
|
||||
Err(e) => eprintln!("Failed to poll plugin: {e}"),
|
||||
}
|
||||
|
||||
}
|
||||
answers
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PluginError {
|
||||
DlOpenError(dlopen::Error),
|
||||
IoError(std::io::Error)
|
||||
}
|
||||
|
||||
impl From<dlopen::Error> for PluginError {
|
||||
fn from(value: dlopen::Error) -> Self {
|
||||
Self::DlOpenError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for PluginError {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Self::IoError(value)
|
||||
}
|
||||
}
|
144
src/plugman/plugin.rs
Normal file
144
src/plugman/plugin.rs
Normal file
|
@ -0,0 +1,144 @@
|
|||
use std::{alloc::Layout, ffi::{c_char, CStr, CString}, path::PathBuf};
|
||||
|
||||
use dlopen::raw::Library;
|
||||
|
||||
#[derive(Debug, Clone, Copy,)]
|
||||
pub struct PluginSyms {
|
||||
init: unsafe extern "C" fn(),
|
||||
pre_reload: unsafe extern "C" fn() -> *const (),
|
||||
post_reload: unsafe extern "C" fn(state: *const ()),
|
||||
poll: unsafe extern "C" fn(buf: *mut i8, len: usize),
|
||||
free: unsafe extern "C" fn(),
|
||||
get_info: unsafe extern "C" fn() -> *const PluginInfo,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PluginInfo {
|
||||
name: *const c_char,
|
||||
version: *const c_char,
|
||||
license: *const c_char,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Plugin {
|
||||
syms: Option<PluginSyms>,
|
||||
path: PathBuf,
|
||||
lib: Option<Library>,
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
|
||||
impl Plugin {
|
||||
pub fn load(path: PathBuf) -> Result<Self, dlopen::Error> {
|
||||
let mut s = Self::default();
|
||||
s.enabled = true;
|
||||
s.path = path;
|
||||
s.reload_symbols()?;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn reload_symbols(&mut self) -> Result<(), dlopen::Error> {
|
||||
println!("INFO: Loading {:?}", self.path);
|
||||
let lib = Library::open(&self.path)?;
|
||||
let symbols = PluginSyms {
|
||||
init: unsafe { lib.symbol("plug_init")? },
|
||||
pre_reload: unsafe { lib.symbol("plug_pre_reload")? },
|
||||
post_reload: unsafe { lib.symbol("plug_post_reload")? },
|
||||
poll: unsafe { lib.symbol("plug_poll")? },
|
||||
free: unsafe { lib.symbol("plug_free")? },
|
||||
|
||||
get_info: unsafe { lib.symbol("plug_get_info")? },
|
||||
};
|
||||
unsafe {
|
||||
if (symbols.get_info)().is_null() {
|
||||
eprintln!("ERROR: Info fields for plugin {:?} are null", self.path);
|
||||
self.disable();
|
||||
}
|
||||
}
|
||||
|
||||
self.syms = Some(symbols);
|
||||
self.lib = Some(lib);
|
||||
println!("INFO: Loading OK");
|
||||
Ok(())
|
||||
}
|
||||
pub fn syms(&self) -> PluginSyms {
|
||||
self.syms.unwrap()
|
||||
}
|
||||
|
||||
pub fn init(&self) {
|
||||
unsafe {
|
||||
(self.syms().init)()
|
||||
}
|
||||
}
|
||||
pub fn reload(&mut self) -> Result<(), dlopen::Error> {
|
||||
unsafe {
|
||||
let state = (self.syms().pre_reload)();
|
||||
if let Err(e) = self.reload_symbols() {
|
||||
self.disable();
|
||||
return Err(e);
|
||||
}
|
||||
(self.syms().post_reload)(state);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn poll(&self, cap: usize) -> Result<String, std::string::FromUtf8Error> {
|
||||
let layout = Layout::from_size_align(cap, 1).unwrap();
|
||||
let buf = unsafe {
|
||||
std::alloc::alloc_zeroed(layout)
|
||||
};
|
||||
let s = unsafe {
|
||||
(self.syms().poll)(buf as *mut i8, cap);
|
||||
let len = libc::strlen(buf as *const i8);
|
||||
String::from_raw_parts(buf, len, cap)
|
||||
};
|
||||
|
||||
println!("Polled: {}", s);
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub fn free(self) {
|
||||
unsafe {
|
||||
(self.syms().free)();
|
||||
}
|
||||
drop(self.lib.unwrap());
|
||||
}
|
||||
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
pub fn disable(&mut self) {
|
||||
self.enabled = false;
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
unsafe {
|
||||
let info = (self.syms().get_info)();
|
||||
CStr::from_ptr((*info).name).to_string_lossy().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn version(&self) -> Option<String> {
|
||||
unsafe {
|
||||
let info = (self.syms().get_info)();
|
||||
let v = (*info).version;
|
||||
if v.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(CStr::from_ptr(v).to_string_lossy().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn license(&self) -> Option<String> {
|
||||
unsafe {
|
||||
let info = (self.syms().get_info)();
|
||||
let v = (*info).license;
|
||||
if v.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(CStr::from_ptr(v).to_string_lossy().to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
189
src/socket.c
189
src/socket.c
|
@ -1,189 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/select.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "socket.h"
|
||||
#include "util.h"
|
||||
|
||||
#define SOCKET_PATH "/tmp/dim.sock"
|
||||
#define BUFFER_SIZE 255
|
||||
|
||||
typedef struct sock_server_t {
|
||||
int s_fd;
|
||||
int c_fd;
|
||||
struct sockaddr_un s_addr;
|
||||
char buf[BUFFER_SIZE];
|
||||
int max_fd;
|
||||
fd_set read_fds;
|
||||
} sock_server_t;
|
||||
|
||||
sock_server_t SOCK_SERVER = {0};
|
||||
|
||||
|
||||
int socket_init(void) {
|
||||
|
||||
// Check if socket exists
|
||||
if (access(SOCKET_PATH, F_OK) == 0) {
|
||||
remove(SOCKET_PATH);
|
||||
}
|
||||
|
||||
|
||||
// Create the socket
|
||||
SOCK_SERVER.s_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (SOCK_SERVER.s_fd == -1) {
|
||||
perror("ERROR: Failed to create socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flags = fcntl(SOCK_SERVER.s_fd, F_GETFL, 0);
|
||||
if (fcntl(SOCK_SERVER.s_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
perror("ERROR: Failed to set socket to non blocking");
|
||||
close(SOCK_SERVER.s_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set up the server address structure
|
||||
memset(&SOCK_SERVER.s_addr, 0, sizeof(struct sockaddr_un));
|
||||
SOCK_SERVER.s_addr.sun_family = AF_UNIX;
|
||||
strncpy(SOCK_SERVER.s_addr.sun_path, SOCKET_PATH, sizeof(SOCK_SERVER.s_addr.sun_path) - 1);
|
||||
|
||||
// Bind the socket to the address
|
||||
int berr = bind(
|
||||
SOCK_SERVER.s_fd,
|
||||
(struct sockaddr *)&SOCK_SERVER.s_addr,
|
||||
sizeof(struct sockaddr_un));
|
||||
|
||||
if (berr == -1) {
|
||||
perror("ERROR: Failed to bind to socket");
|
||||
close(SOCK_SERVER.s_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Listen for incoming connections
|
||||
if (listen(SOCK_SERVER.s_fd, 5) == -1) {
|
||||
perror("ERRROR: Failed to start listening for messages in the socket");
|
||||
close(SOCK_SERVER.s_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("INFO: Server is listening on %s\n", SOCKET_PATH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct timeval timeout = {0};
|
||||
|
||||
sock_msg_t socket_poll(void) {
|
||||
FD_ZERO(&SOCK_SERVER.read_fds);
|
||||
FD_SET(SOCK_SERVER.s_fd, &SOCK_SERVER.read_fds);
|
||||
SOCK_SERVER.max_fd = SOCK_SERVER.s_fd;
|
||||
|
||||
// Add client sockets to the set
|
||||
if (SOCK_SERVER.c_fd > 0) {
|
||||
FD_SET(SOCK_SERVER.c_fd, &SOCK_SERVER.read_fds);
|
||||
if (SOCK_SERVER.c_fd > SOCK_SERVER.max_fd) {
|
||||
SOCK_SERVER.max_fd = SOCK_SERVER.c_fd;
|
||||
}
|
||||
}
|
||||
// Wait for an activity on one of the sockets
|
||||
int activity = select(SOCK_SERVER.max_fd + 1, &SOCK_SERVER.read_fds, NULL, NULL, &timeout);
|
||||
|
||||
if (activity < 0 && errno != EINTR) {
|
||||
perror("select error");
|
||||
}
|
||||
|
||||
|
||||
// If something happened on the server socket, it's an incoming connection
|
||||
if (FD_ISSET(SOCK_SERVER.s_fd, &SOCK_SERVER.read_fds)) {
|
||||
if ((SOCK_SERVER.c_fd = accept(SOCK_SERVER.s_fd, NULL, NULL)) == -1) {
|
||||
if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
||||
perror("accept error");
|
||||
}
|
||||
} else {
|
||||
//printf("Accepted new connection\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If something happened on the client socket, it's incoming data
|
||||
if (SOCK_SERVER.c_fd > 0 && FD_ISSET(SOCK_SERVER.c_fd, &SOCK_SERVER.read_fds)) {
|
||||
int num_bytes = read(SOCK_SERVER.c_fd, SOCK_SERVER.buf, BUFFER_SIZE - 1);
|
||||
if (num_bytes > 0) {
|
||||
SOCK_SERVER.buf[num_bytes] = '\0'; // Null-terminate the buffer
|
||||
return (sock_msg_t)atoi(SOCK_SERVER.buf);
|
||||
//printf("Received message: %s\n", SOCK_SERVER.buf);
|
||||
} else if (num_bytes == 0) {
|
||||
// Client disconnected
|
||||
//printf("Client disconnected\n");
|
||||
close(SOCK_SERVER.c_fd);
|
||||
SOCK_SERVER.c_fd = -1;
|
||||
} else {
|
||||
if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
||||
perror("read error");
|
||||
}
|
||||
}
|
||||
}
|
||||
return SM_NONE;
|
||||
}
|
||||
|
||||
void socket_close(void) {
|
||||
close(SOCK_SERVER.s_fd);
|
||||
unlink(SOCKET_PATH);
|
||||
}
|
||||
|
||||
void socket_send(char* msg_str) {
|
||||
to_lowercase(msg_str);
|
||||
|
||||
sock_msg_t msg_t = SM_NONE;
|
||||
|
||||
if (strcmp(msg_str, "reload") == 0) {
|
||||
msg_t = SM_RELOAD;
|
||||
} else {
|
||||
printf("ERROR: Unknown message type '%s'\n", msg_str);
|
||||
printf("NOTE: Available messages:\n");
|
||||
printf(" - reload\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int client_fd;
|
||||
struct sockaddr_un server_addr;
|
||||
|
||||
// Create the socket
|
||||
if ((client_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
perror("ERROR: Failed to create error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up the server address structure
|
||||
memset(&server_addr, 0, sizeof(struct sockaddr_un));
|
||||
server_addr.sun_family = AF_UNIX;
|
||||
strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1);
|
||||
|
||||
// Connect to the server
|
||||
if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_un)) == -1) {
|
||||
perror("ERROR: Failed to connect to server");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
char msg[255];
|
||||
|
||||
snprintf(msg, 255, "%d", msg_t);
|
||||
|
||||
// Send a message to the server
|
||||
if (write(client_fd, msg, strlen(msg)) == -1) {
|
||||
perror("ERROR: Failed to write message to server");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
close(client_fd);
|
||||
}
|
||||
|
||||
|
14
src/util.c
14
src/util.c
|
@ -1,14 +0,0 @@
|
|||
|
||||
#include <ctype.h>
|
||||
|
||||
void to_lowercase(char* str) {
|
||||
for(int i = 0; str[i]; i++){
|
||||
str[i] = tolower(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void to_uppercase(char* str) {
|
||||
for(int i = 0; str[i]; i++){
|
||||
str[i] = tolower(str[i]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user