first commit 🎉

This commit is contained in:
ari melody 2025-05-05 17:44:20 +01:00
commit b6a4bb5a58
Signed by: ari
GPG key ID: 60B5F0386E3DDB7E
8 changed files with 213 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
pluginhost
plugins/**/*.so
**/*.o

30
Makefile Normal file
View file

@ -0,0 +1,30 @@
CC = clang
CFLAGS = -std=c17 -g -Wall -O2 -fPIC
EXEC = pluginhost
SRCS = $(shell find src -name '*.c')
OBJS = $(SRCS:.c=.o)
PLUGINS = $(shell ls plugins)
.PHONY: $(EXEC)
all: $(EXEC) all_plugins
$(EXEC): $(OBJS)
$(CC) $(CFLAGS) -o $(EXEC) $(OBJS)
src/%.c.o: src/%.c
$(CC) $(CFLAGS) -o $@ -c $<
all_plugins:
for plugin in $(PLUGINS); do \
$(MAKE) -C plugins/$$plugin; \
done
clean:
rm -f $(EXEC) $(OBJS)
for plugin in $(PLUGINS); do \
$(MAKE) -C plugins/$$plugin clean; \
done

7
include/ariplugin.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef ARIPLUGIN_H
#define ARIPLUGIN_H
int ari_plugin_load();
int ari_plugin_unload();
#endif // ARIPLUGIN_H

View file

@ -0,0 +1,22 @@
CC = clang
CFLAGS = -std=c17 -g -Wall
LD = ld
LDFLAGS = -shared -g -lc
LIBRARY = aridoodle.so
SRCS = $(shell find . -name '*.c')
OBJS = $(SRCS:.c=.o)
.PHONY: all
all: $(LIBRARY)
$(LIBRARY): $(OBJS)
$(LD) $(LDFLAGS) -o $(LIBRARY) $(OBJS)
%.c.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
clean:
rm -f $(OBJS) $(LIBRARY)

View file

@ -0,0 +1,12 @@
#include <stdio.h>
#include "../../include/ariplugin.h"
int ari_plugin_load() {
printf("hello from aridoodle :aridoodle:\n");
return 0;
}
int ari_plugin_unload() {
printf("aridoodle says byebye!\n");
return 0;
}

22
plugins/test/Makefile Normal file
View file

@ -0,0 +1,22 @@
CC = clang
CFLAGS = -std=c17 -g -Wall
LD = ld
LDFLAGS = -shared -g -lc
LIBRARY = test.so
SRCS = $(shell find . -name '*.c')
OBJS = $(SRCS:.c=.o)
.PHONY: all
all: $(LIBRARY)
$(LIBRARY): $(OBJS)
$(LD) $(LDFLAGS) -o $(LIBRARY) $(OBJS)
%.c.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
clean:
rm -f $(OBJS) $(LIBRARY)

12
plugins/test/test.c Normal file
View file

@ -0,0 +1,12 @@
#include <stdio.h>
#include "../../include/ariplugin.h"
int ari_plugin_load() {
printf("hello from test plugin!\n");
return 0;
}
int ari_plugin_unload() {
printf("test plugin unloaded successfully!\n");
return 0;
}

105
src/main.c Normal file
View file

@ -0,0 +1,105 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <dirent.h>
#include <err.h>
#define LIBRARY_PATH_FMT "plugins/%s/%s.so"
typedef struct {
char name[256];
void *handle;
int (*func_load)(void);
int (*func_unload)(void);
} Plugin;
int main(int argc, char *argv[]) {
// find plugins
DIR *plugins_dir = opendir("plugins");
if (plugins_dir == NULL) {
errx(EXIT_FAILURE, "failed to read plugins directory");
}
struct dirent *plugin_ent;
size_t n_plugins = 0;
while ((plugin_ent = readdir(plugins_dir)) != NULL) {
if (!strcmp(".", plugin_ent->d_name))
continue;
if (!strcmp("..", plugin_ent->d_name))
continue;
n_plugins++;
}
rewinddir(plugins_dir);
Plugin plugins[n_plugins];
size_t n_plugins_ok = 0;
while ((plugin_ent = readdir(plugins_dir)) != NULL) {
if (!strcmp(".", plugin_ent->d_name))
continue;
if (!strcmp("..", plugin_ent->d_name))
continue;
char *error;
strcpy(plugins[n_plugins_ok].name, plugin_ent->d_name);
char *library_path = NULL;
int len = snprintf(library_path, 0, LIBRARY_PATH_FMT, plugins[n_plugins_ok].name, plugins[n_plugins_ok].name);
library_path = malloc(len);
sprintf(library_path, LIBRARY_PATH_FMT, plugins[n_plugins_ok].name, plugins[n_plugins_ok].name);
plugins[n_plugins_ok].handle = dlopen(library_path, RTLD_LAZY);
if (!plugins[n_plugins_ok].handle) {
errx(EXIT_FAILURE, "failed to load plugin: %s\n", dlerror());
}
dlerror(); // clear errors
plugins[n_plugins_ok].func_load = dlsym(plugins[n_plugins_ok].handle, "ari_plugin_load");
plugins[n_plugins_ok].func_unload = dlsym(plugins[n_plugins_ok].handle, "ari_plugin_unload");
error = dlerror();
if (error != NULL) {
fprintf(stderr, "failed to initialise plugin \"%s\": %s\n", plugins[n_plugins_ok].name, error);
dlclose(plugins[n_plugins_ok].handle);
continue;
}
int code = plugins[n_plugins_ok].func_load();
if (code != EXIT_SUCCESS) {
fprintf(stderr, "warn: plugin \"%s\" returned code %d when loaded\n", plugins[n_plugins_ok].name, code);
}
free(library_path);
n_plugins_ok++;
}
printf("%ld plugins loaded.\n", n_plugins_ok);
printf("press any key to continue...");
getc(stdin);
for (int i = 0; i < n_plugins; i++) {
if (plugins[n_plugins_ok].handle == NULL) {
continue;
}
int code = plugins[i].func_unload();
if (code != EXIT_SUCCESS) {
fprintf(stderr, "warn: plugin \"%s\" returned code %d when unloaded\n", plugins[i].name, code);
}
dlclose(plugins[i].handle);
}
closedir(plugins_dir);
return 0;
}