first commit 🎉
This commit is contained in:
commit
b6a4bb5a58
8 changed files with 213 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
pluginhost
|
||||
plugins/**/*.so
|
||||
**/*.o
|
30
Makefile
Normal file
30
Makefile
Normal 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
7
include/ariplugin.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef ARIPLUGIN_H
|
||||
#define ARIPLUGIN_H
|
||||
|
||||
int ari_plugin_load();
|
||||
int ari_plugin_unload();
|
||||
|
||||
#endif // ARIPLUGIN_H
|
22
plugins/aridoodle/Makefile
Normal file
22
plugins/aridoodle/Makefile
Normal 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)
|
12
plugins/aridoodle/aridoodle.c
Normal file
12
plugins/aridoodle/aridoodle.c
Normal 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
22
plugins/test/Makefile
Normal 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
12
plugins/test/test.c
Normal 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
105
src/main.c
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue