Add optional filter args to 'help' command

This commit is contained in:
Andrew Bettison 2013-03-25 12:05:26 +10:30
parent 28a77abc18
commit a88234ce9d
5 changed files with 50 additions and 27 deletions

47
cli.c
View File

@ -4,19 +4,47 @@
#include "log.h"
#include "serval.h"
#include "rhizome.h"
#include "strbuf_helpers.h"
int cli_usage(const struct cli_schema *commands) {
printf("Usage:\n");
int cli_usage(const struct cli_schema *commands, XPRINTF xpf)
{
return cli_usage_args(0, NULL, commands, xpf);
}
int cli_usage_parsed(const struct cli_parsed *parsed, XPRINTF xpf)
{
if (parsed->varargi == -1)
return cli_usage(parsed->commands, xpf);
return cli_usage_args(parsed->argc - parsed->varargi, &parsed->args[parsed->varargi], parsed->commands, xpf);
}
int cli_usage_args(const int argc, const char *const *args, const struct cli_schema *commands, XPRINTF xpf)
{
unsigned cmd;
int matched_any = 0;
for (cmd = 0; commands[cmd].function; ++cmd) {
unsigned opt;
const char *word;
for (opt = 0; (word = commands[cmd].words[opt]); ++opt) {
if (word[0] == '\\')
++word;
printf(" %s", word);
int matched = 1;
for (opt = 0; matched && opt < argc && (word = commands[cmd].words[opt]); ++opt)
if (strncmp(word, args[opt], strlen(args[opt])) != 0)
matched = 0;
if (matched) {
matched_any = 1;
for (opt = 0; (word = commands[cmd].words[opt]); ++opt) {
if (word[0] == '\\')
++word;
xprintf(xpf, " %s", word);
}
xputc('\n', xpf);
if (commands[cmd].description && commands[cmd].description[0])
xprintf(xpf, " %s\n", commands[cmd].description);
}
printf("\n %s\n",commands[cmd].description);
}
if (!matched_any && argc) {
strbuf b = strbuf_alloca(160);
strbuf_append_argv(b, argc, args);
xprintf(xpf, " No commands matching %s\n", strbuf_str(b));
}
return 0;
}
@ -29,7 +57,8 @@ int cli_parse(const int argc, const char *const *args, const struct cli_schema *
for (cmd = 0; commands[cmd].function; ++cmd) {
struct cli_parsed cmdpa;
memset(&cmdpa, 0, sizeof cmdpa);
cmdpa.command = &commands[cmd];
cmdpa.commands = commands;
cmdpa.cmdi = cmd;
cmdpa.args = args;
cmdpa.argc = argc;
cmdpa.labelc = 0;
@ -202,7 +231,7 @@ void _debug_cli_parsed(struct __sourceloc __whence, const struct cli_parsed *par
int cli_invoke(const struct cli_parsed *parsed, void *context)
{
IN();
int ret = parsed->command->function(parsed, context);
int ret = parsed->commands[parsed->cmdi].function(parsed, context);
RETURN(ret);
OUT();
}

8
cli.h
View File

@ -20,6 +20,7 @@
#ifndef __SERVALD_CLI_H
#define __SERVALD_CLI_H
#include "xprintf.h"
#include "log.h"
#define COMMAND_LINE_MAX_LABELS (32)
@ -37,7 +38,8 @@ struct cli_schema {
};
struct cli_parsed {
const struct cli_schema *command;
const struct cli_schema *commands;
unsigned int cmdi;
struct labelv {
const char *label;
unsigned int len;
@ -53,7 +55,9 @@ void _debug_cli_parsed(struct __sourceloc __whence, const struct cli_parsed *par
#define DEBUG_cli_parsed(parsed) _debug_cli_parsed(__WHENCE__, parsed)
int cli_usage(const struct cli_schema *commands);
int cli_usage(const struct cli_schema *commands, XPRINTF xpf);
int cli_usage_args(const int argc, const char *const *args, const struct cli_schema *commands, XPRINTF xpf);
int cli_usage_parsed(const struct cli_parsed *parsed, XPRINTF xpf);
int cli_parse(const int argc, const char *const *args, const struct cli_schema *commands, struct cli_parsed *parsed);
int cli_invoke(const struct cli_parsed *parsed, void *context);
int _cli_arg(struct __sourceloc __whence, const struct cli_parsed *parsed, char *label, const char **dst, int (*validator)(const char *arg), char *defaultvalue);

View File

@ -49,8 +49,8 @@ extern struct cli_schema command_line_options[];
int commandline_usage(const struct cli_parsed *parsed, void *context)
{
printf("Serval DNA version %s\n", version_servald);
return cli_usage(command_line_options);
printf("Serval DNA version %s\nUsage:\n", version_servald);
return cli_usage_parsed(parsed, XPRINTF_STDIO(stdout));
}
/* Data structures for accumulating output of a single JNI call.
@ -225,7 +225,7 @@ int parseCommandLine(const char *argv0, int argc, const char *const *args)
int result = cli_parse(argc, args, command_line_options, &parsed);
if (result != -1) {
// Do not run the command if the configuration does not load ok
if (((parsed.command->flags & CLIFLAG_PERMISSIVE_CONFIG) ? cf_reload_permissive() : cf_reload()) != -1)
if (((parsed.commands[parsed.cmdi].flags & CLIFLAG_PERMISSIVE_CONFIG) ? cf_reload_permissive() : cf_reload()) != -1)
result = cli_invoke(&parsed, NULL);
else {
strbuf b = strbuf_alloca(160);
@ -2354,7 +2354,7 @@ int app_network_scan(const struct cli_parsed *parsed, void *context)
struct cli_schema command_line_options[]={
{app_dna_lookup,{"dna","lookup","<did>","[<timeout>]",NULL},0,
"Lookup the SIP/MDP address of the supplied telephone number (DID)."},
{commandline_usage,{"help",NULL},CLIFLAG_PERMISSIVE_CONFIG,
{commandline_usage,{"help","...",NULL},CLIFLAG_PERMISSIVE_CONFIG,
"Display command usage."},
{app_echo,{"echo","[-e]","[--]","...",NULL},CLIFLAG_STANDALONE,
"Output the supplied string."},

View File

@ -576,17 +576,7 @@ static int monitor_help(const struct cli_parsed *parsed, void *context)
struct monitor_context *c=context;
strbuf b = strbuf_alloca(16384);
strbuf_puts(b, "\nINFO:Usage\n");
unsigned cmd;
for (cmd = 0; monitor_commands[cmd].function; ++cmd) {
unsigned opt;
const char *word;
for (opt = 0; (word = monitor_commands[cmd].words[opt]); ++opt) {
if (word[0] == '\\')
++word;
strbuf_sprintf(b, " %s", word);
}
strbuf_puts(b, "\n");
}
cli_usage(monitor_commands, XPRINTF_STRBUF(b));
(void)write_all(c->alarm.poll.fd, strbuf_str(b), strbuf_len(b));
return 0;
}

View File

@ -256,7 +256,7 @@ struct cli_schema console_commands[]={
static int console_usage(const struct cli_parsed *parsed, void *context)
{
cli_usage(console_commands);
cli_usage(console_commands, XPRINTF_STDIO(stdout));
fflush(stdout);
return 0;
}