mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-04-24 21:09:49 +00:00
Rewrite command-line parser
Now supports optional args followed by non-optional.
This commit is contained in:
parent
46513bf192
commit
fcb6600cd6
166
cli.c
166
cli.c
@ -5,77 +5,103 @@
|
||||
#include "serval.h"
|
||||
#include "rhizome.h"
|
||||
|
||||
int cli_usage(const struct command_line_option *options) {
|
||||
int cli_usage(const struct command_line_option *commands) {
|
||||
printf("Usage:\n");
|
||||
int i,j;
|
||||
for(i=0;options[i].function;i++) {
|
||||
for(j=0;options[i].words[j];j++)
|
||||
printf(" %s",options[i].words[j]);
|
||||
printf("\n %s\n",options[i].description);
|
||||
for(i=0;commands[i].function;i++) {
|
||||
for(j=0;commands[i].words[j];j++)
|
||||
printf(" %s",commands[i].words[j]);
|
||||
printf("\n %s\n",commands[i].description);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cli_parse(const int argc, const char *const *args, const struct command_line_option *options)
|
||||
static const char * parsed_add_label_arg(struct parsed_command *parsed, const char *label, unsigned labellen, unsigned argi)
|
||||
{
|
||||
int ambiguous=0;
|
||||
int cli_call=-1;
|
||||
int i;
|
||||
for(i=0;options[i].function;i++)
|
||||
{
|
||||
int j;
|
||||
if (parsed->labelc >= NELS(parsed->labelv))
|
||||
return "too many labeled args";
|
||||
parsed->labelv[parsed->labelc].label = label;
|
||||
parsed->labelv[parsed->labelc].len = labellen;
|
||||
parsed->labelv[parsed->labelc].argi = argi;
|
||||
++parsed->labelc;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cli_parse(const int argc, const char *const *args, const struct command_line_option *commands, struct parsed_command *parsed)
|
||||
{
|
||||
int ambiguous = 0;
|
||||
int matched_cmd = -1;
|
||||
int cmd;
|
||||
for (cmd = 0; commands[cmd].function; ++cmd) {
|
||||
struct parsed_command cmdpa;
|
||||
memset(&cmdpa, 0, sizeof cmdpa);
|
||||
cmdpa.command = &commands[cmd];
|
||||
cmdpa.args = args;
|
||||
cmdpa.argc = argc;
|
||||
cmdpa.labelc = 0;
|
||||
cmdpa.varargi = -1;
|
||||
const char *problem = NULL;
|
||||
const char *word = NULL;
|
||||
int optional = 0;
|
||||
int mandatory = 0;
|
||||
for (j = 0; (word = options[i].words[j]); ++j) {
|
||||
int arg, opt;
|
||||
for (arg = 0, opt = 0; !problem && (word = commands[cmd].words[opt]); ++opt) {
|
||||
int wordlen = strlen(word);
|
||||
if (optional < 0) {
|
||||
WHYF("Internal error: command_line_options[%d].word[%d]=\"%s\" not allowed after \"...\"", i, j, word);
|
||||
break;
|
||||
}
|
||||
else if (!( (wordlen > 2 && word[0] == '<' && word[wordlen-1] == '>')
|
||||
|| (wordlen > 4 && word[0] == '[' && word[1] == '<' && word[wordlen-2] == '>' && word[wordlen-1] == ']')
|
||||
|| (wordlen > 0)
|
||||
)) {
|
||||
WHYF("Internal error: command_line_options[%d].word[%d]=\"%s\" is malformed", i, j, word);
|
||||
break;
|
||||
} else if (word[0] == '<') {
|
||||
++mandatory;
|
||||
if (optional) {
|
||||
WHYF("Internal error: command_line_options[%d].word[%d]=\"%s\" should be optional", i, j, word);
|
||||
break;
|
||||
}
|
||||
} else if (word[0] == '[') {
|
||||
++optional;
|
||||
if (cmdpa.varargi != -1)
|
||||
problem = "more words not allowed after \"...\"";
|
||||
else if (wordlen > 4 && word[0] == '[' && word[1] == '<' && word[wordlen-2] == '>' && word[wordlen-1] == ']') {
|
||||
// "[<label>]" consumes one argument if available, records it with label "label".
|
||||
if (arg < argc)
|
||||
problem = parsed_add_label_arg(&cmdpa, &word[2], wordlen - 4, arg++);
|
||||
} else if (wordlen > 2 && word[0] == '[' && word[wordlen-1] == ']') {
|
||||
// "[word]" consumes one argument if it exactly matches "word", records it with label
|
||||
// "word".
|
||||
const char *endp = NULL;
|
||||
if (arg < argc && strncase_startswith(word + 1, wordlen - 2, args[arg], &endp) && endp == word + wordlen - 1)
|
||||
problem = parsed_add_label_arg(&cmdpa, &word[1], wordlen - 2, arg++);
|
||||
} else if (wordlen == 3 && word[0] == '.' && word[1] == '.' && word[2] == '.') {
|
||||
optional = -1;
|
||||
} else {
|
||||
++mandatory;
|
||||
if (j < argc && strcasecmp(word, args[j])) // literal words don't match
|
||||
// "..." consumes all remaining arguments.
|
||||
cmdpa.varargi = arg;
|
||||
arg = argc;
|
||||
} else if (wordlen > 2 && word[0] == '<' && word[wordlen-1] == '>') {
|
||||
// "<label>" consumes exactly one argument, records it with label "label".
|
||||
if (arg < argc)
|
||||
problem = parsed_add_label_arg(&cmdpa, &word[1], wordlen - 2, arg++);
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else if (wordlen > 0) {
|
||||
const char *endp = NULL;
|
||||
// "word" consumes exactly one argument which must exactly match "word".
|
||||
if (arg < argc && strncase_startswith(word, wordlen, args[arg], &endp) && endp == word + wordlen)
|
||||
++arg;
|
||||
else
|
||||
break;
|
||||
} else
|
||||
problem = "malformed";
|
||||
}
|
||||
if (!word && argc >= mandatory && (optional < 0 || argc <= mandatory + optional)) {
|
||||
if (problem)
|
||||
return WHYF("Internal error: commands[%d].word[%d]=\"%s\" - %s", cmd, opt - 1, word, problem);
|
||||
if (!word && arg == argc) {
|
||||
/* A match! We got through the command definition with no internal errors and all literal
|
||||
args matched and we have a proper number of args. If we have multiple matches, then note
|
||||
that the call is ambiguous. */
|
||||
if (cli_call>=0) ambiguous++;
|
||||
if (ambiguous==1) {
|
||||
if (matched_cmd >= 0)
|
||||
++ambiguous;
|
||||
if (ambiguous == 1) {
|
||||
WHY("Ambiguous command line call:");
|
||||
WHY_argv(" ", argc, args);
|
||||
WHY("Matches the following known command line calls:");
|
||||
WHY_argv(" ", argc, options[cli_call].words);
|
||||
WHY_argv(" ", argc, commands[matched_cmd].words);
|
||||
}
|
||||
if (ambiguous)
|
||||
WHY_argv(" ", argc, options[i].words);
|
||||
cli_call=i;
|
||||
WHY_argv(" ", argc, commands[cmd].words);
|
||||
matched_cmd = cmd;
|
||||
*parsed = cmdpa;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't process ambiguous calls */
|
||||
if (ambiguous) return -1;
|
||||
if (ambiguous)
|
||||
return -1;
|
||||
/* Complain if we found no matching calls */
|
||||
if (cli_call<0) {
|
||||
if (matched_cmd < 0) {
|
||||
if (argc) {
|
||||
WHY("Unknown command line call:");
|
||||
WHY_argv(" ", argc, args);
|
||||
@ -83,35 +109,43 @@ int cli_parse(const int argc, const char *const *args, const struct command_line
|
||||
INFO("Use \"help\" command to see a list of valid commands");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return cli_call;
|
||||
return matched_cmd;
|
||||
}
|
||||
|
||||
int cli_invoke(const struct command_line_option *option, const int argc, const char *const *args, void *context)
|
||||
void _debug_parsed(struct __sourceloc __whence, const struct parsed_command *parsed)
|
||||
{
|
||||
DEBUG_argv("command", parsed->argc, parsed->args);
|
||||
strbuf b = strbuf_alloca(1024);
|
||||
int i;
|
||||
for (i = 0; i < parsed->labelc; ++i) {
|
||||
const struct labelv *lab = &parsed->labelv[i];
|
||||
strbuf_sprintf(b, " %s=%d", alloca_toprint(-1, lab->label, lab->len), lab->argi);
|
||||
}
|
||||
if (parsed->varargi >= 0)
|
||||
strbuf_sprintf(b, " varargi=%d", parsed->varargi);
|
||||
DEBUGF("parsed%s", strbuf_str(b));
|
||||
}
|
||||
|
||||
int cli_invoke(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
IN();
|
||||
int ret=option->function(argc, args, option, context);
|
||||
int ret = parsed->command->function(parsed, context);
|
||||
RETURN(ret);
|
||||
}
|
||||
|
||||
int cli_arg(int argc, const char *const *argv, const struct command_line_option *o, char *argname, const char **dst, int (*validator)(const char *arg), char *defaultvalue)
|
||||
int cli_arg(const struct parsed_command *parsed, char *label, const char **dst, int (*validator)(const char *arg), char *defaultvalue)
|
||||
{
|
||||
int arglen = strlen(argname);
|
||||
int labellen = strlen(label);
|
||||
if (dst)
|
||||
*dst = defaultvalue;
|
||||
int i;
|
||||
const char *word;
|
||||
*dst = defaultvalue;
|
||||
for(i = 0; (word = o->words[i]); ++i) {
|
||||
int wordlen = strlen(word);
|
||||
/* No need to check that the "<...>" and "[<...>]" are all intact in the command_line_option,
|
||||
because that was already checked in parseCommandLine(). */
|
||||
if (i < argc
|
||||
&&( (wordlen == arglen + 2 && word[0] == '<' && !strncasecmp(&word[1], argname, arglen))
|
||||
|| (wordlen == arglen + 4 && word[0] == '[' && !strncasecmp(&word[2], argname, arglen)))
|
||||
) {
|
||||
const char *value = argv[i];
|
||||
for (i = 0; i < parsed->labelc; ++i) {
|
||||
if (parsed->labelv[i].len == labellen && strncasecmp(label, parsed->labelv[i].label, labellen) == 0) {
|
||||
const char *value = parsed->args[parsed->labelv[i].argi];
|
||||
if (validator && !(*validator)(value))
|
||||
return WHYF("Invalid argument %d '%s': \"%s\"", i + 1, argname, value);
|
||||
*dst = value;
|
||||
return WHYF("Invalid argument %d '%s': \"%s\"", i + 1, label, value);
|
||||
if (dst)
|
||||
*dst = value;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
61
cli.h
61
cli.h
@ -1,21 +1,62 @@
|
||||
/*
|
||||
Serval command line parsing and processing.
|
||||
Copyright (C) 2012,2013 Serval Project, Inc.
|
||||
|
||||
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 2
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SERVALD_CLI_H
|
||||
#define __SERVALD_CLI_H
|
||||
|
||||
typedef struct command_line_option {
|
||||
int (*function)(int argc, const char *const *argv, const struct command_line_option *o, void *context);
|
||||
const char *words[32]; // 32 words should be plenty!
|
||||
#include "log.h"
|
||||
|
||||
#define COMMAND_LINE_MAX_LABELS (32)
|
||||
|
||||
struct parsed_command;
|
||||
|
||||
struct command_line_option {
|
||||
int (*function)(const struct parsed_command *parsed, void *context);
|
||||
const char *words[COMMAND_LINE_MAX_LABELS];
|
||||
unsigned long long flags;
|
||||
#define CLIFLAG_NONOVERLAY (1<<0) /* Uses a legacy IPv4 DNA call instead of overlay mnetwork */
|
||||
#define CLIFLAG_STANDALONE (1<<1) /* Cannot be issued to a running instance */
|
||||
#define CLIFLAG_PERMISSIVE_CONFIG (1<<2) /* No error on bad configuration file */
|
||||
const char *description; // describe this invocation
|
||||
} command_line_option;
|
||||
};
|
||||
|
||||
struct parsed_command {
|
||||
const struct command_line_option *command;
|
||||
struct labelv {
|
||||
const char *label;
|
||||
unsigned int len;
|
||||
unsigned argi;
|
||||
} labelv[COMMAND_LINE_MAX_LABELS];
|
||||
unsigned labelc;
|
||||
const char *const *args;
|
||||
unsigned argc;
|
||||
unsigned varargi;
|
||||
};
|
||||
|
||||
int cli_usage(const command_line_option *options);
|
||||
int cli_parse(const int argc, const char *const *args, const struct command_line_option *options);
|
||||
int cli_invoke(const struct command_line_option *option, const int argc, const char *const *args, void *context);
|
||||
int cli_arg(int argc, const char *const *argv, const command_line_option *o, char *argname, const char **dst, int (*validator)(const char *arg), char *defaultvalue);
|
||||
void _debug_parsed(struct __sourceloc __whence, const struct parsed_command *parsed);
|
||||
|
||||
#define DEBUG_parsed(parsed) _debug_parsed(__WHENCE__, parsed)
|
||||
|
||||
int cli_usage(const struct command_line_option *commands);
|
||||
int cli_parse(const int argc, const char *const *args, const struct command_line_option *commands, struct parsed_command *parsed);
|
||||
int cli_invoke(const struct parsed_command *parsed, void *context);
|
||||
int cli_arg(const struct parsed_command *parsed, char *label, const char **dst, int (*validator)(const char *arg), char *defaultvalue);
|
||||
|
||||
int cli_lookup_did(const char *text);
|
||||
int cli_absolute_path(const char *arg);
|
||||
@ -27,6 +68,4 @@ int cli_optional_bundle_crypt_key(const char *arg);
|
||||
int cli_uint(const char *arg);
|
||||
int cli_optional_did(const char *text);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif // __SERVALD_CLI_H
|
||||
|
293
commandline.c
293
commandline.c
@ -46,7 +46,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
extern struct command_line_option command_line_options[];
|
||||
|
||||
int commandline_usage(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
int commandline_usage(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
printf("Serval Mesh version <version>.\n");
|
||||
return cli_usage(command_line_options);
|
||||
}
|
||||
@ -223,12 +224,12 @@ int parseCommandLine(const char *argv0, int argc, const char *const *args)
|
||||
fd_clearstats();
|
||||
IN();
|
||||
|
||||
int result = cli_parse(argc, args, command_line_options);
|
||||
struct parsed_command parsed;
|
||||
int result = cli_parse(argc, args, command_line_options, &parsed);
|
||||
if (result != -1) {
|
||||
const struct command_line_option *option = &command_line_options[result];
|
||||
// Do not run the command if the configuration does not load ok
|
||||
if (((option->flags & CLIFLAG_PERMISSIVE_CONFIG) ? cf_reload_permissive() : cf_reload()) != -1)
|
||||
result = cli_invoke(option, argc, args, NULL);
|
||||
if (((parsed.command->flags & CLIFLAG_PERMISSIVE_CONFIG) ? cf_reload_permissive() : cf_reload()) != -1)
|
||||
result = cli_invoke(&parsed, NULL);
|
||||
else {
|
||||
strbuf b = strbuf_alloca(160);
|
||||
strbuf_append_argv(b, argc, args);
|
||||
@ -478,24 +479,22 @@ void cli_flush()
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int app_echo(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_echo(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
int i = 1;
|
||||
int escapes = 0;
|
||||
if (i < argc && strcmp(argv[i], "-e") == 0) {
|
||||
escapes = 1;
|
||||
++i;
|
||||
}
|
||||
for (; i < argc; ++i) {
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
int escapes = !cli_arg(parsed, "-e", NULL, NULL, NULL);
|
||||
int i;
|
||||
for (i = parsed->varargi; i < parsed->argc; ++i) {
|
||||
const char *arg = parsed->args[i];
|
||||
if (config.debug.verbose)
|
||||
DEBUGF("echo:argv[%d]=\"%s\"", i, argv[i]);
|
||||
DEBUGF("echo:argv[%d]=\"%s\"", i, arg);
|
||||
if (escapes) {
|
||||
unsigned char buf[strlen(argv[i])];
|
||||
size_t len = str_fromprint(buf, argv[i]);
|
||||
unsigned char buf[strlen(arg)];
|
||||
size_t len = str_fromprint(buf, arg);
|
||||
cli_write(buf, len);
|
||||
} else
|
||||
cli_puts(argv[i]);
|
||||
cli_puts(arg);
|
||||
cli_delim(NULL);
|
||||
}
|
||||
return 0;
|
||||
@ -541,9 +540,10 @@ void lookup_send_request(unsigned char *srcsid, int srcport, unsigned char *dsts
|
||||
}
|
||||
}
|
||||
|
||||
int app_dna_lookup(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_dna_lookup(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
|
||||
/* Create the instance directory if it does not yet exist */
|
||||
if (create_serval_instance_dir() == -1)
|
||||
@ -555,9 +555,9 @@ int app_dna_lookup(int argc, const char *const *argv, const struct command_line_
|
||||
char uris[MAXREPLIES][MAXURILEN];
|
||||
|
||||
const char *did, *delay;
|
||||
if (cli_arg(argc, argv, o, "did", &did, cli_lookup_did, "*") == -1)
|
||||
if (cli_arg(parsed, "did", &did, cli_lookup_did, "*") == -1)
|
||||
return -1;
|
||||
if (cli_arg(argc, argv, o, "timeout", &delay, NULL, "3000") == -1)
|
||||
if (cli_arg(parsed, "timeout", &delay, NULL, "3000") == -1)
|
||||
return -1;
|
||||
|
||||
int idelay=atoi(delay);
|
||||
@ -658,9 +658,10 @@ int app_dna_lookup(int argc, const char *const *argv, const struct command_line_
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_server_start(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_server_start(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
/* Process optional arguments */
|
||||
int pid=-1;
|
||||
int cpid=-1;
|
||||
@ -701,9 +702,9 @@ int app_server_start(int argc, const char *const *argv, const struct command_lin
|
||||
#endif
|
||||
const char *execpath, *instancepath;
|
||||
char *tmp;
|
||||
int foregroundP = (argc >= 2 && !strcasecmp(argv[1], "foreground"));
|
||||
if (cli_arg(argc, argv, o, "instance path", &instancepath, cli_absolute_path, NULL) == -1
|
||||
|| cli_arg(argc, argv, o, "exec path", &execpath, cli_absolute_path, NULL) == -1)
|
||||
int foregroundP = parsed->argc >= 2 && !strcasecmp(parsed->args[1], "foreground");
|
||||
if (cli_arg(parsed, "instance path", &instancepath, cli_absolute_path, NULL) == -1
|
||||
|| cli_arg(parsed, "exec path", &execpath, cli_absolute_path, NULL) == -1)
|
||||
return -1;
|
||||
if (instancepath != NULL)
|
||||
serval_setinstancepath(instancepath);
|
||||
@ -831,13 +832,14 @@ int app_server_start(int argc, const char *const *argv, const struct command_lin
|
||||
return ret;
|
||||
}
|
||||
|
||||
int app_server_stop(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_server_stop(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
int pid, tries, running;
|
||||
const char *instancepath;
|
||||
time_ms_t timeout;
|
||||
if (cli_arg(argc, argv, o, "instance path", &instancepath, cli_absolute_path, NULL) == -1)
|
||||
if (cli_arg(parsed, "instance path", &instancepath, cli_absolute_path, NULL) == -1)
|
||||
return WHY("Unable to determine instance path");
|
||||
if (instancepath != NULL)
|
||||
serval_setinstancepath(instancepath);
|
||||
@ -892,12 +894,13 @@ int app_server_stop(int argc, const char *const *argv, const struct command_line
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_server_status(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_server_status(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
int pid;
|
||||
const char *instancepath;
|
||||
if (cli_arg(argc, argv, o, "instance path", &instancepath, cli_absolute_path, NULL) == -1)
|
||||
if (cli_arg(parsed, "instance path", &instancepath, cli_absolute_path, NULL) == -1)
|
||||
return WHY("Unable to determine instance path");
|
||||
if (instancepath != NULL)
|
||||
serval_setinstancepath(instancepath);
|
||||
@ -919,13 +922,14 @@ int app_server_status(int argc, const char *const *argv, const struct command_li
|
||||
return pid > 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
int app_mdp_ping(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_mdp_ping(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *sid, *count;
|
||||
if (cli_arg(argc, argv, o, "SID|broadcast", &sid, str_is_subscriber_id, "broadcast") == -1)
|
||||
if (cli_arg(parsed, "SID|broadcast", &sid, str_is_subscriber_id, "broadcast") == -1)
|
||||
return -1;
|
||||
if (cli_arg(argc, argv, o, "count", &count, NULL, "0") == -1)
|
||||
if (cli_arg(parsed, "count", &count, NULL, "0") == -1)
|
||||
return -1;
|
||||
|
||||
// assume we wont hear any responses
|
||||
@ -1066,9 +1070,10 @@ int app_mdp_ping(int argc, const char *const *argv, const struct command_line_op
|
||||
return ret;
|
||||
}
|
||||
|
||||
int app_config_schema(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_config_schema(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
struct cf_om_node *root = NULL;
|
||||
@ -1086,9 +1091,10 @@ int app_config_schema(int argc, const char *const *argv, const struct command_li
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_config_set(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_config_set(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
// <kludge>
|
||||
@ -1107,26 +1113,27 @@ int app_config_set(int argc, const char *const *argv, const struct command_line_
|
||||
if (cf_om_reload() == -1)
|
||||
return -1;
|
||||
// </kludge>
|
||||
const char *var[argc - 1];
|
||||
const char *val[argc - 1];
|
||||
const char *var[parsed->argc - 1];
|
||||
const char *val[parsed->argc - 1];
|
||||
int nvar = 0;
|
||||
int i;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
for (i = 1; i < parsed->argc; ++i) {
|
||||
const char *arg = parsed->args[i];
|
||||
int iv;
|
||||
if (strcmp(argv[i], "set") == 0) {
|
||||
if (i + 2 > argc)
|
||||
return WHYF("malformed command at argv[%d]: 'set' not followed by two arguments", i);
|
||||
var[nvar] = argv[iv = ++i];
|
||||
val[nvar] = argv[++i];
|
||||
} else if (strcmp(argv[i], "del") == 0) {
|
||||
if (i + 1 > argc)
|
||||
return WHYF("malformed command at argv[%d]: 'del' not followed by one argument", i);
|
||||
var[nvar] = argv[iv = ++i];
|
||||
if (strcmp(arg, "set") == 0) {
|
||||
if (i + 2 > parsed->argc)
|
||||
return WHYF("malformed command at args[%d]: 'set' not followed by two arguments", i);
|
||||
var[nvar] = parsed->args[iv = ++i];
|
||||
val[nvar] = parsed->args[++i];
|
||||
} else if (strcmp(arg, "del") == 0) {
|
||||
if (i + 1 > parsed->argc)
|
||||
return WHYF("malformed command at args[%d]: 'del' not followed by one argument", i);
|
||||
var[nvar] = parsed->args[iv = ++i];
|
||||
val[nvar] = NULL;
|
||||
} else
|
||||
return WHYF("malformed command at argv[%d]: unsupported action '%s'", i, argv[i]);
|
||||
return WHYF("malformed command at args[%d]: unsupported action '%s'", i, arg);
|
||||
if (!is_configvarname(var[nvar]))
|
||||
return WHYF("malformed command at argv[%d]: '%s' is not a valid config option name", iv, var[nvar]);
|
||||
return WHYF("malformed command at args[%d]: '%s' is not a valid config option name", iv, var[nvar]);
|
||||
++nvar;
|
||||
}
|
||||
for (i = 0; i < nvar; ++i)
|
||||
@ -1139,11 +1146,12 @@ int app_config_set(int argc, const char *const *argv, const struct command_line_
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_config_get(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_config_get(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *var;
|
||||
if (cli_arg(argc, argv, o, "variable", &var, is_configvarpattern, NULL) == -1)
|
||||
if (cli_arg(parsed, "variable", &var, is_configvarpattern, NULL) == -1)
|
||||
return -1;
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
@ -1173,13 +1181,14 @@ int app_config_get(int argc, const char *const *argv, const struct command_line_
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_rhizome_hash_file(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_hash_file(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
/* compute hash of file. We do this without a manifest, so it will necessarily
|
||||
return the hash of the file unencrypted. */
|
||||
const char *filepath;
|
||||
cli_arg(argc, argv, o, "filepath", &filepath, NULL, "");
|
||||
cli_arg(parsed, "filepath", &filepath, NULL, "");
|
||||
char hexhash[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
if (rhizome_hash_file(NULL,filepath, hexhash))
|
||||
return -1;
|
||||
@ -1188,16 +1197,17 @@ int app_rhizome_hash_file(int argc, const char *const *argv, const struct comman
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_rhizome_add_file(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_add_file(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *filepath, *manifestpath, *authorSidHex, *pin, *bskhex;
|
||||
cli_arg(argc, argv, o, "filepath", &filepath, NULL, "");
|
||||
if (cli_arg(argc, argv, o, "author_sid", &authorSidHex, cli_optional_sid, "") == -1)
|
||||
cli_arg(parsed, "filepath", &filepath, NULL, "");
|
||||
if (cli_arg(parsed, "author_sid", &authorSidHex, cli_optional_sid, "") == -1)
|
||||
return -1;
|
||||
cli_arg(argc, argv, o, "pin", &pin, NULL, "");
|
||||
cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, "");
|
||||
if (cli_arg(argc, argv, o, "bsk", &bskhex, cli_optional_bundle_key, NULL) == -1)
|
||||
cli_arg(parsed, "pin", &pin, NULL, "");
|
||||
cli_arg(parsed, "manifestpath", &manifestpath, NULL, "");
|
||||
if (cli_arg(parsed, "bsk", &bskhex, cli_optional_bundle_key, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
sid_t authorSid;
|
||||
@ -1312,12 +1322,13 @@ int app_rhizome_add_file(int argc, const char *const *argv, const struct command
|
||||
return ret;
|
||||
}
|
||||
|
||||
int app_rhizome_import_bundle(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_import_bundle(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *filepath, *manifestpath;
|
||||
cli_arg(argc, argv, o, "filepath", &filepath, NULL, "");
|
||||
cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, "");
|
||||
cli_arg(parsed, "filepath", &filepath, NULL, "");
|
||||
cli_arg(parsed, "manifestpath", &manifestpath, NULL, "");
|
||||
if (rhizome_opendb() == -1)
|
||||
return -1;
|
||||
|
||||
@ -1366,12 +1377,13 @@ cleanup:
|
||||
return status;
|
||||
}
|
||||
|
||||
int app_rhizome_append_manifest(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_append_manifest(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *manifestpath, *filepath;
|
||||
if (cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, "") == -1
|
||||
|| cli_arg(argc, argv, o, "filepath", &filepath, NULL, "") == -1)
|
||||
if ( cli_arg(parsed, "manifestpath", &manifestpath, NULL, "") == -1
|
||||
|| cli_arg(parsed, "filepath", &filepath, NULL, "") == -1)
|
||||
return -1;
|
||||
|
||||
rhizome_manifest *m = rhizome_new_manifest();
|
||||
@ -1392,15 +1404,16 @@ int app_rhizome_append_manifest(int argc, const char *const *argv, const struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
int app_rhizome_extract_bundle(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_extract_bundle(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *manifestpath, *filepath, *manifestid, *pins, *bskhex;
|
||||
if (cli_arg(argc, argv, o, "manifestid", &manifestid, cli_manifestid, "") == -1
|
||||
|| cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, "") == -1
|
||||
|| cli_arg(argc, argv, o, "filepath", &filepath, NULL, "") == -1
|
||||
|| cli_arg(argc, argv, o, "pin,pin...", &pins, NULL, "") == -1
|
||||
|| cli_arg(argc, argv, o, "bsk", &bskhex, cli_optional_bundle_key, NULL) == -1)
|
||||
if ( cli_arg(parsed, "manifestid", &manifestid, cli_manifestid, "") == -1
|
||||
|| cli_arg(parsed, "manifestpath", &manifestpath, NULL, "") == -1
|
||||
|| cli_arg(parsed, "filepath", &filepath, NULL, "") == -1
|
||||
|| cli_arg(parsed, "pin,pin...", &pins, NULL, "") == -1
|
||||
|| cli_arg(parsed, "bsk", &bskhex, cli_optional_bundle_key, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
/* Ensure the Rhizome database exists and is open */
|
||||
@ -1491,12 +1504,13 @@ int app_rhizome_extract_bundle(int argc, const char *const *argv, const struct c
|
||||
return ret;
|
||||
}
|
||||
|
||||
int app_rhizome_dump_file(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_dump_file(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *fileid, *filepath;
|
||||
if (cli_arg(argc, argv, o, "filepath", &filepath, NULL, "") == -1
|
||||
|| cli_arg(argc, argv, o, "fileid", &fileid, cli_fileid, NULL) == -1)
|
||||
if ( cli_arg(parsed, "filepath", &filepath, NULL, "") == -1
|
||||
|| cli_arg(parsed, "fileid", &fileid, cli_fileid, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
if (create_serval_instance_dir() == -1)
|
||||
@ -1519,17 +1533,18 @@ int app_rhizome_dump_file(int argc, const char *const *argv, const struct comman
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_rhizome_list(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_list(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *pins, *service, *name, *sender_sid, *recipient_sid, *offset, *limit;
|
||||
cli_arg(argc, argv, o, "pin,pin...", &pins, NULL, "");
|
||||
cli_arg(argc, argv, o, "service", &service, NULL, "");
|
||||
cli_arg(argc, argv, o, "name", &name, NULL, "");
|
||||
cli_arg(argc, argv, o, "sender_sid", &sender_sid, cli_optional_sid, "");
|
||||
cli_arg(argc, argv, o, "recipient_sid", &recipient_sid, cli_optional_sid, "");
|
||||
cli_arg(argc, argv, o, "offset", &offset, cli_uint, "0");
|
||||
cli_arg(argc, argv, o, "limit", &limit, cli_uint, "0");
|
||||
cli_arg(parsed, "pin,pin...", &pins, NULL, "");
|
||||
cli_arg(parsed, "service", &service, NULL, "");
|
||||
cli_arg(parsed, "name", &name, NULL, "");
|
||||
cli_arg(parsed, "sender_sid", &sender_sid, cli_optional_sid, "");
|
||||
cli_arg(parsed, "recipient_sid", &recipient_sid, cli_optional_sid, "");
|
||||
cli_arg(parsed, "offset", &offset, cli_uint, "0");
|
||||
cli_arg(parsed, "limit", &limit, cli_uint, "0");
|
||||
/* Create the instance directory if it does not yet exist */
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
@ -1540,21 +1555,23 @@ int app_rhizome_list(int argc, const char *const *argv, const struct command_lin
|
||||
return rhizome_list_manifests(service, name, sender_sid, recipient_sid, atoi(offset), atoi(limit), 0);
|
||||
}
|
||||
|
||||
int app_keyring_create(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_keyring_create(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *pin;
|
||||
cli_arg(argc, argv, o, "pin,pin...", &pin, NULL, "");
|
||||
cli_arg(parsed, "pin,pin...", &pin, NULL, "");
|
||||
if (!keyring_open_with_pins(pin))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_keyring_list(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_keyring_list(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *pins;
|
||||
cli_arg(argc, argv, o, "pin,pin...", &pins, NULL, "");
|
||||
cli_arg(parsed, "pin,pin...", &pins, NULL, "");
|
||||
keyring_file *k = keyring_open_with_pins(pins);
|
||||
if (!k)
|
||||
return -1;
|
||||
@ -1577,11 +1594,12 @@ int app_keyring_list(int argc, const char *const *argv, const struct command_lin
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_keyring_add(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_keyring_add(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *pin;
|
||||
cli_arg(argc, argv, o, "pin", &pin, NULL, "");
|
||||
cli_arg(parsed, "pin", &pin, NULL, "");
|
||||
keyring_file *k = keyring_open_with_pins("");
|
||||
if (!k)
|
||||
return -1;
|
||||
@ -1622,14 +1640,15 @@ int app_keyring_add(int argc, const char *const *argv, const struct command_line
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_keyring_set_did(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_keyring_set_did(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *sid, *did, *pin, *name;
|
||||
cli_arg(argc, argv, o, "sid", &sid, str_is_subscriber_id, "");
|
||||
cli_arg(argc, argv, o, "did", &did, cli_optional_did, "");
|
||||
cli_arg(argc, argv, o, "name", &name, NULL, "");
|
||||
cli_arg(argc, argv, o, "pin", &pin, NULL, "");
|
||||
cli_arg(parsed, "sid", &sid, str_is_subscriber_id, "");
|
||||
cli_arg(parsed, "did", &did, cli_optional_did, "");
|
||||
cli_arg(parsed, "name", &name, NULL, "");
|
||||
cli_arg(parsed, "pin", &pin, NULL, "");
|
||||
|
||||
if (strlen(name)>63) return WHY("Name too long (31 char max)");
|
||||
|
||||
@ -1651,9 +1670,10 @@ int app_keyring_set_did(int argc, const char *const *argv, const struct command_
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_id_self(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_id_self(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
/* List my own identities */
|
||||
overlay_mdp_frame a;
|
||||
bzero(&a, sizeof(overlay_mdp_frame));
|
||||
@ -1661,14 +1681,15 @@ int app_id_self(int argc, const char *const *argv, const struct command_line_opt
|
||||
int count=0;
|
||||
|
||||
a.packetTypeAndFlags=MDP_GETADDRS;
|
||||
if (!strcasecmp(argv[1],"self"))
|
||||
const char *arg = parsed->argc >= 2 ? parsed->args[1] : "";
|
||||
if (!strcasecmp(arg,"self"))
|
||||
a.addrlist.mode = MDP_ADDRLIST_MODE_SELF; /* get own identities */
|
||||
else if (!strcasecmp(argv[1],"allpeers"))
|
||||
else if (!strcasecmp(arg,"allpeers"))
|
||||
a.addrlist.mode = MDP_ADDRLIST_MODE_ALL_PEERS; /* get all known peers */
|
||||
else if (!strcasecmp(argv[1],"peers"))
|
||||
else if (!strcasecmp(arg,"peers"))
|
||||
a.addrlist.mode = MDP_ADDRLIST_MODE_ROUTABLE_PEERS; /* get routable (reachable) peers */
|
||||
else
|
||||
return WHYF("unsupported arg '%s'", argv[1]);
|
||||
return WHYF("unsupported arg '%s'", arg);
|
||||
a.addrlist.first_sid=0;
|
||||
|
||||
do{
|
||||
@ -1698,8 +1719,10 @@ int app_id_self(int argc, const char *const *argv, const struct command_line_opt
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_count_peers(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_count_peers(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
overlay_mdp_frame a;
|
||||
bzero(&a, sizeof(overlay_mdp_frame));
|
||||
a.packetTypeAndFlags=MDP_GETADDRS;
|
||||
@ -1715,9 +1738,10 @@ int app_count_peers(int argc, const char *const *argv, const struct command_line
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_crypt_test(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_crypt_test(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
unsigned char nonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES];
|
||||
unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
|
||||
|
||||
@ -1878,11 +1902,12 @@ int app_crypt_test(int argc, const char *const *argv, const struct command_line_
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_node_info(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_node_info(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose) DEBUG_argv("command", argc, argv);
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *sid;
|
||||
cli_arg(argc, argv, o, "sid", &sid, NULL, "");
|
||||
cli_arg(parsed, "sid", &sid, NULL, "");
|
||||
|
||||
overlay_mdp_frame mdp;
|
||||
bzero(&mdp,sizeof(mdp));
|
||||
@ -1925,8 +1950,10 @@ int app_node_info(int argc, const char *const *argv, const struct command_line_o
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_route_print(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_route_print(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
overlay_mdp_frame mdp;
|
||||
bzero(&mdp,sizeof(mdp));
|
||||
|
||||
@ -1967,16 +1994,16 @@ int app_route_print(int argc, const char *const *argv, const struct command_line
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_reverse_lookup(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_reverse_lookup(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
const char *sid, *delay;
|
||||
|
||||
if (cli_arg(argc, argv, o, "sid", &sid, str_is_subscriber_id, "") == -1)
|
||||
if (cli_arg(parsed, "sid", &sid, str_is_subscriber_id, "") == -1)
|
||||
return -1;
|
||||
if (cli_arg(argc, argv, o, "timeout", &delay, NULL, "3000") == -1)
|
||||
if (cli_arg(parsed, "timeout", &delay, NULL, "3000") == -1)
|
||||
return -1;
|
||||
|
||||
|
||||
int port=32768+(random()&0xffff);
|
||||
|
||||
unsigned char srcsid[SID_SIZE];
|
||||
@ -2063,8 +2090,10 @@ int app_reverse_lookup(int argc, const char *const *argv, const struct command_l
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_network_scan(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_network_scan(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
overlay_mdp_frame mdp;
|
||||
bzero(&mdp,sizeof(mdp));
|
||||
|
||||
@ -2072,7 +2101,7 @@ int app_network_scan(int argc, const char *const *argv, const struct command_lin
|
||||
|
||||
struct overlay_mdp_scan *scan = (struct overlay_mdp_scan *)&mdp.raw;
|
||||
const char *address;
|
||||
if (cli_arg(argc, argv, o, "address", &address, NULL, NULL) == -1)
|
||||
if (cli_arg(parsed, "address", &address, NULL, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
if (address){
|
||||
@ -2112,7 +2141,7 @@ struct command_line_option command_line_options[]={
|
||||
"Lookup the SIP/MDP address of the supplied telephone number (DID)."},
|
||||
{commandline_usage,{"help",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||
"Display command usage."},
|
||||
{app_echo,{"echo","...",NULL},CLIFLAG_STANDALONE,
|
||||
{app_echo,{"echo","[-e]","[--]","...",NULL},CLIFLAG_STANDALONE,
|
||||
"Output the supplied string."},
|
||||
{app_server_start,{"start",NULL},CLIFLAG_STANDALONE,
|
||||
"Start Serval Mesh node process with instance path taken from SERVALINSTANCE_PATH environment variable."},
|
||||
|
@ -5,6 +5,7 @@ HDRS= fifo.h \
|
||||
overlay_packet.h \
|
||||
rhizome.h \
|
||||
serval.h \
|
||||
cli.h \
|
||||
str.h \
|
||||
mem.h \
|
||||
os.h \
|
||||
|
@ -46,7 +46,7 @@ struct monitor_command_handler monitor_handlers[]={
|
||||
{.command="", .handler=remote_print},
|
||||
};
|
||||
|
||||
int app_monitor_cli(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_monitor_cli(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct pollfd fds[2];
|
||||
struct monitor_state *state;
|
||||
|
92
monitor.c
92
monitor.c
@ -382,23 +382,24 @@ void monitor_get_all_supported_codecs(unsigned char *codecs){
|
||||
}
|
||||
}
|
||||
|
||||
static int monitor_set(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int monitor_set(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct monitor_context *c=context;
|
||||
if (strcase_startswith((char *)argv[1],"vomp",NULL)){
|
||||
if (strcase_startswith(parsed->args[1],"vomp",NULL)){
|
||||
c->flags|=MONITOR_VOMP;
|
||||
// store the list of supported codecs against the monitor connection,
|
||||
// since we need to forget about them when the client disappears.
|
||||
int i;
|
||||
for (i=2;i<argc;i++){
|
||||
int codec = atoi(argv[i]);
|
||||
for (i = 2; i < parsed->argc; ++i) {
|
||||
int codec = atoi(parsed->args[i]);
|
||||
if (codec>=0 && codec <=255)
|
||||
set_codec_flag(codec, c->supported_codecs);
|
||||
}
|
||||
}else if (strcase_startswith((char *)argv[1],"rhizome", NULL))
|
||||
}else if (strcase_startswith(parsed->args[1],"rhizome", NULL))
|
||||
c->flags|=MONITOR_RHIZOME;
|
||||
else if (strcase_startswith((char *)argv[1],"peers", NULL))
|
||||
else if (strcase_startswith(parsed->args[1],"peers", NULL))
|
||||
c->flags|=MONITOR_PEERS;
|
||||
else if (strcase_startswith((char *)argv[1],"dnahelper", NULL))
|
||||
else if (strcase_startswith(parsed->args[1],"dnahelper", NULL))
|
||||
c->flags|=MONITOR_DNAHELPER;
|
||||
else
|
||||
return monitor_write_error(c,"Unknown monitor type");
|
||||
@ -410,15 +411,16 @@ static int monitor_set(int argc, const char *const *argv, const struct command_l
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_clear(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int monitor_clear(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct monitor_context *c=context;
|
||||
if (strcase_startswith((char *)argv[1],"vomp",NULL))
|
||||
if (strcase_startswith(parsed->args[1],"vomp",NULL))
|
||||
c->flags&=~MONITOR_VOMP;
|
||||
else if (strcase_startswith((char *)argv[1],"rhizome", NULL))
|
||||
else if (strcase_startswith(parsed->args[1],"rhizome", NULL))
|
||||
c->flags&=~MONITOR_RHIZOME;
|
||||
else if (strcase_startswith((char *)argv[1],"peers", NULL))
|
||||
else if (strcase_startswith(parsed->args[1],"peers", NULL))
|
||||
c->flags&=~MONITOR_PEERS;
|
||||
else if (strcase_startswith((char *)argv[1],"dnahelper", NULL))
|
||||
else if (strcase_startswith(parsed->args[1],"dnahelper", NULL))
|
||||
c->flags&=~MONITOR_DNAHELPER;
|
||||
else
|
||||
return monitor_write_error(c,"Unknown monitor type");
|
||||
@ -430,17 +432,18 @@ static int monitor_clear(int argc, const char *const *argv, const struct command
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_lookup_match(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
struct monitor_context *c=context;
|
||||
const char *sid=argv[2];
|
||||
const char *ext=argv[4];
|
||||
const char *name=argc>=4?argv[5]:"";
|
||||
static int monitor_lookup_match(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct monitor_context *c = context;
|
||||
const char *sid = parsed->args[2];
|
||||
const char *ext = parsed->args[4];
|
||||
const char *name = parsed->argc >= 4 ? parsed->args[5] : "";
|
||||
|
||||
if (!my_subscriber)
|
||||
return monitor_write_error(c,"I don't know who I am");
|
||||
|
||||
struct sockaddr_mdp addr={
|
||||
.port = atoi(argv[3]),
|
||||
.port = atoi(parsed->args[3]),
|
||||
};
|
||||
|
||||
if (stowSid((unsigned char *)&addr.sid, 0, sid)==-1)
|
||||
@ -453,69 +456,75 @@ static int monitor_lookup_match(int argc, const char *const *argv, const struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_call(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int monitor_call(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct monitor_context *c=context;
|
||||
unsigned char sid[SID_SIZE];
|
||||
if (stowSid(sid, 0, argv[1]) == -1)
|
||||
if (stowSid(sid, 0, parsed->args[1]) == -1)
|
||||
return monitor_write_error(c,"invalid SID, so cannot place call");
|
||||
|
||||
if (!my_subscriber)
|
||||
return monitor_write_error(c,"I don't know who I am");
|
||||
struct subscriber *remote = find_subscriber(sid, SID_SIZE, 1);
|
||||
vomp_dial(my_subscriber, remote, argv[2], argv[3]);
|
||||
vomp_dial(my_subscriber, remote, parsed->args[2], parsed->args[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_call_ring(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(argv[1],NULL,16));
|
||||
static int monitor_call_ring(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(parsed->args[1],NULL,16));
|
||||
if (!call)
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", argv[1]);
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", parsed->args[1]);
|
||||
else
|
||||
vomp_ringing(call);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_call_pickup(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(argv[1],NULL,16));
|
||||
static int monitor_call_pickup(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(parsed->args[1],NULL,16));
|
||||
if (!call)
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", argv[1]);
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", parsed->args[1]);
|
||||
else
|
||||
vomp_pickup(call);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_call_audio(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int monitor_call_audio(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct monitor_context *c=context;
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(argv[1],NULL,16));
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(parsed->args[1],NULL,16));
|
||||
|
||||
if (!call){
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", argv[1]);
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", parsed->args[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int codec_type = atoi(argv[2]);
|
||||
int time = argc>=4?atoi(argv[3]):-1;
|
||||
int sequence = argc>=5?atoi(argv[4]):-1;
|
||||
int codec_type = atoi(parsed->args[2]);
|
||||
int time = parsed->argc >=4 ? atoi(parsed->args[3]) : -1;
|
||||
int sequence = parsed->argc >= 5 ? atoi(parsed->args[4]) : -1;
|
||||
|
||||
vomp_received_audio(call, codec_type, time, sequence, c->buffer, c->data_expected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_call_hangup(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(argv[1],NULL,16));
|
||||
static int monitor_call_hangup(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(parsed->args[1],NULL,16));
|
||||
if (!call)
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", argv[1]);
|
||||
monitor_tell_formatted(MONITOR_VOMP, "\nHANGUP:%s\n", parsed->args[1]);
|
||||
else
|
||||
vomp_hangup(call);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_call_dtmf(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int monitor_call_dtmf(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
struct monitor_context *c=context;
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(argv[1],NULL,16));
|
||||
struct vomp_call_state *call=vomp_find_call_by_session(strtol(parsed->args[1],NULL,16));
|
||||
if (!call)
|
||||
return monitor_write_error(c,"Invalid call token");
|
||||
const char *digits = argv[2];
|
||||
const char *digits = parsed->args[2];
|
||||
|
||||
int i;
|
||||
for(i=0;i<strlen(digits);i++) {
|
||||
@ -552,8 +561,9 @@ int monitor_process_command(struct monitor_context *c)
|
||||
char *argv[16]={NULL,};
|
||||
int argc = parse_argv(c->line, ' ', argv, 16);
|
||||
|
||||
int res = cli_parse(argc, (const char *const*)argv, monitor_options);
|
||||
if (res == -1 || cli_invoke(&monitor_options[res], argc, (const char *const*)argv, c))
|
||||
struct parsed_command parsed;
|
||||
int res = cli_parse(argc, (const char *const*)argv, monitor_options, &parsed);
|
||||
if (res == -1 || cli_invoke(&parsed, c))
|
||||
return monitor_write_error(c, "Invalid command");
|
||||
return 0;
|
||||
}
|
||||
|
@ -513,25 +513,27 @@ static int rhizome_sync_with_peers(int mode, int peer_count, const struct config
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_rhizome_direct_sync(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_rhizome_direct_sync(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
/* Attempt to connect with a remote Rhizome Direct instance,
|
||||
and negotiate which BARs to synchronise. */
|
||||
const char *modeName = (argc >= 3 ? argv[2] : "sync");
|
||||
const char *modeName = (parsed->argc >= 3 ? parsed->args[2] : "sync");
|
||||
int mode=3; /* two-way sync */
|
||||
if (!strcasecmp(modeName,"push")) mode=1; /* push only */
|
||||
if (!strcasecmp(modeName,"pull")) mode=2; /* pull only */
|
||||
DEBUGF("sync direction = %d",mode);
|
||||
if (argv[3]) {
|
||||
if (parsed->args[3]) {
|
||||
struct config_rhizome_peer peer;
|
||||
const struct config_rhizome_peer *peers[1] = { &peer };
|
||||
int result = cf_opt_rhizome_peer_from_uri(&peer, argv[3]);
|
||||
int result = cf_opt_rhizome_peer_from_uri(&peer, parsed->args[3]);
|
||||
if (result == CFOK)
|
||||
return rhizome_sync_with_peers(mode, 1, peers);
|
||||
else {
|
||||
strbuf b = strbuf_alloca(128);
|
||||
strbuf_cf_flag_reason(b, result);
|
||||
return WHYF("Invalid peer URI %s -- %s", alloca_str_toprint(argv[3]), strbuf_str(b));
|
||||
return WHYF("Invalid peer URI %s -- %s", alloca_str_toprint(parsed->args[3]), strbuf_str(b));
|
||||
}
|
||||
} else if (config.rhizome.direct.peer.ac == 0) {
|
||||
DEBUG("No rhizome direct peers were configured or supplied");
|
||||
|
9
serval.h
9
serval.h
@ -109,6 +109,7 @@ struct in_addr {
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "cli.h"
|
||||
#include "constants.h"
|
||||
#include "mem.h"
|
||||
#include "xprintf.h"
|
||||
@ -656,12 +657,12 @@ int directory_registration();
|
||||
int directory_service_init();
|
||||
|
||||
struct command_line_option;
|
||||
int app_rhizome_direct_sync(int argc, const char *const *argv, const struct command_line_option *o, void *context);
|
||||
int app_rhizome_direct_sync(const struct parsed_command *parsed, void *context);
|
||||
#ifdef HAVE_VOIPTEST
|
||||
int app_pa_phone(int argc, const char *const *argv, const struct command_line_option *o, void *context);
|
||||
int app_pa_phone(const struct parsed_command *parsed, void *context);
|
||||
#endif
|
||||
int app_monitor_cli(int argc, const char *const *argv, const struct command_line_option *o, void *context);
|
||||
int app_vomp_console(int argc, const char *const *argv, const struct command_line_option *o, void *context);
|
||||
int app_monitor_cli(const struct parsed_command *parsed, void *context);
|
||||
int app_vomp_console(const struct parsed_command *parsed, void *context);
|
||||
|
||||
int monitor_get_fds(struct pollfd *fds,int *fdcount,int fdmax);
|
||||
|
||||
|
@ -186,19 +186,21 @@ struct monitor_command_handler console_handlers[]={
|
||||
{.command="MONITORSTATUS", .handler=remote_noop},
|
||||
};
|
||||
|
||||
static int console_dial(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int console_dial(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (call_token!=-1){
|
||||
printf("Already in a call\n");
|
||||
return 0;
|
||||
}
|
||||
const char *sid=argv[1];
|
||||
const char *local=argc>=3?argv[2]:"";
|
||||
const char *remote=argc>=4?argv[3]:"";
|
||||
const char *sid = parsed->args[1];
|
||||
const char *local = parsed->argc >= 3 ? parsed->args[2] : "";
|
||||
const char *remote = parsed->argc >= 4 ? parsed->args[3] : "";
|
||||
send_call(sid, local, remote);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int console_answer(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int console_answer(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (call_token==-1){
|
||||
printf("No active call to answer\n");
|
||||
fflush(stdout);
|
||||
@ -207,7 +209,8 @@ static int console_answer(int argc, const char *const *argv, const struct comman
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int console_hangup(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int console_hangup(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (call_token==-1){
|
||||
printf("No call to hangup\n");
|
||||
fflush(stdout);
|
||||
@ -216,7 +219,8 @@ static int console_hangup(int argc, const char *const *argv, const struct comman
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int console_audio(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int console_audio(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (call_token==-1){
|
||||
printf("No active call\n");
|
||||
fflush(stdout);
|
||||
@ -225,11 +229,11 @@ static int console_audio(int argc, const char *const *argv, const struct command
|
||||
static struct strbuf str_buf = STRUCT_STRBUF_EMPTY;
|
||||
int i;
|
||||
strbuf_init(&str_buf, buf, sizeof(buf));
|
||||
for (i = 0; i < argc; ++i) {
|
||||
for (i = 0; i < parsed->argc; ++i) {
|
||||
if (i)
|
||||
strbuf_putc(&str_buf, ' ');
|
||||
if (argv[i])
|
||||
strbuf_toprint_quoted(&str_buf, "\"\"", argv[i]);
|
||||
if (parsed->args[i])
|
||||
strbuf_toprint_quoted(&str_buf, "\"\"", parsed->args[i]);
|
||||
else
|
||||
strbuf_puts(&str_buf, "NULL");
|
||||
}
|
||||
@ -239,7 +243,7 @@ static int console_audio(int argc, const char *const *argv, const struct command
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int console_usage(int argc, const char *const *argv, const struct command_line_option *o, void *context);
|
||||
static int console_usage(const struct parsed_command *parsed, void *context);
|
||||
|
||||
struct command_line_option console_commands[]={
|
||||
{console_answer,{"answer",NULL},0,"Answer an incoming phone call"},
|
||||
@ -250,7 +254,8 @@ struct command_line_option console_commands[]={
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static int console_usage(int argc, const char *const *argv, const struct command_line_option *o, void *context){
|
||||
static int console_usage(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
cli_usage(console_commands);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
@ -260,12 +265,13 @@ static void console_command(char *line){
|
||||
char *argv[16];
|
||||
int argc = parse_argv(line, ' ', argv, 16);
|
||||
|
||||
int ret = cli_parse(argc, (const char *const*)argv, console_commands);
|
||||
struct parsed_command parsed;
|
||||
int ret = cli_parse(argc, (const char *const*)argv, console_commands, &parsed);
|
||||
if (ret == -1) {
|
||||
printf("Unknown command, try help\n");
|
||||
fflush(stdout);
|
||||
} else {
|
||||
cli_invoke(&console_commands[ret], argc, (const char *const*)argv, NULL);
|
||||
cli_invoke(&parsed, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,8 +312,10 @@ static void monitor_read(struct sched_ent *alarm){
|
||||
}
|
||||
}
|
||||
|
||||
int app_vomp_console(int argc, const char *const *argv, const struct command_line_option *o, void *context)
|
||||
int app_vomp_console(const struct parsed_command *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_parsed(parsed);
|
||||
static struct profile_total stdin_profile={
|
||||
.name="read_lines",
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user