diff options
author | James Booth <boothj5@gmail.com> | 2016-07-12 23:50:21 +0100 |
---|---|---|
committer | James Booth <boothj5@gmail.com> | 2016-07-12 23:50:21 +0100 |
commit | 0991699ae65387dc67852a3f9d465de25d6067a0 (patch) | |
tree | 93ac5aab454e6d2b7a281deb0441965c5242f47a /src | |
parent | 5f393a6d9f995a9be86923f24e8b634a7a9d4ed9 (diff) | |
download | profani-tty-0991699ae65387dc67852a3f9d465de25d6067a0.tar.gz |
Add /plugins install command
Diffstat (limited to 'src')
-rw-r--r-- | src/command/cmd_ac.c | 218 | ||||
-rw-r--r-- | src/command/cmd_defs.c | 7 | ||||
-rw-r--r-- | src/command/cmd_funcs.c | 45 | ||||
-rw-r--r-- | src/common.c | 26 | ||||
-rw-r--r-- | src/common.h | 1 | ||||
-rw-r--r-- | src/plugins/plugins.c | 26 | ||||
-rw-r--r-- | src/plugins/plugins.h | 1 |
7 files changed, 218 insertions, 106 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 09383edf..d738b455 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -57,6 +57,8 @@ #include "pgp/gpg.h" #endif +static char* _complete_filepath(const char *const input, char *const startstr); + static char* _sub_autocomplete(ProfWin *window, const char *const input); static char* _notify_autocomplete(ProfWin *window, const char *const input); static char* _theme_autocomplete(ProfWin *window, const char *const input); @@ -187,7 +189,7 @@ static Autocomplete plugins_ac; static Autocomplete plugins_load_ac; static Autocomplete plugins_unload_ac; static Autocomplete plugins_reload_ac; -static Autocomplete sendfile_ac; +static Autocomplete filepath_ac; static Autocomplete blocked_ac; static Autocomplete tray_ac; static Autocomplete presence_ac; @@ -705,11 +707,12 @@ cmd_ac_init(void) autocomplete_add(autoping_ac, "timeout"); plugins_ac = autocomplete_new(); + autocomplete_add(plugins_ac, "install"); autocomplete_add(plugins_ac, "load"); autocomplete_add(plugins_ac, "unload"); autocomplete_add(plugins_ac, "reload"); - sendfile_ac = autocomplete_new(); + filepath_ac = autocomplete_new(); blocked_ac = autocomplete_new(); autocomplete_add(blocked_ac, "add"); @@ -903,7 +906,7 @@ cmd_ac_reset(ProfWin *window) autocomplete_reset(notify_mention_ac); autocomplete_reset(notify_trigger_ac); autocomplete_reset(sub_ac); - autocomplete_reset(sendfile_ac); + autocomplete_reset(filepath_ac); autocomplete_reset(who_room_ac); autocomplete_reset(who_roster_ac); @@ -1111,7 +1114,7 @@ cmd_ac_uninit(void) autocomplete_free(plugins_load_ac); autocomplete_free(plugins_unload_ac); autocomplete_free(plugins_reload_ac); - autocomplete_free(sendfile_ac); + autocomplete_free(filepath_ac); autocomplete_free(blocked_ac); autocomplete_free(tray_ac); autocomplete_free(presence_ac); @@ -1890,6 +1893,10 @@ _plugins_autocomplete(ProfWin *window, const char *const input) { char *result = NULL; + if (strncmp(input, "/plugins install ", 17) == 0) { + return _complete_filepath(input, "/plugins install"); + } + if (strncmp(input, "/plugins load ", 14) == 0) { if (plugins_load_ac == NULL) { plugins_load_ac = autocomplete_new(); @@ -2719,107 +2726,9 @@ _close_autocomplete(ProfWin *window, const char *const input) static char* _sendfile_autocomplete(ProfWin *window, const char *const input) { - static char* last_directory = NULL; - - unsigned int output_off = 0; - - char *result = NULL; - char *tmp; - - // strip command - char *inpcp = (char*)input + 9; - while (*inpcp == ' ') { - inpcp++; - } - - inpcp = strdup(inpcp); - - // strip quotes - if (*inpcp == '"') { - tmp = strchr(inpcp+1, '"'); - if (tmp) { - *tmp = '\0'; - } - tmp = strdup(inpcp+1); - free(inpcp); - inpcp = tmp; - } - - // expand ~ to $HOME - if (inpcp[0] == '~' && inpcp[1] == '/') { - if (asprintf(&tmp, "%s/%sfoo", getenv("HOME"), inpcp+2) == -1) { - return NULL; - } - output_off = strlen(getenv("HOME"))+1; - } else { - if (asprintf(&tmp, "%sfoo", inpcp) == -1) { - return NULL; - } - } - free(inpcp); - inpcp = tmp; - - char* inpcp2 = strdup(inpcp); - char* foofile = strdup(basename(inpcp2)); - char* directory = strdup(dirname(inpcp)); - free(inpcp); - free(inpcp2); - - if (!last_directory || strcmp(last_directory, directory) != 0) { - free(last_directory); - last_directory = directory; - autocomplete_reset(sendfile_ac); - - struct dirent *dir; - - DIR *d = opendir(directory); - if (d) { - while ((dir = readdir(d)) != NULL) { - if (strcmp(dir->d_name, ".") == 0) { - continue; - } else if (strcmp(dir->d_name, "..") == 0) { - continue; - } else if (*(dir->d_name) == '.' && *foofile != '.') { - // only show hidden files on explicit request - continue; - } - char * acstring; - if (output_off) { - if (asprintf(&tmp, "%s/%s", directory, dir->d_name) == -1) { - return NULL; - } - if (asprintf(&acstring, "~/%s", tmp+output_off) == -1) { - return NULL; - } - free(tmp); - } else if (strcmp(directory, "/") == 0) { - if (asprintf(&acstring, "/%s", dir->d_name) == -1) { - return NULL; - } - } else { - if (asprintf(&acstring, "%s/%s", directory, dir->d_name) == -1) { - return NULL; - } - } - autocomplete_add(sendfile_ac, acstring); - free(acstring); - } - closedir(d); - } - } else { - free(foofile); - free(directory); - } - - result = autocomplete_param_with_ac(input, "/sendfile", sendfile_ac, TRUE); - if (result) { - return result; - } - - return NULL; + return _complete_filepath(input, "/sendfile"); } - static char* _subject_autocomplete(ProfWin *window, const char *const input) { @@ -3019,3 +2928,106 @@ _presence_autocomplete(ProfWin *window, const char *const input) return NULL; } + +static char* +_complete_filepath(const char *const input, char *const startstr) +{ + static char* last_directory = NULL; + + unsigned int output_off = 0; + + char *result = NULL; + char *tmp; + + // strip command + char *inpcp = (char*)input + strlen(startstr); + while (*inpcp == ' ') { + inpcp++; + } + + inpcp = strdup(inpcp); + + // strip quotes + if (*inpcp == '"') { + tmp = strchr(inpcp+1, '"'); + if (tmp) { + *tmp = '\0'; + } + tmp = strdup(inpcp+1); + free(inpcp); + inpcp = tmp; + } + + // expand ~ to $HOME + if (inpcp[0] == '~' && inpcp[1] == '/') { + if (asprintf(&tmp, "%s/%sfoo", getenv("HOME"), inpcp+2) == -1) { + return NULL; + } + output_off = strlen(getenv("HOME"))+1; + } else { + if (asprintf(&tmp, "%sfoo", inpcp) == -1) { + return NULL; + } + } + free(inpcp); + inpcp = tmp; + + char* inpcp2 = strdup(inpcp); + char* foofile = strdup(basename(inpcp2)); + char* directory = strdup(dirname(inpcp)); + free(inpcp); + free(inpcp2); + + if (!last_directory || strcmp(last_directory, directory) != 0) { + free(last_directory); + last_directory = directory; + autocomplete_reset(filepath_ac); + + struct dirent *dir; + + DIR *d = opendir(directory); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (strcmp(dir->d_name, ".") == 0) { + continue; + } else if (strcmp(dir->d_name, "..") == 0) { + continue; + } else if (*(dir->d_name) == '.' && *foofile != '.') { + // only show hidden files on explicit request + continue; + } + char * acstring; + if (output_off) { + if (asprintf(&tmp, "%s/%s", directory, dir->d_name) == -1) { + return NULL; + } + if (asprintf(&acstring, "~/%s", tmp+output_off) == -1) { + return NULL; + } + free(tmp); + } else if (strcmp(directory, "/") == 0) { + if (asprintf(&acstring, "/%s", dir->d_name) == -1) { + return NULL; + } + } else { + if (asprintf(&acstring, "%s/%s", directory, dir->d_name) == -1) { + return NULL; + } + } + autocomplete_add(filepath_ac, acstring); + free(acstring); + } + closedir(d); + } + } else { + free(foofile); + free(directory); + } + + result = autocomplete_param_with_ac(input, startstr, filepath_ac, TRUE); + if (result) { + return result; + } + + return NULL; +} diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 1a94605a..a9fc3089 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -1979,16 +1979,19 @@ static struct cmd_t command_defs[] = CMD_NOTAGS CMD_SYN( "/plugins", + "/plugins install <path>", "/plugins unload <plugin>", "/plugins load <plugin>", "/plugins reload [<plugin>]") CMD_DESC( "Manage plugins. Passing no arguments lists currently loaded plugins.") CMD_ARGS( - { "load <plugin>", "Load a plugin." }, - { "unload <plugin>", "Unload a plugin." }, + { "install <file>", "Install file to plugins directory, and load or reload the plugin." }, + { "load <plugin>", "Load a plugin that already exists in the plugin directory." }, + { "unload <plugin>", "Unload a loaded plugin." }, { "reload [<plugin>]", "Reload a plugin, passing no argument will reload all plugins" }) CMD_EXAMPLES( + "/plugin install /home/steveharris/Downloads/metal.py", "/plugin load browser.py", "/plugin unload say.py", "/plugin reload wikipedia.py") diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index fcce7028..05de90a5 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -6025,7 +6025,50 @@ cmd_xa(ProfWin *window, const char *const command, gchar **args) gboolean cmd_plugins(ProfWin *window, const char *const command, gchar **args) { - if (g_strcmp0(args[0], "load") == 0) { + if (g_strcmp0(args[0], "install") == 0) { + char *filename = args[1]; + if (filename == NULL) { + cons_bad_cmd_usage(command); + return TRUE; + } + + // expand ~ to $HOME + if (filename[0] == '~' && filename[1] == '/') { + if (asprintf(&filename, "%s/%s", getenv("HOME"), filename+2) == -1) { + return TRUE; + } + } else { + filename = strdup(filename); + } + + if (access(filename, R_OK) != 0) { + cons_show("File not found: %s", filename); + free(filename); + return TRUE; + } + + if (!is_regular_file(filename)) { + cons_show("Not a file: %s", filename); + free(filename); + return TRUE; + } + + if (!g_str_has_suffix(filename, ".py") && !g_str_has_suffix(filename, ".so")) { + cons_show("Plugins must have one of the following extensions: '.py' '.so'"); + free(filename); + return TRUE; + } + + char *plugin_name = basename(filename); + gboolean result = plugins_install(plugin_name, filename); + if (result) { + cons_show("Plugin installed, use '/plugin load %s' to enable the plugin.", plugin_name); + } else { + cons_show("Failed to install plugin: %s", plugin_name); + } + + return TRUE; + } else if (g_strcmp0(args[0], "load") == 0) { if (args[1] == NULL) { cons_bad_cmd_usage(command); return TRUE; diff --git a/src/common.c b/src/common.c index 13a2366c..efa459de 100644 --- a/src/common.c +++ b/src/common.c @@ -38,6 +38,7 @@ #include <assert.h> #include <stdlib.h> #include <stdint.h> +#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> @@ -155,6 +156,31 @@ mkdir_recursive(const char *dir) return result; } +gboolean +copy_file(const char *const sourcepath, const char *const targetpath) +{ + int ch; + FILE *source = fopen(sourcepath, "rb"); + if (source == NULL) { + return FALSE; + } + + FILE *target = fopen(targetpath, "wb"); + if (target == NULL) { + fclose(source); + return FALSE; + } + + while((ch = fgetc(source)) != EOF) { + fputc(ch, target); + } + + fclose(source); + fclose(target); + + return TRUE; +} + char* str_replace(const char *string, const char *substr, const char *replacement) diff --git a/src/common.h b/src/common.h index c67b1460..ca6900dc 100644 --- a/src/common.h +++ b/src/common.h @@ -102,6 +102,7 @@ gboolean p_hash_table_contains(GHashTable *hash_table, gconstpointer key); gboolean create_dir(char *name); gboolean mkdir_recursive(const char *dir); +gboolean copy_file(const char *const src, const char *const target); char* str_replace(const char *string, const char *substr, const char *replacement); int str_contains(const char str[], int size, char ch); gboolean strtoi_range(char *str, int *saveptr, int min, int max, char **err_msg); diff --git a/src/plugins/plugins.c b/src/plugins/plugins.c index 24eb40d2..5096bdee 100644 --- a/src/plugins/plugins.c +++ b/src/plugins/plugins.c @@ -62,6 +62,8 @@ static GHashTable *plugins; +static gchar* _get_plugins_dir(void); + void plugins_init(void) { @@ -129,6 +131,30 @@ plugins_init(void) } gboolean +plugins_install(const char *const plugin_name, const char *const filename) +{ + char *plugins_dir = _get_plugins_dir(); + GString *target_path = g_string_new(plugins_dir); + free(plugins_dir); + g_string_append(target_path, "/"); + g_string_append(target_path, plugin_name); + + ProfPlugin *plugin = g_hash_table_lookup(plugins, plugin_name); + if (plugin) { + plugins_unload(plugin_name); + } + + gboolean result = copy_file(filename, target_path->str); + g_string_free(target_path, TRUE); + + if (result) { + result = plugins_load(plugin_name); + } + + return result; +} + +gboolean plugins_load(const char *const name) { ProfPlugin *plugin = g_hash_table_lookup(plugins, name); diff --git a/src/plugins/plugins.h b/src/plugins/plugins.h index fc10c363..28f00ab4 100644 --- a/src/plugins/plugins.h +++ b/src/plugins/plugins.h @@ -105,6 +105,7 @@ char* plugins_autocomplete(const char *const input); void plugins_reset_autocomplete(void); void plugins_shutdown(void); +gboolean plugins_install(const char *const plugin_name, const char *const filename); gboolean plugins_load(const char *const name); gboolean plugins_unload(const char *const name); gboolean plugins_reload(const char *const name); |