add strict ansi compliance
[dana/openbox.git] / openbox / plugin.c
1 #include <glib.h>
2 #include <gmodule.h>
3
4 typedef void (*PluginStartup)();
5 typedef void (*PluginShutdown)();
6
7 typedef struct {
8     GModule *module;
9     char *name;
10
11     PluginStartup startup;
12     PluginShutdown shutdown;
13 } Plugin;
14
15 static gpointer load_sym(GModule *module, char *name, char *symbol)
16 {
17     gpointer var;
18     if (!g_module_symbol(module, symbol, &var)) {
19         g_warning("Failed to load symbol '%s' from plugin '%s'",
20                   symbol, name);
21         var = NULL;
22     }
23     return var;
24 }
25
26 static Plugin *plugin_new(char *name)
27 {
28     Plugin *p;
29     char *path;
30    
31     p = g_new(Plugin, 1);
32
33     path = g_build_filename(PLUGINDIR, name, NULL);
34     p->module = g_module_open(path, 0);
35     g_free(path);
36
37     if (p->module == NULL) {
38         path = g_build_filename(g_get_home_dir(), ".openbox", "plugins", name,
39                                 NULL);
40         p->module = g_module_open(path, 0);
41         g_free(path);
42     }
43
44     if (p->module == NULL) {
45         g_free(p);
46         return NULL;
47     }
48
49     p->startup = (PluginStartup)load_sym(p->module, name, "plugin_startup");
50     p->shutdown = (PluginShutdown)load_sym(p->module, name, "plugin_shutdown");
51
52     if (p->startup == NULL || p->shutdown == NULL) {
53         g_module_close(p->module);
54         g_free(p);
55         return NULL;
56     }
57
58     p->name = g_strdup(name);
59     return p;
60 }
61
62 static void plugin_free(Plugin *p)
63 {
64     p->shutdown();
65
66     g_free(p->name);
67     g_module_close(p->module);
68 }
69
70
71 static GData *plugins = NULL;
72
73 void plugin_startup()
74 {
75     g_datalist_init(&plugins);
76 }
77
78 void plugin_shutdown()
79 {
80     g_datalist_clear(&plugins);
81 }
82
83 gboolean plugin_open(char *name)
84 {
85     Plugin *p;
86
87     if (g_datalist_get_data(&plugins, name) != NULL) {
88         g_warning("plugin '%s' already loaded, can't load again", name);
89         return TRUE;
90     }
91
92     p = plugin_new(name);
93     if (p == NULL) {
94         g_warning("failed to load plugin '%s'", name);
95         return FALSE;
96     }
97
98     g_datalist_set_data_full(&plugins, name, p,  (GDestroyNotify) plugin_free);
99     p->startup();
100     return TRUE;
101 }
102
103 void plugin_close(char *name)
104 {
105     g_datalist_remove_data(&plugins, name);
106 }