comparison src/module.c @ 3551:cd938f18f3f8

[gaim-migrate @ 3626] In the interest of continued progress, I pulled what's usable out of my development tree and am committing it. Here, we have gotten rid of the plugins dialog and perl menu under Tools and put them both in preferences. Perl scripts now work like plugins--you have to load them explicitly (it will probe $prefix/lib/gaim and $HOME/.gaim for them) and you can unload them (although right now, this is entirely unreliable) Oh, and I broke all your perl scripts. Sorry about that. Don't try fixing them yet, though--I'm gonna make unloading single scripts more reliable tommorow. I should also finish Phase Two tommorow as well. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Thu, 26 Sep 2002 07:37:52 +0000
parents 6b0cb60162f4
children e120097bbd72
comparison
equal deleted inserted replaced
3550:e9b2003ee562 3551:cd938f18f3f8
34 #include <config.h> 34 #include <config.h>
35 #endif 35 #endif
36 36
37 #include "gaim.h" 37 #include "gaim.h"
38 38
39 #ifdef GAIM_PLUGINS
40
41 #include <string.h> 39 #include <string.h>
42 #include <sys/time.h> 40 #include <sys/time.h>
43 41
44 #include <sys/types.h> 42 #include <sys/types.h>
45 #include <sys/stat.h> 43 #include <sys/stat.h>
49 #include <stdlib.h> 47 #include <stdlib.h>
50 48
51 /* ------------------ Global Variables ----------------------- */ 49 /* ------------------ Global Variables ----------------------- */
52 50
53 GList *plugins = NULL; 51 GList *plugins = NULL;
52 GList *probed_plugins = NULL;
54 GList *callbacks = NULL; 53 GList *callbacks = NULL;
55 54
56 char *last_dir = NULL; 55 char *last_dir = NULL;
57 56
58 /* --------------- Function Declarations --------------------- */ 57 /* --------------- Function Declarations --------------------- */
59 58
60 struct gaim_plugin * load_plugin(const char *); 59 struct gaim_plugin * load_plugin(const char *);
60 #ifdef GAIM_PLUGINS
61 void unload_plugin(struct gaim_plugin *p); 61 void unload_plugin(struct gaim_plugin *p);
62 struct gaim_plugin *reload_plugin(struct gaim_plugin *p); 62 struct gaim_plugin *reload_plugin(struct gaim_plugin *p);
63
64 void gaim_signal_connect(GModule *, enum gaim_event, void *, void *); 63 void gaim_signal_connect(GModule *, enum gaim_event, void *, void *);
65 void gaim_signal_disconnect(GModule *, enum gaim_event, void *); 64 void gaim_signal_disconnect(GModule *, enum gaim_event, void *);
66 void gaim_plugin_unload(GModule *); 65 void gaim_plugin_unload(GModule *);
67 66
68 /* --------------- Static Function Declarations ------------- */ 67 /* --------------- Static Function Declarations ------------- */
69 68
70 static void plugin_remove_callbacks(GModule *); 69 static void plugin_remove_callbacks(GModule *);
71 70 #endif
72 /* ------------------ Code Below ---------------------------- */ 71 /* ------------------ Code Below ---------------------------- */
73 72
74 struct gaim_plugin *load_plugin(const char *filename) 73 static int is_so_file(char *filename, char *ext)
75 { 74 {
75 int len;
76 if (!filename) return 0;
77 if (!filename[0]) return 0;
78 len = strlen(filename);
79 len -= strlen(ext);
80 if (len < 0) return 0;
81 return (!strncmp(filename + len, ext, strlen(ext)));
82 }
83
84 void gaim_probe_plugins() {
85 GDir *dir;
86 const gchar *file;
87 gchar *path;
88 struct gaim_plugin_description *plugdes;
76 struct gaim_plugin *plug; 89 struct gaim_plugin *plug;
77 GList *c = plugins; 90 char userspace[128];
91 char *probedirs[] = {LIBDIR, &userspace, 0};
92 #if GAIM_PLUGINS
78 char *(*gaim_plugin_init)(GModule *); 93 char *(*gaim_plugin_init)(GModule *);
79 char *(*cfunc)(); 94 char *(*cfunc)();
80 char *error; 95 int l;
81 char *retval; 96 struct gaim_plugin_description *(*desc)();
97 GModule *handle;
98 #endif
99
100 g_snprintf(userspace, sizeof(userspace), "%s" G_DIR_SEPARATOR_S ".gaim", g_get_home_dir());
101
102 for (l=0; probedirs[l]; l++) {
103 dir = g_dir_open(probedirs[l], 0, NULL);
104 if (dir) {
105 while ((file = g_dir_read_name(dir))) {
106 #ifdef GAIM_PLUGINS
107 if (is_so_file(file, ".so") && g_module_supported()) {
108 path = g_build_filename(probedirs[l], file, NULL);
109 handle = g_module_open(path, 0);
110 if (!handle) {
111 debug_printf("%s is unloadable: %s\n", file, g_module_error());
112 continue;
113 }
114 if (!g_module_symbol(handle, "gaim_plugin_init", (gpointer *)&gaim_plugin_init)) {
115 debug_printf("%s is unloadable %s\n", file, g_module_error());
116 g_module_close(handle);
117 continue;
118 }
119 plug = g_new0(struct gaim_plugin, 1);
120 g_snprintf(plug->path, sizeof(plug->path), path);
121 plug->type = plugin;
122 g_free(path);
123 if (g_module_symbol(handle, "gaim_plugin_desc", (gpointer *)&desc)) {
124 memcpy(&(plug->desc), desc(), sizeof(plug->desc));
125 } else {
126 if (g_module_symbol(handle, "name", (gpointer *)&cfunc)) {
127 plug->desc.name = g_strdup(cfunc());
128 }
129 if (g_module_symbol(handle, "description", (gpointer *)&cfunc)) {
130 plug->desc.description = g_strdup(cfunc());
131 }
132 }
133 probed_plugins = g_list_append(probed_plugins, plug);
134 g_module_close(handle);
135 }
136 #endif
137 #ifdef USE_PERL
138 if (is_so_file(file, ".pl")) {
139 path = g_build_filename(LIBDIR, file, NULL);
140 plug = probe_perl(path);
141 if (plug)
142 probed_plugins = g_list_append(probed_plugins, plug);
143 g_free(path);
144 }
145 #endif
146 }
147 g_dir_close(dir);
148 }
149 }
150 }
151
152 #ifdef GAIM_PLUGINS
153 struct gaim_plugin *load_plugin(const char *filename)
154 {
155 struct gaim_plugin *plug;
156 struct gaim_plugin_description *desc;
157 struct gaim_plugin_description *(*gaim_plugin_desc)();
158 char *(*cfunc)();
159 GList *c = plugins;
160 GList *p = probed_plugins;
161 char *(*gaim_plugin_init)(GModule *);
162 char *error, *retval, *tmp;
163 gboolean newplug = FALSE;
82 164
83 if (!g_module_supported()) 165 if (!g_module_supported())
84 return NULL; 166 return NULL;
85 if (filename && !strlen(filename)) 167 if (!filename || !strlen(filename))
86 return NULL; 168 return NULL;
87 169
88 while (filename && c) { 170 while (filename && p) {
89 plug = (struct gaim_plugin *)c->data; 171 plug = (struct gaim_plugin *)p->data;
90 if (!strcmp(filename, g_module_name(plug->handle))) { 172 if (!strcmp(filename, plug->path))
91 /* just need to reload plugin */ 173 break;
92 return reload_plugin(plug); 174 p = p->next;
93 } else 175 }
94 c = g_list_next(c); 176
95 } 177 if (plug && plug->handle) {
96 plug = g_malloc(sizeof *plug); 178 reload_plugin(plug);
97 179 return NULL;
98 if (last_dir) 180 }
99 g_free(last_dir); 181
100 last_dir = g_dirname(filename); 182 if (!plug) {
101 183 plug = g_new0(struct gaim_plugin, 1);
184 g_snprintf(plug->path, sizeof(plug->path), filename);
185 newplug = TRUE;
186 }
187
102 debug_printf("Loading %s\n", filename); 188 debug_printf("Loading %s\n", filename);
103 plug->handle = g_module_open(filename, 0); 189 plug->handle = g_module_open(filename, 0);
104 if (!plug->handle) { 190 if (!plug->handle) {
105 error = (char *)g_module_error(); 191 error = (char *)g_module_error();
106 do_error_dialog(_("Gaim was unable to load your plugin."), error, GAIM_ERROR); 192 plug->handle = NULL;
107 g_free(plug); 193 tmp = plug->desc.description;
194 plug->desc.description = g_strdup_printf("<span weight=\"bold\" foreground=\"red\">%s</span>\n\n%s", error, tmp);
195 g_free(tmp);
108 return NULL; 196 return NULL;
109 } 197 }
110 198
111 if (!g_module_symbol(plug->handle, "gaim_plugin_init", (gpointer *)&gaim_plugin_init)) { 199 if (!g_module_symbol(plug->handle, "gaim_plugin_init", (gpointer *)&gaim_plugin_init)) {
112 do_error_dialog(_("Gaim was unable to load your plugin."), g_module_error(), GAIM_ERROR);
113 g_module_close(plug->handle); 200 g_module_close(plug->handle);
114 g_free(plug); 201 plug->handle = NULL;
202 tmp = plug->desc.description;
203 plug->desc.description = g_strdup_printf("<span foreground=\"red\">%s</span>\n\n%s", g_module_error(), tmp);
204 g_free(tmp);
115 return NULL; 205 return NULL;
116 } 206 }
117 207
118 retval = gaim_plugin_init(plug->handle); 208 retval = gaim_plugin_init(plug->handle);
119 debug_printf("loaded plugin returned %s\n", retval ? retval : "NULL"); 209 debug_printf("loaded plugin returned %s\n", retval ? retval : "NULL");
120 if (retval) { 210 if (retval) {
121 plugin_remove_callbacks(plug->handle); 211 plugin_remove_callbacks(plug->handle);
122 do_error_dialog("Gaim was unable to load your plugin.", retval, GAIM_ERROR); 212 do_error_dialog("Gaim was unable to load your plugin.", retval, GAIM_ERROR);
123 g_module_close(plug->handle); 213 g_module_close(plug->handle);
124 g_free(plug); 214 plug->handle = NULL;
125 return NULL; 215 return NULL;
126 } 216 }
127 217
128 plugins = g_list_append(plugins, plug); 218 plugins = g_list_append(plugins, plug);
129 219
130 if (g_module_symbol(plug->handle, "name", (gpointer *)&cfunc)) { 220 if (newplug) {
131 plug->name = cfunc(); 221 g_snprintf(plug->path, sizeof(plug->path), filename);
132 } else { 222 if (g_module_symbol(plug->handle, "gaim_plugin_desc", (gpointer *)&gaim_plugin_desc)) {
133 plug->name = NULL; 223 desc = gaim_plugin_desc();
134 } 224 plug->desc.name = desc->name;
135 225 } else {
136 if (g_module_symbol(plug->handle, "description", (gpointer *)&cfunc)) 226 if (g_module_symbol(plug->handle, "name", (gpointer *)&cfunc)) {
137 plug->description = cfunc(); 227 plug->desc.name = g_strdup(cfunc());
138 else 228 }
139 plug->description = NULL; 229 if (g_module_symbol(plug->handle, "description", (gpointer *)&cfunc)) {
140 230 plug->desc.description = g_strdup(cfunc());
231 }
232 }
233 probed_plugins = g_list_append(probed_plugins, plug);
234 }
235
141 save_prefs(); 236 save_prefs();
142 return plug; 237 return plug;
238
143 } 239 }
144 240
145 static void unload_gaim_plugin(struct gaim_plugin *p) 241 static void unload_gaim_plugin(struct gaim_plugin *p)
146 { 242 {
147 void (*gaim_plugin_remove)(); 243 void (*gaim_plugin_remove)();
153 gaim_plugin_remove(); 249 gaim_plugin_remove();
154 250
155 plugin_remove_callbacks(p->handle); 251 plugin_remove_callbacks(p->handle);
156 252
157 plugins = g_list_remove(plugins, p); 253 plugins = g_list_remove(plugins, p);
158 g_free(p); 254 p->handle = NULL;
159 save_prefs(); 255 save_prefs();
160 } 256 }
161 257
162 void unload_plugin(struct gaim_plugin *p) 258 void unload_plugin(struct gaim_plugin *p)
163 { 259 {
192 if (g_module_symbol(p->handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) 288 if (g_module_symbol(p->handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove))
193 gaim_plugin_remove(); 289 gaim_plugin_remove();
194 plugin_remove_callbacks(p->handle); 290 plugin_remove_callbacks(p->handle);
195 plugins = g_list_remove(plugins, p); 291 plugins = g_list_remove(plugins, p);
196 g_free(p); 292 g_free(p);
197 /* XXX CUI need to tell UI what happened, but not like this */ 293 /* XXX CUI need to tell UI what happened, but not like this
198 update_show_plugins(); 294 update_show_plugins(); */
199 295
200 g_timeout_add(5000, unload_timeout, handle); 296 g_timeout_add(5000, unload_timeout, handle);
201 } 297 }
202 298
203 /* Do unload/load cycle of plugin. */ 299 /* Do unload/load cycle of plugin. */
379 int plugin_event(enum gaim_event event, ...) 475 int plugin_event(enum gaim_event event, ...)
380 { 476 {
381 #ifdef GAIM_PLUGINS 477 #ifdef GAIM_PLUGINS
382 GList *c = callbacks; 478 GList *c = callbacks;
383 struct gaim_callback *g; 479 struct gaim_callback *g;
480 #endif
384 va_list arrg; 481 va_list arrg;
385 void *arg1 = NULL, 482 void *arg1 = NULL,
386 *arg2 = NULL, 483 *arg2 = NULL,
387 *arg3 = NULL, 484 *arg3 = NULL,
388 *arg4 = NULL, 485 *arg4 = NULL,
389 *arg5 = NULL; 486 *arg5 = NULL;
390 #endif 487
391 488
392 debug_printf("%s\n", event_name(event)); 489 debug_printf("%s\n", event_name(event));
393 490
394 #ifdef GAIM_PLUGINS 491 #ifdef GAIM_PLUGINS
395 while (c) { 492 while (c) {