/* * Copyright (c) 2003-2008 by FlashCode * See README for License detail, AUTHORS for developers list. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* plugin.c: manages WeeChat plugins (dynamic C libraries) */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include "../core/weechat.h" #include "../core/wee-config.h" #include "../core/wee-hook.h" #include "../core/wee-infolist.h" #include "../core/wee-list.h" #include "../core/wee-log.h" #include "../core/wee-network.h" #include "../core/wee-string.h" #include "../core/wee-upgrade-file.h" #include "../core/wee-utf8.h" #include "../core/wee-util.h" #include "../gui/gui-bar.h" #include "../gui/gui-bar-item.h" #include "../gui/gui-buffer.h" #include "../gui/gui-chat.h" #include "../gui/gui-nicklist.h" #include "../gui/gui-window.h" #include "plugin.h" #include "plugin-api.h" #include "plugin-config.h" struct t_weechat_plugin *weechat_plugins = NULL; struct t_weechat_plugin *last_weechat_plugin = NULL; int plugin_argc; /* command line arguments (used only */ char **plugin_argv; /* first time loading plugin) */ /* * plugin_valid: check if a plugin pointer exists * return 1 if plugin exists * 0 if plugin is not found */ int plugin_valid (struct t_weechat_plugin *plugin) { struct t_weechat_plugin *ptr_plugin; if (!plugin) return 0; for (ptr_plugin = weechat_plugins; ptr_plugin; ptr_plugin = ptr_plugin->next_plugin) { if (ptr_plugin == plugin) return 1; } /* plugin not found */ return 0; } /* * plugin_search: search a plugin by name */ struct t_weechat_plugin * plugin_search (const char *name) { struct t_weechat_plugin *ptr_plugin; if (!name) return NULL; for (ptr_plugin = weechat_plugins; ptr_plugin; ptr_plugin = ptr_plugin->next_plugin) { if (string_strcasecmp (ptr_plugin->name, name) == 0) return ptr_plugin; } /* plugin not found */ return NULL; } /* * plugin_get_name: get name of plugin with a pointer */ const char * plugin_get_name (struct t_weechat_plugin *plugin) { static char *plugin_core = PLUGIN_CORE; return (plugin) ? plugin->name : plugin_core; } /* * plugin_load: load a WeeChat plugin (a dynamic library) * return: pointer to new WeeChat plugin, NULL if error */ struct t_weechat_plugin * plugin_load (const char *filename) { char *ptr_home, *full_name, *full_name2; void *handle; char *name, *author, *description, *version, *weechat_version, *license; char *charset; t_weechat_init_func *init_func; int rc, i, argc; char **argv; struct t_weechat_plugin *new_plugin; struct t_config_option *ptr_option; if (!filename) return NULL; full_name = util_search_full_lib_name (filename, "plugins"); if (!full_name) return NULL; ptr_home = getenv ("HOME"); full_name2 = string_replace (full_name, "~", ptr_home); if (full_name2) { free (full_name); full_name = full_name2; } handle = dlopen (full_name, RTLD_GLOBAL | RTLD_NOW); if (!handle) { gui_chat_printf (NULL, _("%sError: unable to load plugin \"%s\": %s"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], full_name, dlerror()); free (full_name); return NULL; } /* look for plugin name */ name = dlsym (handle, "weechat_plugin_name"); if (!name) { gui_chat_printf (NULL, _("%sError: symbol \"%s\" not found in " "plugin \"%s\", failed to load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "weechat_plugin_name", full_name); dlclose (handle); free (full_name); return NULL; } /* check for plugin with same name */ if (plugin_search (name)) { gui_chat_printf (NULL, _("%sError: unable to load plugin \"%s\": a plugin " "with same name already exists"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], full_name); dlclose (handle); free (full_name); return NULL; } /* look for plugin description */ description = dlsym (handle, "weechat_plugin_description"); if (!description) { gui_chat_printf (NULL, _("%sError: symbol \"%s\" not found " "in plugin \"%s\", failed to load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "weechat_plugin_description", full_name); dlclose (handle); free (full_name); return NULL; } /* look for plugin author */ author = dlsym (handle, "weechat_plugin_author"); if (!author) { gui_chat_printf (NULL, _("%sError: symbol \"%s\" not found " "in plugin \"%s\", failed to load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "weechat_plugin_author", full_name); dlclose (handle); free (full_name); return NULL; } /* look for plugin version */ version = dlsym (handle, "weechat_plugin_version"); if (!version) { gui_chat_printf (NULL, _("%sError: symbol \"%s\" not found in " "plugin \"%s\", failed to load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "weechat_plugin_version", full_name); dlclose (handle); free (full_name); return NULL; } /* look for WeeChat version required for plugin */ weechat_version = dlsym (handle, "weechat_plugin_weechat_version"); if (!weechat_version) { gui_chat_printf (NULL, _("%sError: symbol \"%s\" not found in " "plugin \"%s\", failed to load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "weechat_plugin_weechat_version", full_name); dlclose (handle); free (full_name); return NULL; } if (util_weechat_version_cmp (PACKAGE_VERSION, weechat_version) != 0) { gui_chat_printf (NULL, _("%sError: plugin \"%s\" is compiled for WeeChat " "%s and you are running version %s, failed to " "load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], full_name, weechat_version, PACKAGE_VERSION); dlclose (handle); free (full_name); return NULL; } /* look for plugin license */ license = dlsym (handle, "weechat_plugin_license"); if (!license) { gui_chat_printf (NULL, _("%sError: symbol \"%s\" not found in " "plugin \"%s\", failed to load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "weechat_plugin_license", full_name); dlclose (handle); free (full_name); return NULL; } /* look for plugin charset (optional, default is UTF-8) */ charset = dlsym (handle, "weechat_plugin_charset"); /* look for plugin init function */ init_func = dlsym (handle, "weechat_plugin_init"); if (!init_func) { gui_chat_printf (NULL, _("%sError: function \"%s\" not " "found in plugin \"%s\", failed to load"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], "weechat_plugin_init", full_name); dlclose (handle); free (full_name); return NULL; } /* create new plugin */ new_plugin = malloc (sizeof (*new_plugin)); if (new_plugin) { /* variables */ new_plugin->filename = strdup (full_name); new_plugin->handle = handle; new_plugin->name = strdup (name); new_plugin->description = strdup (description); new_plugin->author = strdup (author); new_plugin->version = strdup (version); new_plugin->weechat_version = strdup (weechat_version); new_plugin->license = strdup (license); new_plugin->charset = (charset) ? strdup (charset) : NULL; ptr_option = config_weechat_debug_get (name); new_plugin->debug = (ptr_option) ? CONFIG_INTEGER(ptr_option) : 0; /* functions */ new_plugin->plugin_get_name = &plugin_get_name; new_plugin->charset_set = &plugin_api_charset_set; new_plugin->iconv_to_internal = &string_iconv_to_internal; new_plugin->iconv_from_internal = &string_iconv_from_internal; new_plugin->gettext = &plugin_api_gettext; new_plugin->ngettext = &plugin_api_ngettext; new_plugin->strndup = &string_strndup; new_plugin->string_tolower = &string_tolower; new_plugin->string_toupper = &string_toupper; new_plugin->strcasecmp = &string_strcasecmp; new_plugin->strncasecmp = &string_strncasecmp; new_plugin->strcmp_ignore_chars = &string_strcmp_ignore_chars; new_plugin->strcasestr = &string_strcasestr; new_plugin->string_match = &string_match; new_plugin->string_replace = &string_replace; new_plugin->string_remove_quotes = &string_remove_quotes; new_plugin->string_strip = &string_strip; new_plugin->string_has_highlight = &string_has_highlight; new_plugin->string_mask_to_regex = &string_mask_to_regex; new_plugin->string_explode = &string_explode; new_plugin->string_free_exploded = &string_free_exploded; new_plugin->string_build_with_exploded = &string_build_with_exploded; new_plugin->string_split_command = &string_split_command; new_plugin->string_free_splitted_command = &string_free_splitted_command; new_plugin->utf8_has_8bits = &utf8_has_8bits; new_plugin->utf8_is_valid = &utf8_is_valid; new_plugin->utf8_normalize = &utf8_normalize; new_plugin->utf8_prev_char = &utf8_prev_char; new_plugin->utf8_next_char = &utf8_next_char; new_plugin->utf8_char_size = &utf8_char_size; new_plugin->utf8_strlen = &utf8_strlen; new_plugin->utf8_strnlen = &utf8_strnlen; new_plugin->utf8_strlen_screen = &utf8_strlen_screen; new_plugin->utf8_charcasecmp = &utf8_charcasecmp; new_plugin->utf8_char_size_screen = &utf8_char_size_screen; new_plugin->utf8_add_offset = &utf8_add_offset; new_plugin->utf8_real_pos = &utf8_real_pos; new_plugin->utf8_pos = &utf8_pos; new_plugin->utf8_strndup = &utf8_strndup; new_plugin->mkdir_home = &util_mkdir_home; new_plugin->mkdir = &util_mkdir; new_plugin->mkdir_parents = &util_mkdir_parents; new_plugin->exec_on_files = &util_exec_on_files; new_plugin->timeval_cmp = &util_timeval_cmp; new_plugin->timeval_diff = &util_timeval_diff; new_plugin->timeval_add = &util_timeval_add; new_plugin->list_new = &weelist_new; new_plugin->list_add = &weelist_add; new_plugin->list_search = &weelist_search; new_plugin->list_casesearch = &weelist_casesearch; new_plugin->list_get = &weelist_get; new_plugin->list_set = &weelist_set; new_plugin->list_next = &weelist_next; new_plugin->list_prev = &weelist_prev; new_plugin->list_string = &weelist_string; new_plugin->list_size = &weelist_size; new_plugin->list_remove = &weelist_remove; new_plugin->list_remove_all = &weelist_remove_all; new_plugin->list_free = &weelist_free; new_plugin->config_new = &config_file_new; new_plugin->config_new_section = &config_file_new_section; new_plugin->config_search_section = &config_file_search_section; new_plugin->config_new_option = &config_file_new_option; new_plugin->config_search_option = &config_file_search_option; new_plugin->config_search_section_option = &config_file_search_section_option; new_plugin->config_search_with_string = &config_file_search_with_string; new_plugin->config_string_to_boolean = &config_file_string_to_boolean; new_plugin->config_option_reset = &config_file_option_reset; new_plugin->config_option_set = &config_file_option_set; new_plugin->config_option_unset = &config_file_option_unset; new_plugin->config_option_rename = &config_file_option_rename; new_plugin->config_option_get_pointer = &config_file_option_get_pointer; new_plugin->config_boolean = &config_file_option_boolean; new_plugin->config_integer = &config_file_option_integer; new_plugin->config_string = &config_file_option_string; new_plugin->config_color = &config_file_option_color; new_plugin->config_write_line = &config_file_write_line; new_plugin->config_write = &config_file_write; new_plugin->config_read = &config_file_read; new_plugin->config_reload = &config_file_reload; new_plugin->config_option_free = &config_file_option_free; new_plugin->config_section_free_options = &config_file_section_free_options; new_plugin->config_section_free = &config_file_section_free; new_plugin->config_free = &config_file_free; new_plugin->config_get = &plugin_api_config_get; new_plugin->config_get_plugin = &plugin_api_config_get_plugin; new_plugin->config_set_plugin = &plugin_api_config_set_plugin; new_plugin->prefix = &plugin_api_prefix; new_plugin->color = &plugin_api_color; new_plugin->printf_date_tags = &gui_chat_printf_date_tags; new_plugin->printf_y = &gui_chat_printf_y; new_plugin->log_printf = &log_printf; new_plugin->hook_command = &hook_command; new_plugin->hook_timer = &hook_timer; new_plugin->hook_fd = &hook_fd; new_plugin->hook_connect = &hook_connect; new_plugin->hook_print = &hook_print; new_plugin->hook_signal = &hook_signal; new_plugin->hook_signal_send = &hook_signal_send; new_plugin->hook_config = &hook_config; new_plugin->hook_completion = &hook_completion; new_plugin->hook_completion_list_add = &hook_completion_list_add; new_plugin->hook_modifier = &hook_modifier; new_plugin->hook_modifier_exec = &hook_modifier_exec; new_plugin->hook_info = &hook_info; new_plugin->hook_infolist = &hook_infolist; new_plugin->unhook = &unhook; new_plugin->unhook_all = &unhook_all_plugin; new_plugin->buffer_new = &gui_buffer_new; new_plugin->buffer_search = &gui_buffer_search_by_name; new_plugin->buffer_clear = &gui_buffer_clear; new_plugin->buffer_close = &gui_buffer_close; new_plugin->buffer_get_integer = &gui_buffer_get_integer; new_plugin->buffer_get_string = &gui_buffer_get_string; new_plugin->buffer_get_pointer = &gui_buffer_get_pointer; new_plugin->buffer_set = &gui_buffer_set; new_plugin->buffer_set_pointer = &gui_buffer_set_pointer; new_plugin->buffer_string_replace_local_var = &gui_buffer_string_replace_local_var; new_plugin->window_get_integer = &gui_window_get_integer; new_plugin->window_get_string = &gui_window_get_string; new_plugin->window_get_pointer = &gui_window_get_pointer; new_plugin->nicklist_add_group = &gui_nicklist_add_group; new_plugin->nicklist_search_group = &gui_nicklist_search_group; new_plugin->nicklist_add_nick = &gui_nicklist_add_nick; new_plugin->nicklist_search_nick = &gui_nicklist_search_nick; new_plugin->nicklist_remove_group = &gui_nicklist_remove_group; new_plugin->nicklist_remove_nick = &gui_nicklist_remove_nick; new_plugin->nicklist_remove_all = &gui_nicklist_remove_all; new_plugin->bar_item_search = &gui_bar_item_search; new_plugin->bar_item_new = &gui_bar_item_new; new_plugin->bar_item_update = &gui_bar_item_update; new_plugin->bar_item_remove = &gui_bar_item_free; new_plugin->bar_search = &gui_bar_search; new_plugin->bar_new = &gui_bar_new; new_plugin->bar_set = &gui_bar_set; new_plugin->bar_update = &gui_bar_update; new_plugin->bar_remove = &gui_bar_free; new_plugin->command = &plugin_api_command; new_plugin->network_pass_proxy = &network_pass_proxy; new_plugin->network_connect_to = &network_connect_to; new_plugin->info_get = &hook_info_get; new_plugin->infolist_new = &infolist_new; new_plugin->infolist_new_item = &infolist_new_item; new_plugin->infolist_new_var_integer = &infolist_new_var_integer; new_plugin->infolist_new_var_string = &infolist_new_var_string; new_plugin->infolist_new_var_pointer = &infolist_new_var_pointer; new_plugin->infolist_new_var_buffer = &infolist_new_var_buffer; new_plugin->infolist_new_var_time = &infolist_new_var_time; new_plugin->infolist_get = &hook_infolist_get; new_plugin->infolist_next = &plugin_api_infolist_next; new_plugin->infolist_prev = &plugin_api_infolist_prev; new_plugin->infolist_reset_item_cursor = &plugin_api_infolist_reset_item_cursor; new_plugin->infolist_fields = &plugin_api_infolist_fields; new_plugin->infolist_integer = &plugin_api_infolist_integer; new_plugin->infolist_string = &plugin_api_infolist_string; new_plugin->infolist_pointer = &plugin_api_infolist_pointer; new_plugin->infolist_buffer = &plugin_api_infolist_buffer; new_plugin->infolist_time = &plugin_api_infolist_time; new_plugin->infolist_free = &plugin_api_infolist_free; new_plugin->upgrade_create = &upgrade_file_create; new_plugin->upgrade_write_object = &upgrade_file_write_object; new_plugin->upgrade_read = &upgrade_file_read; new_plugin->upgrade_close = &upgrade_file_close; /* add new plugin to list */ new_plugin->prev_plugin = last_weechat_plugin; new_plugin->next_plugin = NULL; if (weechat_plugins) last_weechat_plugin->next_plugin = new_plugin; else weechat_plugins = new_plugin; last_weechat_plugin = new_plugin; /* associate orphan buffers with this plugin (if asked during upgrade process) */ gui_buffer_set_plugin_for_upgrade (name, new_plugin); /* build arguments for plugin */ argc = 0; argv = NULL; if (plugin_argc > 0) { argv = malloc ((plugin_argc + 1) * sizeof (*argv)); if (argv) { argc = 0; for (i = 0; i < plugin_argc; i++) { if ((string_strcasecmp (plugin_argv[i], "-a") == 0) || (string_strcasecmp (plugin_argv[i], "--no-connect") == 0) || (string_strcasecmp (plugin_argv[i], "--upgrade") == 0) || (string_strncasecmp (plugin_argv[i], name, strlen (name)) == 0)) { argv[argc] = plugin_argv[i]; argc++; } } if (argc == 0) { free (argv); argv = NULL; } else argv[argc] = NULL; } } /* init plugin */ rc = ((t_weechat_init_func *)init_func) (new_plugin, argc, argv); if (argv) free (argv); if (rc != WEECHAT_RC_OK) { gui_chat_printf (NULL, _("%sError: unable to initialize plugin " "\"%s\""), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], full_name); plugin_remove (new_plugin); free (full_name); return NULL; } } else { gui_chat_printf (NULL, _("%sError: unable to load plugin \"%s\" " "(not enough memory)"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], full_name); dlclose (handle); free (full_name); return NULL; } gui_chat_printf (NULL, _("Plugin \"%s\" loaded"), name); free (full_name); return new_plugin; } /* * plugin_auto_load_file: load a file found by plugin_auto_load, * but only it this is really a dynamic library */ void plugin_auto_load_file (void *plugin, const char *filename) { char *pos; /* make C compiler happy */ (void) plugin; if (CONFIG_STRING(config_plugin_extension) && CONFIG_STRING(config_plugin_extension)[0]) { pos = strstr (filename, CONFIG_STRING(config_plugin_extension)); if (pos) { if (string_strcasecmp (pos, CONFIG_STRING(config_plugin_extension)) == 0) { plugin_load (filename); } } } else plugin_load (filename); } /* * plugin_auto_load: auto-load WeeChat plugins */ void plugin_auto_load () { char *ptr_home, *dir_name, *plugin_path, *plugin_path2; char *list_plugins, *pos, *pos2; if (CONFIG_STRING(config_plugin_autoload) && CONFIG_STRING(config_plugin_autoload)[0]) { if (string_strcasecmp (CONFIG_STRING(config_plugin_autoload), "*") == 0) { /* auto-load plugins in WeeChat home dir */ if (CONFIG_STRING(config_plugin_path) && CONFIG_STRING(config_plugin_path)[0]) { ptr_home = getenv ("HOME"); plugin_path = string_replace (CONFIG_STRING(config_plugin_path), "~", ptr_home); plugin_path2 = string_replace ((plugin_path) ? plugin_path : CONFIG_STRING(config_plugin_path), "%h", weechat_home); util_exec_on_files ((plugin_path2) ? plugin_path2 : ((plugin_path) ? plugin_path : CONFIG_STRING(config_plugin_path)), NULL, &plugin_auto_load_file); if (plugin_path) free (plugin_path); if (plugin_path2) free (plugin_path2); } /* auto-load plugins in WeeChat global lib dir */ dir_name = malloc (strlen (WEECHAT_LIBDIR) + 16); if (dir_name) { snprintf (dir_name, strlen (WEECHAT_LIBDIR) + 16, "%s/plugins", WEECHAT_LIBDIR); util_exec_on_files (dir_name, NULL, &plugin_auto_load_file); free (dir_name); } } else { list_plugins = strdup (CONFIG_STRING(config_plugin_autoload)); if (list_plugins) { pos = list_plugins; while (pos && pos[0]) { pos2 = strchr (pos, ','); if (pos2) pos2[0] = '\0'; plugin_load (pos); if (pos2) pos = pos2 + 1; else pos = NULL; } free (list_plugins); } } } } /* * plugin_remove: remove a WeeChat plugin */ void plugin_remove (struct t_weechat_plugin *plugin) { struct t_weechat_plugin *new_weechat_plugins; struct t_gui_buffer *ptr_buffer, *next_buffer; /* close buffers created by this plugin */ ptr_buffer = gui_buffers; while (ptr_buffer) { next_buffer = ptr_buffer->next_buffer; if (ptr_buffer->plugin == plugin) gui_buffer_close (ptr_buffer); ptr_buffer = next_buffer; } /* remove plugin from list */ if (last_weechat_plugin == plugin) last_weechat_plugin = plugin->prev_plugin; if (plugin->prev_plugin) { (plugin->prev_plugin)->next_plugin = plugin->next_plugin; new_weechat_plugins = weechat_plugins; } else new_weechat_plugins = plugin->next_plugin; if (plugin->next_plugin) (plugin->next_plugin)->prev_plugin = plugin->prev_plugin; /* remove all config files */ config_file_free_all_plugin (plugin); /* remove all hooks */ unhook_all_plugin (plugin); /* remove all bar items */ gui_bar_item_free_all_plugin (plugin); /* free data */ if (plugin->filename) free (plugin->filename); dlclose (plugin->handle); if (plugin->name) free (plugin->name); if (plugin->description) free (plugin->description); if (plugin->author) free (plugin->author); if (plugin->version) free (plugin->version); if (plugin->weechat_version) free (plugin->weechat_version); if (plugin->license) free (plugin->license); if (plugin->charset) free (plugin->charset); free (plugin); weechat_plugins = new_weechat_plugins; } /* * plugin_unload: unload a WeeChat plugin */ void plugin_unload (struct t_weechat_plugin *plugin) { t_weechat_end_func *end_func; char *name; name = (plugin->name) ? strdup (plugin->name) : NULL; end_func = dlsym (plugin->handle, "weechat_plugin_end"); if (end_func) (void) (end_func) (plugin); plugin_remove (plugin); gui_chat_printf (NULL, _("Plugin \"%s\" unloaded"), (name) ? name : "???"); if (name) free (name); } /* * plugin_unload_name: unload a WeeChat plugin by name */ void plugin_unload_name (const char *name) { struct t_weechat_plugin *ptr_plugin; ptr_plugin = plugin_search (name); if (ptr_plugin) plugin_unload (ptr_plugin); else { gui_chat_printf (NULL, _("%sError: plugin \"%s\" not found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], name); } } /* * plugin_unload_all: unload all WeeChat plugins */ void plugin_unload_all () { while (weechat_plugins) { plugin_unload (last_weechat_plugin); } } /* * plugin_reload_name: reload a WeeChat plugin by name */ void plugin_reload_name (const char *name) { struct t_weechat_plugin *ptr_plugin; char *filename; ptr_plugin = plugin_search (name); if (ptr_plugin) { filename = strdup (ptr_plugin->filename); if (filename) { plugin_unload (ptr_plugin); gui_chat_printf (NULL, _("Plugin \"%s\" unloaded"), name); plugin_load (filename); free (filename); } } else { gui_chat_printf (NULL, _("%sError: plugin \"%s\" not found"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], name); } } /* * plugin_init: init plugin support */ void plugin_init (int auto_load, int argc, char *argv[]) { plugin_argc = argc; plugin_argv = argv; /* init plugin API (create some hooks) */ plugin_api_init (); /* read plugins options on disk */ plugin_config_init (); plugin_config_read (); /* auto-load plugins if asked */ if (auto_load) plugin_auto_load (); /* discard command arguments for future plugins */ plugin_argc = 0; plugin_argv = NULL; } /* * plugin_end: end plugin support */ void plugin_end () { /* write plugins config options */ plugin_config_write (); /* unload all plugins */ plugin_unload_all (); /* free all plugin options */ plugin_config_end (); } /* * plugin_add_to_infolist: add a plugin in an infolist * return 1 if ok, 0 if error */ int plugin_add_to_infolist (struct t_infolist *infolist, struct t_weechat_plugin *plugin) { struct t_infolist_item *ptr_item; if (!infolist || !plugin) return 0; ptr_item = infolist_new_item (infolist); if (!ptr_item) return 0; if (!infolist_new_var_pointer (ptr_item, "pointer", plugin)) return 0; if (!infolist_new_var_string (ptr_item, "filename", plugin->filename)) return 0; if (!infolist_new_var_pointer (ptr_item, "handle", plugin->handle)) return 0; if (!infolist_new_var_string (ptr_item, "description", plugin->description)) return 0; if (!infolist_new_var_string (ptr_item, "author", plugin->author)) return 0; if (!infolist_new_var_string (ptr_item, "version", plugin->version)) return 0; if (!infolist_new_var_string (ptr_item, "weechat_version", plugin->weechat_version)) return 0; if (!infolist_new_var_string (ptr_item, "license", plugin->license)) return 0; if (!infolist_new_var_string (ptr_item, "charset", plugin->charset)) return 0; if (!infolist_new_var_integer (ptr_item, "debug", plugin->debug)) return 0; return 1; } /* * plugin_print_log: print plugin infos in log (usually for crash dump) */ void plugin_print_log () { struct t_weechat_plugin *ptr_plugin; for (ptr_plugin = weechat_plugins; ptr_plugin; ptr_plugin = ptr_plugin->next_plugin) { log_printf (""); log_printf ("[plugin (addr:0x%lx)]", ptr_plugin); log_printf (" filename . . . . . . . : '%s'", ptr_plugin->filename); log_printf (" handle . . . . . . . . : 0x%lx", ptr_plugin->handle); log_printf (" name . . . . . . . . . : '%s'", ptr_plugin->name); log_printf (" description. . . . . . : '%s'", ptr_plugin->description); log_printf (" version. . . . . . . . : '%s'", ptr_plugin->version); log_printf (" charset. . . . . . . . : '%s'", ptr_plugin->charset); log_printf (" debug. . . . . . . . . : %d", ptr_plugin->debug); log_printf (" prev_plugin. . . . . . : 0x%lx", ptr_plugin->prev_plugin); log_printf (" next_plugin. . . . . . : 0x%lx", ptr_plugin->next_plugin); } }