Rust rewrite

This commit is contained in:
2024-06-14 18:22:20 +03:00
parent dc7f72f6ef
commit 35cb20545c
30 changed files with 1117 additions and 766 deletions

44
src/display.rs Normal file
View 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(())
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -1,9 +0,0 @@
#ifndef _H_UTIL
#define _H_UTIL
void to_lowercase(char* str);
void to_uppercase(char* str);
#endif

View File

@@ -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
View 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));
}
}

View File

@@ -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) {}

View File

@@ -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) {}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
View 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
View 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())
}
}
}

View File

@@ -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);
}

View File

@@ -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]);
}
}