Files
bananarchy/src/dwm-plugins/dwm_plugin_runner.c
T

162 lines
4.4 KiB
C
Raw Normal View History

#include <dirent.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "../sxmo-dwm/dwm_plugin.h"
static int try_send_plugin_fifo(const char *plugin_name, int sub_argc, char **sub_argv) {
if (sub_argc >= 2 && sub_argv[1] && strcmp(sub_argv[1], "--preload") == 0) {
return 0;
}
char pid_path[128];
snprintf(pid_path, sizeof(pid_path), "/tmp/dwm_plugin_%s.pid", plugin_name);
FILE *pf = fopen(pid_path, "r");
if (!pf) {
return 0;
}
int pid = 0;
int ok = (fscanf(pf, "%d", &pid) == 1 && pid > 1 && kill((pid_t)pid, 0) == 0);
fclose(pf);
if (!ok) {
return 0;
}
char fifo_path[128];
snprintf(fifo_path, sizeof(fifo_path), "/tmp/dwm_plugin_%s.fifo", plugin_name);
int fd = open(fifo_path, O_WRONLY | O_NONBLOCK | O_CLOEXEC);
if (fd < 0) {
return 0;
}
char cmd[256];
int len = 0;
if (strcmp(plugin_name, "xdrawer") == 0) {
len = snprintf(cmd, sizeof(cmd), "TOGGLE\n");
} else if (sub_argc >= 2 && sub_argv[1] && sub_argv[1][0]) {
len = snprintf(cmd, sizeof(cmd), "OPEN %s\n", sub_argv[1]);
} else {
len = snprintf(cmd, sizeof(cmd), "OPEN\n");
}
ssize_t wr = (len > 0 && len < (int)sizeof(cmd)) ? write(fd, cmd, (size_t)len) : -1;
close(fd);
return wr > 0 ? 1 : 0;
}
static const char *const kPluginDirs[] = {
"/home/user/.local/lib/dwm/plugins",
"/usr/lib/dwm/plugins",
NULL
};
static const char *resolve_plugin_name_from_argv0(const char *argv0) {
const char *base = strrchr(argv0, '/');
base = base ? (base + 1) : argv0;
if (strcasecmp(base, "xdrawer") == 0) {
return "xdrawer";
}
if (strcasecmp(base, "xdialer") == 0 || strcasecmp(base, "dialer") == 0) {
return "dialer";
}
if (strcasecmp(base, "xcalllog") == 0 || strcasecmp(base, "calllog") == 0) {
return "calllog";
}
return NULL;
}
static int list_plugins(void) {
for (int i = 0; kPluginDirs[i]; ++i) {
DIR *dir = opendir(kPluginDirs[i]);
if (!dir) {
continue;
}
struct dirent *ent;
while ((ent = readdir(dir)) != NULL) {
size_t len = strlen(ent->d_name);
if (len <= 3 || strcmp(ent->d_name + len - 3, ".so") != 0) {
continue;
}
char path[512];
snprintf(path, sizeof(path), "%s/%s", kPluginDirs[i], ent->d_name);
void *h = dlopen(path, RTLD_NOW | RTLD_LOCAL);
if (!h) {
continue;
}
const DwmPlugin *plug = (const DwmPlugin *)dlsym(h, DWM_PLUGIN_ENTRY_SYMBOL);
if (plug && plug->api_version == DWM_PLUGIN_API_VERSION && plug->name) {
printf("%-12s %s (%s)\n",
plug->name,
plug->description ? plug->description : "",
path);
}
dlclose(h);
}
closedir(dir);
}
return 0;
}
int main(int argc, char **argv) {
const char *plugin_name = resolve_plugin_name_from_argv0(argv[0]);
int sub_argc = argc;
char **sub_argv = argv;
if (!plugin_name) {
if (argc < 2 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
fprintf(stderr, "Usage: %s <plugin-name|--list> [args...]\n", argv[0]);
return 1;
}
if (strcmp(argv[1], "--list") == 0 || strcmp(argv[1], "-l") == 0) {
return list_plugins();
}
plugin_name = argv[1];
sub_argc = argc - 1;
sub_argv = argv + 1;
}
if (try_send_plugin_fifo(plugin_name, sub_argc, sub_argv)) {
return 0;
}
const char *env_dir = getenv("DWM_PLUGIN_PATH");
char path[512];
void *handle = NULL;
if (env_dir && env_dir[0]) {
snprintf(path, sizeof(path), "%s/%s.so", env_dir, plugin_name);
if (access(path, R_OK) == 0) {
handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
}
}
for (int i = 0; !handle && kPluginDirs[i]; ++i) {
snprintf(path, sizeof(path), "%s/%s.so", kPluginDirs[i], plugin_name);
if (access(path, R_OK) == 0) {
handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
}
}
if (!handle) {
fprintf(stderr, "dwm-plugin: failed to load plugin '%s': %s\n",
plugin_name, dlerror());
return 1;
}
const DwmPlugin *plug = (const DwmPlugin *)dlsym(handle, DWM_PLUGIN_ENTRY_SYMBOL);
if (!plug || plug->api_version != DWM_PLUGIN_API_VERSION || !plug->run_main) {
fprintf(stderr, "dwm-plugin: invalid plugin '%s'\n", plugin_name);
dlclose(handle);
return 1;
}
int rc = plug->run_main(sub_argc, sub_argv);
dlclose(handle);
return rc;
}