| 145 g_snprintf(buf, BUF_LEN - 1, "%s/%s", getenv("HOME"), PLUGIN_DIR); |
145 g_snprintf(buf, BUF_LEN - 1, "%s/%s", getenv("HOME"), PLUGIN_DIR); |
| 146 plug->filename = g_malloc(strlen(buf) + strlen(filename) + 1); |
146 plug->filename = g_malloc(strlen(buf) + strlen(filename) + 1); |
| 147 sprintf(plug->filename, "%s%s", buf, filename); |
147 sprintf(plug->filename, "%s%s", buf, filename); |
| 148 } else |
148 } else |
| 149 plug->filename = g_strdup(filename); |
149 plug->filename = g_strdup(filename); |
| |
150 sprintf(debug_buff, "Loading %s\n", filename); |
| |
151 debug_print(debug_buff); |
| 150 /* do NOT OR with RTLD_GLOBAL, otherwise plugins may conflict |
152 /* do NOT OR with RTLD_GLOBAL, otherwise plugins may conflict |
| 151 * (it's really just a way to work around other people's bad |
153 * (it's really just a way to work around other people's bad |
| 152 * programming, by not using RTLD_GLOBAL :P ) */ |
154 * programming, by not using RTLD_GLOBAL :P ) */ |
| 153 plug->handle = dlopen(plug->filename, RTLD_LAZY); |
155 plug->handle = dlopen(plug->filename, RTLD_LAZY); |
| 154 if (!plug->handle) { |
156 if (!plug->handle) { |
| 341 i = GTK_LIST(pluglist)->selection; |
343 i = GTK_LIST(pluglist)->selection; |
| 342 |
344 |
| 343 if (i == NULL) return; |
345 if (i == NULL) return; |
| 344 |
346 |
| 345 p = gtk_object_get_user_data(GTK_OBJECT(i->data)); |
347 p = gtk_object_get_user_data(GTK_OBJECT(i->data)); |
| |
348 sprintf(debug_buff, "Unloading %s\n", p->filename); |
| |
349 debug_print(debug_buff); |
| 346 |
350 |
| 347 gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove"); |
351 gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove"); |
| 348 if ((error = (char *)dlerror()) == NULL) |
352 if ((error = (char *)dlerror()) == NULL) |
| 349 (*gaim_plugin_remove)(); |
353 (*gaim_plugin_remove)(); |
| |
354 sprintf(debug_buff, "%d callbacks to search\n", g_list_length(callbacks)); |
| |
355 debug_print(debug_buff); |
| 350 while (c) { |
356 while (c) { |
| 351 g = (struct gaim_callback *)c->data; |
357 g = (struct gaim_callback *)c->data; |
| 352 if (g->handle == p->handle) { |
358 if (g->handle == p->handle) { |
| 353 callbacks = g_list_remove(callbacks, c->data); |
359 callbacks = g_list_remove(callbacks, c->data); |
| 354 g_free(g); |
360 g_free(g); |
| |
361 sprintf(debug_buff, "Removing callback, %d remain\n", |
| |
362 g_list_length(callbacks)); |
| |
363 debug_print(debug_buff); |
| 355 c = callbacks; |
364 c = callbacks; |
| 356 if (c == NULL) break; |
365 if (c == NULL) { |
| |
366 break; |
| |
367 } |
| |
368 } else { |
| |
369 c = c->next; |
| 357 } |
370 } |
| 358 c = c->next; |
371 } |
| 359 } |
372 dlclose(p->handle); |
| 360 /* don't ask me why this works */ |
|
| 361 if (callbacks != NULL) dlclose(p->handle); |
|
| 362 |
373 |
| 363 plugins = g_list_remove(plugins, p); |
374 plugins = g_list_remove(plugins, p); |
| 364 g_free(p->filename); |
375 g_free(p->filename); |
| 365 g_free(p); |
376 g_free(p); |
| 366 gtk_widget_set_sensitive(config, 0); |
377 gtk_widget_set_sensitive(config, 0); |
| 404 call->event = which; |
415 call->event = which; |
| 405 call->function = func; |
416 call->function = func; |
| 406 call->data = data; |
417 call->data = data; |
| 407 |
418 |
| 408 callbacks = g_list_append(callbacks, call); |
419 callbacks = g_list_append(callbacks, call); |
| |
420 sprintf(debug_buff, "Adding callback %d\n", g_list_length(callbacks)); |
| |
421 debug_print(debug_buff); |
| 409 } |
422 } |
| 410 |
423 |
| 411 void gaim_signal_disconnect(void *handle, enum gaim_event which, void *func) { |
424 void gaim_signal_disconnect(void *handle, enum gaim_event which, void *func) { |
| 412 GList *c = callbacks; |
425 GList *c = callbacks; |
| 413 struct gaim_callback *g = NULL; |
426 struct gaim_callback *g = NULL; |