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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#include <glib.h>
#include <gmodule.h>
typedef void (*PluginStartup)();
typedef void (*PluginShutdown)();
typedef struct {
GModule *module;
char *name;
PluginStartup startup;
PluginShutdown shutdown;
} Plugin;
static gpointer load_sym(GModule *module, char *name, char *symbol)
{
gpointer var;
if (!g_module_symbol(module, symbol, &var)) {
g_warning("Failed to load symbol '%s' from plugin '%s'",
symbol, name);
var = NULL;
}
return var;
}
static Plugin *plugin_new(char *name)
{
Plugin *p;
char *path;
p = g_new(Plugin, 1);
path = g_build_filename(PLUGINDIR, name, NULL);
p->module = g_module_open(path, 0);
g_free(path);
if (p->module == NULL) {
path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
NULL);
p->module = g_module_open(path, 0);
g_free(path);
}
if (p->module == NULL) {
g_free(p);
return NULL;
}
p->startup = load_sym(p->module, name, "plugin_startup");
p->shutdown = load_sym(p->module, name, "plugin_shutdown");
if (p->startup == NULL || p->shutdown == NULL) {
g_module_close(p->module);
g_free(p);
return NULL;
}
p->name = g_strdup(name);
return p;
}
static void plugin_free(Plugin *p)
{
p->shutdown();
g_free(p->name);
g_module_close(p->module);
}
static GData *plugins = NULL;
void plugin_startup()
{
g_datalist_init(&plugins);
}
void plugin_shutdown()
{
g_datalist_clear(&plugins);
}
gboolean plugin_open(char *name)
{
Plugin *p;
if (g_datalist_get_data(&plugins, name) != NULL) {
g_warning("plugin '%s' already loaded, can't load again", name);
return TRUE;
}
p = plugin_new(name);
if (p == NULL) {
g_warning("failed to load plugin '%s'", name);
return FALSE;
}
g_datalist_set_data_full(&plugins, name, p, (GDestroyNotify) plugin_free);
p->startup();
return TRUE;
}
void plugin_close(char *name)
{
g_datalist_remove_data(&plugins, name);
}
|