1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-09-22 19:45:54 -04:00

WIP - Unload plugin commands

This commit is contained in:
James Booth 2016-06-29 23:35:57 +01:00
parent 61a09476c5
commit a01eb5d08e
21 changed files with 162 additions and 21 deletions

View File

@ -702,6 +702,7 @@ cmd_ac_init(void)
plugins_ac = autocomplete_new(); plugins_ac = autocomplete_new();
autocomplete_add(plugins_ac, "load"); autocomplete_add(plugins_ac, "load");
autocomplete_add(plugins_ac, "unload");
sendfile_ac = autocomplete_new(); sendfile_ac = autocomplete_new();
@ -784,6 +785,14 @@ cmd_ac_remove(const char *const value)
} }
} }
void
cmd_ac_remove_help(const char *const value)
{
if (help_ac) {
autocomplete_remove(help_ac, value);
}
}
gboolean gboolean
cmd_ac_exists(char *cmd) cmd_ac_exists(char *cmd)
{ {

View File

@ -48,6 +48,7 @@ void cmd_ac_add_alias(ProfAlias *alias);
void cmd_ac_add_alias_value(char *value); void cmd_ac_add_alias_value(char *value);
void cmd_ac_remove(const char *const value); void cmd_ac_remove(const char *const value);
void cmd_ac_remove_help(const char *const value);
void cmd_ac_remove_alias_value(char *value); void cmd_ac_remove_alias_value(char *value);
gboolean cmd_ac_exists(char *cmd); gboolean cmd_ac_exists(char *cmd);

View File

@ -1979,13 +1979,16 @@ static struct cmd_t command_defs[] =
CMD_NOTAGS CMD_NOTAGS
CMD_SYN( CMD_SYN(
"/plugins", "/plugins",
"/plugins load <plugin>") "/plugins load <plugin>",
"/plugins unload <plugin>")
CMD_DESC( CMD_DESC(
"Manage plugins. Passing no arguments lists currently loaded plugins.") "Manage plugins. Passing no arguments lists currently loaded plugins.")
CMD_ARGS( CMD_ARGS(
{ "load <plugin>", "Load a plugin." }) { "load <plugin>", "Load a plugin." },
{ "unload <plugin>", "Unload a plugin." })
CMD_EXAMPLES( CMD_EXAMPLES(
"/plugin load browser.py") "/plugin load browser.py",
"/plugin unload pid.so")
}, },
{ "/prefs", { "/prefs",

View File

@ -95,6 +95,49 @@ static gboolean _cmd_execute(ProfWin *window, const char *const command, const c
static gboolean _cmd_execute_default(ProfWin *window, const char *inp); static gboolean _cmd_execute_default(ProfWin *window, const char *inp);
static gboolean _cmd_execute_alias(ProfWin *window, const char *const inp, gboolean *ran); static gboolean _cmd_execute_alias(ProfWin *window, const char *const inp, gboolean *ran);
void
command_help_free(CommandHelp *help)
{
free(help->desc);
if (help->tags) {
int i = 0;
while (i < 20 && help->tags[i]) {
free(help->tags[i]);
i++;
}
free(help->tags);
}
if (help->synopsis) {
int i = 0;
while (i < 50 && help->synopsis[i]) {
free(help->synopsis[i]);
i++;
}
free(help->synopsis);
}
if (help->examples) {
int i = 0;
while (i < 20 && help->examples[i]) {
free(help->examples[i]);
i++;
}
free(help->examples);
}
if (help->args) {
int i = 0;
while (i < 120 && help->args[i]) {
free(help->args[i][0]);
free(help->args[i][1]);
free(help->args[i]);
}
free(help->args);
}
}
/* /*
* Take a line of input and process it, return TRUE if profanity is to * Take a line of input and process it, return TRUE if profanity is to
* continue, FALSE otherwise * continue, FALSE otherwise
@ -3809,7 +3852,7 @@ cmd_form(ProfWin *window, const char *const command, gchar **args)
} else { } else {
mucconfwin_form_help(confwin); mucconfwin_form_help(confwin);
const gchar **help_text = NULL; gchar **help_text = NULL;
Command *command = cmd_get("/form"); Command *command = cmd_get("/form");
if (command) { if (command) {
@ -6038,6 +6081,16 @@ cmd_plugins(ProfWin *window, const char *const command, gchar **args)
cons_show("Failed to load plugin: %s", args[1]); cons_show("Failed to load plugin: %s", args[1]);
} }
return TRUE;
} else if (g_strcmp0(args[0], "unload") == 0) {
if (args[1] == NULL) {
cons_bad_cmd_usage(command);
return TRUE;
}
plugins_unload(args[1]);
prefs_remove_plugin(args[1]);
cons_show("Unloaded plugin: %s", args[1]);
return TRUE; return TRUE;
} else { } else {
GSList *plugins = plugins_get_list(); GSList *plugins = plugins_get_list();

View File

@ -39,11 +39,11 @@
// Command help strings // Command help strings
typedef struct cmd_help_t { typedef struct cmd_help_t {
const gchar *tags[20]; gchar *tags[20];
const gchar *synopsis[50]; gchar *synopsis[50];
const gchar *desc; gchar *desc;
const gchar *args[128][2]; gchar *args[128][2];
const gchar *examples[20]; gchar *examples[20];
} CommandHelp; } CommandHelp;
/* /*
@ -69,6 +69,7 @@ typedef struct cmd_t {
CommandHelp help; CommandHelp help;
} Command; } Command;
void command_help_free(CommandHelp *help);
gboolean cmd_process_input(ProfWin *window, char *inp); gboolean cmd_process_input(ProfWin *window, char *inp);
void cmd_execute_connect(ProfWin *window, const char *const account); void cmd_execute_connect(ProfWin *window, const char *const account);

View File

@ -631,6 +631,13 @@ prefs_add_plugin(const char *const name)
_save_prefs(); _save_prefs();
} }
void
prefs_remove_plugin(const char *const name)
{
conf_string_list_remove(prefs, "plugins", "load", name);
_save_prefs();
}
void void
prefs_free_plugins(gchar **plugins) prefs_free_plugins(gchar **plugins)
{ {

View File

@ -191,6 +191,7 @@ void prefs_set_autoxa_time(gint value);
gchar** prefs_get_plugins(void); gchar** prefs_get_plugins(void);
void prefs_free_plugins(gchar **plugins); void prefs_free_plugins(gchar **plugins);
void prefs_add_plugin(const char *const name); void prefs_add_plugin(const char *const name);
void prefs_remove_plugin(const char *const name);
char prefs_get_otr_char(void); char prefs_get_otr_char(void);
void prefs_set_otr_char(char ch); void prefs_set_otr_char(char ch);

View File

@ -106,11 +106,12 @@ api_cons_bad_cmd_usage(const char *const cmd)
} }
void void
api_register_command(const char *command_name, int min_args, int max_args, api_register_command(char *plugin_name, char *command_name, int min_args, int max_args,
const char **synopsis, const char *description, const char *arguments[][2], const char **examples, void *callback, const char **synopsis, const char *description, const char *arguments[][2], const char **examples, void *callback,
void(*callback_func)(PluginCommand *command, gchar **args)) void(*callback_func)(PluginCommand *command, gchar **args))
{ {
PluginCommand *command = malloc(sizeof(PluginCommand)); PluginCommand *command = malloc(sizeof(PluginCommand));
command->plugin_name = plugin_name;
command->command_name = command_name; command->command_name = command_name;
command->min_args = min_args; command->min_args = min_args;
command->max_args = max_args; command->max_args = max_args;

View File

@ -50,7 +50,7 @@ gboolean api_current_win_is_console(void);
char* api_get_current_nick(void); char* api_get_current_nick(void);
char** api_get_current_occupants(void); char** api_get_current_occupants(void);
void api_register_command(const char *command_name, int min_args, int max_args, void api_register_command(char *plugin_name, char *command_name, int min_args, int max_args,
const char **synopsis, const char *description, const char *arguments[][2], const char **examples, const char **synopsis, const char *description, const char *arguments[][2], const char **examples,
void *callback, void(*callback_func)(PluginCommand *command, gchar **args)); void *callback, void(*callback_func)(PluginCommand *command, gchar **args));
void api_register_timed(void *callback, int interval_seconds, void api_register_timed(void *callback, int interval_seconds,

View File

@ -80,7 +80,7 @@ c_api_cons_bad_cmd_usage(const char *const cmd)
} }
static void static void
c_api_register_command(const char *filename, const char *command_name, int min_args, int max_args, c_api_register_command(const char *filename, char *command_name, int min_args, int max_args,
const char **synopsis, const char *description, const char *arguments[][2], const char **examples, const char **synopsis, const char *description, const char *arguments[][2], const char **examples,
void(*callback)(char **args)) void(*callback)(char **args))
{ {
@ -89,7 +89,7 @@ c_api_register_command(const char *filename, const char *command_name, int min_a
CommandWrapper *wrapper = malloc(sizeof(CommandWrapper)); CommandWrapper *wrapper = malloc(sizeof(CommandWrapper));
wrapper->func = callback; wrapper->func = callback;
api_register_command(command_name, min_args, max_args, synopsis, api_register_command(plugin_name, command_name, min_args, max_args, synopsis,
description, arguments, examples, wrapper, c_command_callback); description, arguments, examples, wrapper, c_command_callback);
} }

View File

@ -77,6 +77,40 @@ callbacks_add_command(PluginCommand *command)
cmd_ac_add_help(&command->command_name[1]); cmd_ac_add_help(&command->command_name[1]);
} }
void
_command_destroy(PluginCommand *command)
{
free(command->command_name);
free(command->plugin_name);
command_help_free(command->help);
// TODO free callback
}
void
callbacks_remove_commands(const char *const plugin_name)
{
GSList *items_to_remove = NULL;
GSList *curr = p_commands;
while (curr) {
PluginCommand *command = curr->data;
if (g_strcmp0(command->plugin_name, plugin_name) == 0) {
cmd_ac_remove(command->command_name);
cmd_ac_remove_help(&command->command_name[1]);
items_to_remove = g_slist_append(items_to_remove, curr);
}
curr = g_slist_next(curr);
}
curr = items_to_remove;
while (curr) {
GSList *item = curr->data;
PluginCommand *command = item->data;
_command_destroy(command);
p_commands = g_slist_remove_link(p_commands, item);
curr = g_slist_next(curr);
}
}
void void
callbacks_add_timed(PluginTimedFunction *timed_function) callbacks_add_timed(PluginTimedFunction *timed_function)
{ {

View File

@ -40,7 +40,8 @@
#include "command/cmd_defs.h" #include "command/cmd_defs.h"
typedef struct p_command { typedef struct p_command {
const char *command_name; char *plugin_name;
char *command_name;
int min_args; int min_args;
int max_args; int max_args;
CommandHelp *help; CommandHelp *help;
@ -65,6 +66,7 @@ void callbacks_init(void);
void callbacks_close(void); void callbacks_close(void);
void callbacks_add_command(PluginCommand *command); void callbacks_add_command(PluginCommand *command);
void callbacks_remove_commands(const char *const plugin_name);
void callbacks_add_timed(PluginTimedFunction *timed_function); void callbacks_add_timed(PluginTimedFunction *timed_function);
void callbacks_add_window_handler(const char *tag, PluginWindowCallback *window_callback); void callbacks_add_window_handler(const char *tag, PluginWindowCallback *window_callback);
void * callbacks_get_window_handler(const char *tag); void * callbacks_get_window_handler(const char *tag);

View File

@ -172,6 +172,33 @@ plugins_load(const char *const name)
} }
} }
gboolean
plugins_unload(const char *const name)
{
GSList *found = g_slist_find_custom(plugins, name, (GCompareFunc)_find_by_name);
if (!found) {
log_info("Failed to unload plugin: %s, plugin not currently loaded", name);
return FALSE;
}
plugins = g_slist_remove_link(plugins, found);
#ifdef HAVE_PYTHON
if (g_str_has_suffix(name, ".py")) {
python_plugin_destroy(found->data);
}
#endif
#ifdef HAVE_C
if (g_str_has_suffix(name, ".so")) {
c_plugin_destroy(found->data);
}
#endif
g_slist_free(found);
return TRUE;
}
GSList * GSList *
plugins_get_list(void) plugins_get_list(void)
{ {

View File

@ -105,6 +105,7 @@ void plugins_reset_autocomplete(void);
void plugins_shutdown(void); void plugins_shutdown(void);
gboolean plugins_load(const char *const name); gboolean plugins_load(const char *const name);
gboolean plugins_unload(const char *const name);
void plugins_on_start(void); void plugins_on_start(void);
void plugins_on_shutdown(void); void plugins_on_shutdown(void);

View File

@ -42,7 +42,7 @@ int (*prof_cons_show)(const char * const message) = NULL;
int (*prof_cons_show_themed)(const char *const group, const char *const item, const char *const def, const char *const message) = NULL; int (*prof_cons_show_themed)(const char *const group, const char *const item, const char *const def, const char *const message) = NULL;
int (*prof_cons_bad_cmd_usage)(const char *const cmd) = NULL; int (*prof_cons_bad_cmd_usage)(const char *const cmd) = NULL;
void (*_prof_register_command)(const char *filename, const char *command_name, int min_args, int max_args, void (*_prof_register_command)(const char *filename, char *command_name, int min_args, int max_args,
const char **synopsis, const char *description, const char *arguments[][2], const char **examples, const char **synopsis, const char *description, const char *arguments[][2], const char **examples,
void(*callback)(char **args)) = NULL; void(*callback)(char **args)) = NULL;

View File

@ -46,7 +46,7 @@ int (*prof_cons_show)(const char * const message);
int (*prof_cons_show_themed)(const char *const group, const char *const item, const char *const def, const char *const message); int (*prof_cons_show_themed)(const char *const group, const char *const item, const char *const def, const char *const message);
int (*prof_cons_bad_cmd_usage)(const char *const cmd); int (*prof_cons_bad_cmd_usage)(const char *const cmd);
void (*_prof_register_command)(const char *filename, const char *command_name, int min_args, int max_args, void (*_prof_register_command)(const char *filename, char *command_name, int min_args, int max_args,
const char **synopsis, const char *description, const char *arguments[][2], const char **examples, const char **synopsis, const char *description, const char *arguments[][2], const char **examples,
void(*callback)(char **args)); void(*callback)(char **args));

View File

@ -105,7 +105,7 @@ python_api_cons_bad_cmd_usage(PyObject *self, PyObject *args)
static PyObject* static PyObject*
python_api_register_command(PyObject *self, PyObject *args) python_api_register_command(PyObject *self, PyObject *args)
{ {
const char *command_name = NULL; char *command_name = NULL;
int min_args = 0; int min_args = 0;
int max_args = 0; int max_args = 0;
PyObject *synopsis = NULL; PyObject *synopsis = NULL;
@ -165,7 +165,7 @@ python_api_register_command(PyObject *self, PyObject *args)
c_examples[len] = NULL; c_examples[len] = NULL;
allow_python_threads(); allow_python_threads();
api_register_command(command_name, min_args, max_args, c_synopsis, api_register_command(plugin_name, command_name, min_args, max_args, c_synopsis,
description, c_arguments, c_examples, p_callback, python_command_callback); description, c_arguments, c_examples, p_callback, python_command_callback);
disable_python_threads(); disable_python_threads();
} }

View File

@ -888,6 +888,7 @@ python_check_error(void)
void void
python_plugin_destroy(ProfPlugin *plugin) python_plugin_destroy(ProfPlugin *plugin)
{ {
callbacks_remove_commands(plugin->name);
disable_python_threads(); disable_python_threads();
free(plugin->name); free(plugin->name);
Py_XDECREF(plugin->module); Py_XDECREF(plugin->module);

View File

@ -1230,7 +1230,7 @@ ui_handle_room_config_submit_result_error(const char *const roomjid, const char
} }
void void
ui_show_lines(ProfWin *window, const gchar** lines) ui_show_lines(ProfWin *window, gchar** lines)
{ {
if (lines) { if (lines) {
int i; int i;

View File

@ -110,7 +110,7 @@ void ui_goodbye_title(void);
void ui_handle_room_configuration_form_error(const char *const roomjid, const char *const message); void ui_handle_room_configuration_form_error(const char *const roomjid, const char *const message);
void ui_handle_room_config_submit_result(const char *const roomjid); void ui_handle_room_config_submit_result(const char *const roomjid);
void ui_handle_room_config_submit_result_error(const char *const roomjid, const char *const message); void ui_handle_room_config_submit_result_error(const char *const roomjid, const char *const message);
void ui_show_lines(ProfWin *window, const gchar** lines); void ui_show_lines(ProfWin *window, gchar** lines);
void ui_redraw_all_room_rosters(void); void ui_redraw_all_room_rosters(void);
void ui_show_all_room_rosters(void); void ui_show_all_room_rosters(void);
void ui_hide_all_room_rosters(void); void ui_hide_all_room_rosters(void);

View File

@ -265,7 +265,7 @@ void mucconfwin_show_form(ProfMucConfWin *confwin) {}
void mucconfwin_show_form_field(ProfMucConfWin *confwin, DataForm *form, char *tag) {} void mucconfwin_show_form_field(ProfMucConfWin *confwin, DataForm *form, char *tag) {}
void mucconfwin_form_help(ProfMucConfWin *confwin) {} void mucconfwin_form_help(ProfMucConfWin *confwin) {}
void mucconfwin_field_help(ProfMucConfWin *confwin, char *tag) {} void mucconfwin_field_help(ProfMucConfWin *confwin, char *tag) {}
void ui_show_lines(ProfWin *window, const gchar** lines) {} void ui_show_lines(ProfWin *window, gchar** lines) {}
void ui_redraw_all_room_rosters(void) {} void ui_redraw_all_room_rosters(void) {}
void ui_show_all_room_rosters(void) {} void ui_show_all_room_rosters(void) {}
void ui_hide_all_room_rosters(void) {} void ui_hide_all_room_rosters(void) {}