diff options
Diffstat (limited to 'plugin.c')
-rw-r--r-- | plugin.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/plugin.c b/plugin.c new file mode 100644 index 0000000..c7d6b2e --- /dev/null +++ b/plugin.c @@ -0,0 +1,188 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "plugin.h" +#include "util/argconfig.h" + +static int version(struct plugin *plugin) +{ + struct program *prog = plugin->parent; + + if (plugin->name) + printf("%s %s version %s\n", prog->name, plugin->name, prog->version); + else + printf("%s version %s\n", prog->name, prog->version); + return 0; +} + +static int help(int argc, char **argv, struct plugin *plugin) +{ + char man[0x100]; + struct program *prog = plugin->parent; + char *str = argv[1]; + int i; + + if (argc == 1) { + general_help(plugin); + return 0; + } + + for (i = 0; plugin->commands[i]; i++) { + struct command *cmd = plugin->commands[i]; + + if (strcmp(str, cmd->name)) + if (!cmd->alias || (cmd->alias && strcmp(str, cmd->alias))) + continue; + + if (plugin->name) + sprintf(man, "%s-%s-%s", prog->name, plugin->name, cmd->name); + else + sprintf(man, "%s-%s", prog->name, cmd->name); + if (execlp("man", "man", man, (char *)NULL)) + perror(argv[1]); + } + return 0; +} + +void usage(struct plugin *plugin) +{ + struct program *prog = plugin->parent; + + if (plugin->name) + printf("usage: %s %s %s\n", prog->name, plugin->name, prog->usage); + else + printf("usage: %s %s\n", prog->name, prog->usage); +} + +void general_help(struct plugin *plugin) +{ + struct program *prog = plugin->parent; + struct plugin *extension; + unsigned i = 0; + unsigned padding = 15; + unsigned curr_length = 0; + printf("%s-%s\n", prog->name, prog->version); + + usage(plugin); + + printf("\n"); + print_word_wrapped(prog->desc, 0, 0); + printf("\n"); + + if (plugin->desc) { + printf("\n"); + print_word_wrapped(plugin->desc, 0, 0); + printf("\n"); + } + + printf("\nThe following are all implemented sub-commands:\n"); + + /* iterate through all commands to get maximum length */ + /* Still need to handle the case of ultra long strings, help messages, etc */ + for (; plugin->commands[i]; i++) + if (padding < (curr_length = 2 + strlen(plugin->commands[i]->name))) + padding = curr_length; + + i = 0; + for (; plugin->commands[i]; i++) + printf(" %-*s %s\n", padding, plugin->commands[i]->name, + plugin->commands[i]->help); + + printf(" %-*s %s\n", padding, "version", "Shows the program version"); + printf(" %-*s %s\n", padding, "help", "Display this help"); + printf("\n"); + + if (plugin->name) + printf("See '%s %s help <command>' for more information on a specific command\n", + prog->name, plugin->name); + else + printf("See '%s help <command>' for more information on a specific command\n", + prog->name); + + /* The first plugin is the built-in. If we're not showing help for the + * built-in, don't show the program's other extensions */ + if (plugin->name) + return; + + extension = prog->extensions->next; + if (!extension) + return; + + printf("\nThe following are all installed plugin extensions:\n"); + while (extension) { + printf(" %-*s %s\n", 15, extension->name, extension->desc); + extension = extension->next; + } + printf("\nSee '%s <plugin> help' for more information on a plugin\n", + prog->name); +} + +int handle_plugin(int argc, char **argv, struct plugin *plugin) +{ + unsigned i = 0; + char *str = argv[0]; + char use[0x100]; + + struct plugin *extension; + struct program *prog = plugin->parent; + + if (!argc) { + general_help(plugin); + return 0; + } + + if (!plugin->name) + sprintf(use, "%s %s <device> [OPTIONS]", prog->name, str); + else + sprintf(use, "%s %s %s <device> [OPTIONS]", prog->name, plugin->name, str); + argconfig_append_usage(use); + + /* translate --help and --version into commands */ + while (*str == '-') + str++; + + if (!strcmp(str, "help")) + return help(argc, argv, plugin); + if (!strcmp(str, "version")) + return version(plugin); + + for (; plugin->commands[i]; i++) { + struct command *cmd = plugin->commands[i]; + + if (strcmp(str, cmd->name)) + if (!cmd->alias || (cmd->alias && strcmp(str, cmd->alias))) + continue; + + return (cmd->fn(argc, argv, cmd, plugin)); + } + + /* Check extensions only if this is running the built-in plugin */ + if (plugin->name) { + printf("ERROR: Invalid sub-command '%s' for plugin %s\n", str, plugin->name); + return -ENOTTY; + } + + extension = plugin->next; + while (extension) { + if (!strcmp(str, extension->name)) + return handle_plugin(argc - 1, &argv[1], extension); + extension = extension->next; + } + + /* If the command is executed with the extension name and + * command together ("plugin-command"), run the plug in */ + extension = plugin->next; + while (extension) { + if (!strncmp(str, extension->name, strlen(extension->name))) { + argv[0] += strlen(extension->name); + while (*argv[0] == '-') + argv[0]++; + return handle_plugin(argc, &argv[0], extension); + } + extension = extension->next; + } + printf("ERROR: Invalid sub-command '%s'\n", str); + return -ENOTTY; +} |