aboutsummaryrefslogtreecommitdiff
path: root/plugin.c
blob: 58c79f37eae6b9650bb5b52b9593ced1fe208f57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include "event.h"
#include "global.h"
#include "plugin.h"
#include "plugin_client_header.h"


struct plugin_data{
	void *handle;
	plugin_event_func_t *callback;
};

static i64 num_plugins=0;
static i64 plugins_cap=8;
static struct plugin_data *plugins_list=NULL;


static void consume_event(const struct event_item *event){
	struct plugin_event pe;
	switch(event->type){
		case EVENT_MESSAGE: pe.type=PLUGIN_EVENT_MESSAGE; break;
		case EVENT_ONLINE: pe.type=PLUGIN_EVENT_ONLINE; break;
		case EVENT_JOIN: pe.type=PLUGIN_EVENT_JOIN; break;
		case EVENT_LEAVE: pe.type=PLUGIN_EVENT_LEAVE; break;
		default:
			die("Unknown event type %d in plugin.c:consume_event",event->type);
	}
	pe.timestamp=event->timestamp;
	pe.message=event->message;
	pe.user=event->user;
	pe.room=event->room;
	pe.num=event->num;

	for(i64 i=0;i<num_plugins;i++){
		plugins_list[i].callback(&pe);
	}
}


void plugin_init(void){
	if(plugins_list!=NULL)return;
	plugins_list=malloc(plugins_cap,struct plugin_data);
	memset(plugins_list,0,num_plugins*sizeof(struct plugin_data));

	event_register(consume_event);
}

void plugin_register(const char *fname){
	if(num_plugins==plugins_cap){
		plugins_cap*=2;
		plugins_list=realloc(plugins_list,plugins_cap,struct plugin_data);
	}

	struct plugin_data *data=plugins_list+num_plugins;
	num_plugins++;
	data->handle=dlopen(fname,RTLD_NOW|RTLD_LOCAL);
	if(data->handle==NULL){
		die("Error loading plugin '%s': %s",fname,dlerror());
	}

	plugin_event_func_t* (*init_func)(void)=NULL;
	dlerror();
	*(void**)&init_func=dlsym(data->handle,"plugin_init_func");
	char *err=dlerror();
	if(err!=NULL){
		die("Error reading symbol 'plugin_init_func' from plugin '%s'",fname);
	}
	if(init_func==NULL){
		die("Plugin '%s' exports NULL init function",fname);
	}

	data->callback=init_func();
	if(data->callback==NULL){
		die("Init function of plugin '%s' returned NULL",fname);
	}

	printf("Loaded plugin '%s'\n",fname);
}