mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-23 13:09:00 +00:00
update the internal cli api following comments from kevin.
This change basically simplifies the interface of the new-style handler removing almost all the tricks used in the previous implementation to achieve backward compatibility (which is still present and guaranteed.) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47652 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -38,6 +38,10 @@ void ast_cli(int fd, char *fmt, ...)
|
|||||||
#define RESULT_SHOWUSAGE 1
|
#define RESULT_SHOWUSAGE 1
|
||||||
#define RESULT_FAILURE 2
|
#define RESULT_FAILURE 2
|
||||||
|
|
||||||
|
#define CLI_SUCCESS (char *)RESULT_SUCCESS
|
||||||
|
#define CLI_SHOWUSAGE (char *)RESULT_SHOWUSAGE
|
||||||
|
#define CLI_FAILURE (char *)RESULT_FAILURE
|
||||||
|
|
||||||
#define AST_MAX_CMD_LEN 16
|
#define AST_MAX_CMD_LEN 16
|
||||||
|
|
||||||
#define AST_MAX_ARGS 64
|
#define AST_MAX_ARGS 64
|
||||||
@@ -67,67 +71,44 @@ void ast_cli(int fd, char *fmt, ...)
|
|||||||
|
|
||||||
In the "new-style" format, all the above functionalities are implemented
|
In the "new-style" format, all the above functionalities are implemented
|
||||||
by a single function, and the arguments tell which output is required.
|
by a single function, and the arguments tell which output is required.
|
||||||
|
The prototype is the following:
|
||||||
|
|
||||||
\note \b Note: ideally, the new-style handler would have a different prototype,
|
char *new_setdebug(const struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||||
i.e. something like
|
|
||||||
|
|
||||||
int new_setdebug(const struct ast_cli *e, int function,
|
|
||||||
int fd, int argc, char *argv[], // handler args
|
|
||||||
int n, int pos, const char *line, const char *word // -complete args)
|
|
||||||
|
|
||||||
but at this moment we want to help the transition from old-style to new-style
|
|
||||||
functions so we keep the same interface and override some of the traditional
|
|
||||||
arguments.
|
|
||||||
|
|
||||||
To help the transition, a new-style entry has the same interface as the old one,
|
|
||||||
but it is declared as follows:
|
|
||||||
|
|
||||||
int new_setdebug(int fd, int argc, char *argv[]);
|
|
||||||
|
|
||||||
...
|
...
|
||||||
// this is how we create the entry to register
|
// this is how we create the entry to register
|
||||||
NEW_CLI(new_setdebug, "short description")
|
NEW_CLI(new_setdebug, "short description")
|
||||||
...
|
...
|
||||||
|
|
||||||
Called with the default arguments (argc > 0), the new_handler implements
|
To help the transition, we make the pointer to the struct ast_cli_entry
|
||||||
the command as before.
|
available to old-style handlers via argv[-1].
|
||||||
A negative argc indicates one of the other functions, namely
|
|
||||||
generate the usage string, the full command, or implement the generator.
|
|
||||||
As a trick to extend the interface while being backward compatible,
|
|
||||||
argv[-1] points to a struct ast_cli_args, and, for the generator,
|
|
||||||
argv[0] is really a pointer to a struct ast_cli_args.
|
|
||||||
The return string is obtained by casting the result to char *
|
|
||||||
|
|
||||||
An example of new-style handler is the following
|
An example of new-style handler is the following
|
||||||
|
|
||||||
\code
|
\code
|
||||||
static int test_new_cli(int fd, int argc, char *argv[])
|
static char *test_new_cli(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||||
{
|
{
|
||||||
struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
|
|
||||||
struct ast_cli_args *a;
|
|
||||||
static char *choices = { "one", "two", "three", NULL };
|
static char *choices = { "one", "two", "three", NULL };
|
||||||
|
|
||||||
switch(argc) {
|
switch (cmd) {
|
||||||
case CLI_USAGE:
|
case CLI_INIT:
|
||||||
return (int)
|
e->command = "do this well";
|
||||||
|
e->usage =
|
||||||
"Usage: do this well <arg>\n"
|
"Usage: do this well <arg>\n"
|
||||||
" typically multiline with body indented\n";
|
" typically multiline with body indented\n";
|
||||||
|
return NULL;
|
||||||
case CLI_CMD_STRING:
|
|
||||||
return (int)"do this well";
|
|
||||||
|
|
||||||
case CLI_GENERATE:
|
case CLI_GENERATE:
|
||||||
a = (struct ast_cli_args *)argv[0];
|
|
||||||
if (a->pos > e->args)
|
if (a->pos > e->args)
|
||||||
return NULL;
|
return NULL;
|
||||||
return ast_cli_complete(a->word, choices, a->n);
|
return ast_cli_complete(a->word, choices, a->n);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// we are guaranteed to be called with argc >= e->args;
|
// we are guaranteed to be called with argc >= e->args;
|
||||||
if (argc > e->args + 1) // we accept one extra argument
|
if (a->argc > e->args + 1) // we accept one extra argument
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
ast_cli(fd, "done this well for %s\n", e->args[argc-1]);
|
ast_cli(a->fd, "done this well for %s\n", e->args[argc-1]);
|
||||||
return RESULT_SUCCESS;
|
return CLI_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,12 +120,25 @@ static int test_new_cli(int fd, int argc, char *argv[])
|
|||||||
See \ref CLI_command_API
|
See \ref CLI_command_API
|
||||||
*/
|
*/
|
||||||
enum ast_cli_fn {
|
enum ast_cli_fn {
|
||||||
CLI_USAGE = -1, /* return the usage string */
|
CLI_INIT = -2, /* return the usage string */
|
||||||
CLI_CMD_STRING = -2, /* return the command string */
|
|
||||||
CLI_GENERATE = -3, /* behave as 'generator', remap argv to struct ast_cli_args */
|
CLI_GENERATE = -3, /* behave as 'generator', remap argv to struct ast_cli_args */
|
||||||
|
CLI_HANDLER = -4, /* run the normal handler */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* argument for new-style CLI handler */
|
||||||
|
struct ast_cli_args {
|
||||||
|
int fd;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
const char *line; /* the current input line */
|
||||||
|
const char *word; /* the word we want to complete */
|
||||||
|
int pos; /* position of the word to complete */
|
||||||
|
int n; /* the iteration count (n-th entry we generate) */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ast_cli_entry;
|
||||||
typedef int (*old_cli_fn)(int fd, int argc, char *argv[]);
|
typedef int (*old_cli_fn)(int fd, int argc, char *argv[]);
|
||||||
|
typedef char *(*new_cli_fn)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||||
|
|
||||||
/*! \brief descriptor for a cli entry
|
/*! \brief descriptor for a cli entry
|
||||||
See \ref CLI_command_API
|
See \ref CLI_command_API
|
||||||
@@ -161,10 +155,10 @@ struct ast_cli_entry {
|
|||||||
You can overwrite argv or the strings it points to, but remember
|
You can overwrite argv or the strings it points to, but remember
|
||||||
that this memory is deallocated after the handler returns.
|
that this memory is deallocated after the handler returns.
|
||||||
*/
|
*/
|
||||||
int (*handler)(int fd, int argc, char *argv[]);
|
old_cli_fn handler;
|
||||||
|
|
||||||
const char *summary; /*!< Summary of the command (< 60 characters) */
|
const char *summary; /*!< Summary of the command (< 60 characters) */
|
||||||
const char *usage; /*!< Detailed usage information */
|
char *usage; /*!< Detailed usage information */
|
||||||
|
|
||||||
/*! Generate the n-th (starting from 0) possible completion
|
/*! Generate the n-th (starting from 0) possible completion
|
||||||
for a given 'word' following 'line' in position 'pos'.
|
for a given 'word' following 'line' in position 'pos'.
|
||||||
@@ -188,21 +182,13 @@ struct ast_cli_entry {
|
|||||||
int args; /*!< number of non-null entries in cmda */
|
int args; /*!< number of non-null entries in cmda */
|
||||||
char *command; /*!< command, non-null for new-style entries */
|
char *command; /*!< command, non-null for new-style entries */
|
||||||
int deprecated;
|
int deprecated;
|
||||||
|
new_cli_fn new_handler;
|
||||||
char *_deprecated_by; /*!< copied from the "parent" _full_cmd, on deprecated commands */
|
char *_deprecated_by; /*!< copied from the "parent" _full_cmd, on deprecated commands */
|
||||||
/*! For linking */
|
/*! For linking */
|
||||||
AST_LIST_ENTRY(ast_cli_entry) list;
|
AST_LIST_ENTRY(ast_cli_entry) list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NEW_CLI(fn, txt) { .handler = (old_cli_fn)fn, .summary = txt }
|
#define NEW_CLI(fn, txt) { .new_handler = fn, .summary = txt }
|
||||||
|
|
||||||
/* argument for new-style CLI handler */
|
|
||||||
struct ast_cli_args {
|
|
||||||
char fake[4]; /* a fake string, in the first position, for safety */
|
|
||||||
const char *line; /* the current input line */
|
|
||||||
const char *word; /* the word we want to complete */
|
|
||||||
int pos; /* position of the word to complete */
|
|
||||||
int n; /* the iteration count (n-th entry we generate) */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Helper function to generate cli entries from a NULL-terminated array.
|
* Helper function to generate cli entries from a NULL-terminated array.
|
||||||
|
168
main/cli.c
168
main/cli.c
@@ -168,40 +168,38 @@ static int handle_reload_deprecated(int fd, int argc, char *argv[])
|
|||||||
return handle_reload(fd, argc+1, argv-1); /* see comment in handle_load_deprecated() */
|
return handle_reload(fd, argc+1, argv-1); /* see comment in handle_load_deprecated() */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_verbose(int fd, int argc, char *argv[])
|
static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||||
{
|
{
|
||||||
/* "core set verbose [atleast] <n>" */
|
|
||||||
int oldval = option_verbose;
|
int oldval = option_verbose;
|
||||||
int newlevel;
|
int newlevel;
|
||||||
int atleast = 0;
|
int atleast = 0;
|
||||||
struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
|
|
||||||
static char *choices[] = { "off", "atleast", NULL };
|
static char *choices[] = { "off", "atleast", NULL };
|
||||||
struct ast_cli_args *a;
|
int fd = a->fd;
|
||||||
|
int argc = a->argc;
|
||||||
|
char **argv = a->argv;
|
||||||
|
|
||||||
switch (argc) {
|
switch (cmd) {
|
||||||
case CLI_CMD_STRING:
|
case CLI_INIT:
|
||||||
return (int)"core set verbose";
|
e->command = "core set verbose";
|
||||||
|
e->usage =
|
||||||
case CLI_USAGE:
|
|
||||||
return (int)
|
|
||||||
"Usage: core set verbose [atleast] <level>\n"
|
"Usage: core set verbose [atleast] <level>\n"
|
||||||
" core set verbose off\n"
|
" core set verbose off\n"
|
||||||
" Sets level of verbose messages to be displayed. 0 or off means\n"
|
" Sets level of verbose messages to be displayed. 0 or off means\n"
|
||||||
" no messages should be displayed. Equivalent to -v[v[v...]]\n"
|
" no messages should be displayed. Equivalent to -v[v[v...]]\n"
|
||||||
" on startup\n";
|
" on startup\n";
|
||||||
|
return NULL;
|
||||||
|
|
||||||
case CLI_GENERATE:
|
case CLI_GENERATE:
|
||||||
a = (struct ast_cli_args *)argv[0];
|
|
||||||
if (a->pos > e->args)
|
if (a->pos > e->args)
|
||||||
return (int)NULL;
|
return NULL;
|
||||||
return (int)ast_cli_complete(a->word, choices, a->n);
|
return ast_cli_complete(a->word, choices, a->n);
|
||||||
}
|
}
|
||||||
/* all the above return, so we proceed with the handler.
|
/* all the above return, so we proceed with the handler.
|
||||||
* we are guaranteed to be called with argc >= e->args;
|
* we are guaranteed to be called with argc >= e->args;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (argc < e->args + 1)
|
if (argc < e->args + 1)
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
|
|
||||||
if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
|
if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
|
||||||
newlevel = 0;
|
newlevel = 0;
|
||||||
@@ -210,9 +208,9 @@ static int handle_verbose(int fd, int argc, char *argv[])
|
|||||||
if (!strcasecmp(argv[e->args], "atleast"))
|
if (!strcasecmp(argv[e->args], "atleast"))
|
||||||
atleast = 1;
|
atleast = 1;
|
||||||
if (argc != e->args + atleast + 1)
|
if (argc != e->args + atleast + 1)
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1)
|
if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1)
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (!atleast || newlevel > option_verbose)
|
if (!atleast || newlevel > option_verbose)
|
||||||
@@ -226,44 +224,43 @@ done:
|
|||||||
ast_cli(fd, "Verbosity was %d and is now %d\n", oldval, option_verbose);
|
ast_cli(fd, "Verbosity was %d and is now %d\n", oldval, option_verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return CLI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_set_debug(int fd, int argc, char *argv[])
|
static char *handle_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||||
{
|
{
|
||||||
struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
|
|
||||||
int oldval = option_debug;
|
int oldval = option_debug;
|
||||||
int newlevel;
|
int newlevel;
|
||||||
int atleast = 0;
|
int atleast = 0;
|
||||||
char *filename = '\0';
|
char *filename = '\0';
|
||||||
static char *choices[] = { "off", "atleast", NULL };
|
static char *choices[] = { "off", "atleast", NULL };
|
||||||
struct ast_cli_args *a;
|
int fd = a->fd;
|
||||||
|
int argc = a->argc;
|
||||||
|
char **argv = a->argv;
|
||||||
|
|
||||||
switch (argc) {
|
switch (cmd) {
|
||||||
case CLI_CMD_STRING:
|
case CLI_INIT:
|
||||||
return (int)"core set debug";
|
e->command = "core set debug";
|
||||||
|
e->usage =
|
||||||
case CLI_USAGE:
|
|
||||||
return (int)
|
|
||||||
"Usage: core set debug [atleast] <level> [filename]\n"
|
"Usage: core set debug [atleast] <level> [filename]\n"
|
||||||
" core set debug off\n"
|
" core set debug off\n"
|
||||||
" Sets level of core debug messages to be displayed. 0 or 'off' means\n"
|
" Sets level of core debug messages to be displayed. 0 or 'off' means\n"
|
||||||
" no messages should be displayed. Equivalent to -d[d[d...]]\n"
|
" no messages should be displayed. Equivalent to -d[d[d...]]\n"
|
||||||
" on startup. If filename is specified, debugging will be\n"
|
" on startup. If filename is specified, debugging will be\n"
|
||||||
" limited to just that file.\n";
|
" limited to just that file.\n";
|
||||||
|
return NULL;
|
||||||
|
|
||||||
case CLI_GENERATE:
|
case CLI_GENERATE:
|
||||||
a = (struct ast_cli_args *)argv[0];
|
|
||||||
if (a->pos > e->args)
|
if (a->pos > e->args)
|
||||||
return (int)NULL;
|
return NULL;
|
||||||
return (int)ast_cli_complete(a->word, choices, a->n);
|
return ast_cli_complete(a->word, choices, a->n);
|
||||||
}
|
}
|
||||||
/* all the above return, so we proceed with the handler.
|
/* all the above return, so we proceed with the handler.
|
||||||
* we are guaranteed to be called with argc >= e->args;
|
* we are guaranteed to be called with argc >= e->args;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (argc < e->args + 1)
|
if (argc < e->args + 1)
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
|
|
||||||
if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
|
if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
|
||||||
newlevel = 0;
|
newlevel = 0;
|
||||||
@@ -272,9 +269,9 @@ static int handle_set_debug(int fd, int argc, char *argv[])
|
|||||||
if (!strcasecmp(argv[e->args], "atleast"))
|
if (!strcasecmp(argv[e->args], "atleast"))
|
||||||
atleast = 1;
|
atleast = 1;
|
||||||
if (argc < e->args + atleast + 1 || argc > e->args + atleast + 2)
|
if (argc < e->args + atleast + 1 || argc > e->args + atleast + 2)
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1)
|
if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1)
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
|
|
||||||
if (argc == e->args + atleast + 1) {
|
if (argc == e->args + atleast + 1) {
|
||||||
debug_filename[0] = '\0';
|
debug_filename[0] = '\0';
|
||||||
@@ -302,7 +299,7 @@ done:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return CLI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_logger_mute(int fd, int argc, char *argv[])
|
static int handle_logger_mute(int fd, int argc, char *argv[])
|
||||||
@@ -415,80 +412,72 @@ static void print_uptimestr(int fd, time_t timeval, const char *prefix, int prin
|
|||||||
ast_cli(fd, "%s: %s\n", prefix, timestr);
|
ast_cli(fd, "%s: %s\n", prefix, timestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_showuptime(int fd, int argc, char *argv[])
|
static char * handle_showuptime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||||
{
|
{
|
||||||
struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
|
|
||||||
time_t curtime;
|
time_t curtime;
|
||||||
int printsec;
|
int printsec;
|
||||||
struct ast_cli_args *a;
|
|
||||||
|
|
||||||
switch (argc) {
|
switch (cmd) {
|
||||||
case CLI_CMD_STRING:
|
case CLI_INIT:
|
||||||
return (int)"core show uptime";
|
e->command = "core show uptime";
|
||||||
|
e->usage =
|
||||||
case CLI_USAGE:
|
|
||||||
return (int)
|
|
||||||
"Usage: core show uptime [seconds]\n"
|
"Usage: core show uptime [seconds]\n"
|
||||||
" Shows Asterisk uptime information.\n"
|
" Shows Asterisk uptime information.\n"
|
||||||
" The seconds word returns the uptime in seconds only.\n";
|
" The seconds word returns the uptime in seconds only.\n";
|
||||||
|
return NULL;
|
||||||
|
|
||||||
case CLI_GENERATE:
|
case CLI_GENERATE:
|
||||||
a = (struct ast_cli_args *)argv[0];
|
return (a->pos > e->args || a->n > 0) ? NULL : "seconds";
|
||||||
return (int)((a->pos > e->args || a->n > 0) ? NULL : "seconds");
|
|
||||||
}
|
}
|
||||||
/* regular handler */
|
/* regular handler */
|
||||||
if (argc == e->args+1 && !strcasecmp(argv[e->args],"seconds"))
|
if (a->argc == e->args+1 && !strcasecmp(a->argv[e->args],"seconds"))
|
||||||
printsec = 1;
|
printsec = 1;
|
||||||
else if (argc == e->args)
|
else if (a->argc == e->args)
|
||||||
printsec = 0;
|
printsec = 0;
|
||||||
else
|
else
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
curtime = time(NULL);
|
curtime = time(NULL);
|
||||||
if (ast_startuptime)
|
if (ast_startuptime)
|
||||||
print_uptimestr(fd, curtime - ast_startuptime, "System uptime", printsec);
|
print_uptimestr(a->fd, curtime - ast_startuptime, "System uptime", printsec);
|
||||||
if (ast_lastreloadtime)
|
if (ast_lastreloadtime)
|
||||||
print_uptimestr(fd, curtime - ast_lastreloadtime, "Last reload", printsec);
|
print_uptimestr(a->fd, curtime - ast_lastreloadtime, "Last reload", printsec);
|
||||||
return RESULT_SUCCESS;
|
return CLI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_modlist(int fd, int argc, char *argv[])
|
static char *handle_modlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||||
{
|
{
|
||||||
struct ast_cli_entry *e = (struct ast_cli_entry *)argv[-1];
|
|
||||||
char *like;
|
char *like;
|
||||||
struct ast_cli_args *a;
|
|
||||||
|
|
||||||
switch(argc) {
|
switch (cmd) {
|
||||||
case CLI_CMD_STRING:
|
case CLI_INIT:
|
||||||
return (int)"module show";
|
e->command = "module show";
|
||||||
|
e->usage =
|
||||||
case CLI_USAGE:
|
|
||||||
return (int)
|
|
||||||
"Usage: module show [like keyword]\n"
|
"Usage: module show [like keyword]\n"
|
||||||
" Shows Asterisk modules currently in use, and usage statistics.\n";
|
" Shows Asterisk modules currently in use, and usage statistics.\n";
|
||||||
|
return NULL;
|
||||||
|
|
||||||
case CLI_GENERATE:
|
case CLI_GENERATE:
|
||||||
a = (struct ast_cli_args *)argv[0];
|
|
||||||
if (a->pos == e->args)
|
if (a->pos == e->args)
|
||||||
return (int)(a->n == 0 ? strdup("like") : NULL);
|
return a->n == 0 ? strdup("like") : NULL;
|
||||||
else if (a->pos == e->args+1 && strcasestr(a->line," like "))
|
else if (a->pos == e->args+1 && strcasestr(a->line," like "))
|
||||||
return (int)ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
|
return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
|
||||||
else
|
else
|
||||||
return (int)NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* all the above return, so we proceed with the handler.
|
/* all the above return, so we proceed with the handler.
|
||||||
* we are guaranteed to have argc >= e->args
|
* we are guaranteed to have argc >= e->args
|
||||||
*/
|
*/
|
||||||
if (argc == e->args)
|
if (a->argc == e->args)
|
||||||
like = "";
|
like = "";
|
||||||
else if (argc == e->args + 2 && !strcmp(argv[e->args],"like"))
|
else if (a->argc == e->args + 2 && !strcmp(a->argv[e->args],"like"))
|
||||||
like = argv[e->args + 1];
|
like = a->argv[e->args + 1];
|
||||||
else
|
else
|
||||||
return RESULT_SHOWUSAGE;
|
return CLI_SHOWUSAGE;
|
||||||
|
|
||||||
ast_mutex_lock(&climodentrylock);
|
ast_mutex_lock(&climodentrylock);
|
||||||
climodentryfd = fd; /* global, protected by climodentrylock */
|
climodentryfd = a->fd; /* global, protected by climodentrylock */
|
||||||
ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
|
ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
|
||||||
ast_cli(fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
|
ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
|
||||||
climodentryfd = -1;
|
climodentryfd = -1;
|
||||||
ast_mutex_unlock(&climodentrylock);
|
ast_mutex_unlock(&climodentrylock);
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
@@ -1281,9 +1270,9 @@ static int __ast_cli_unregister(struct ast_cli_entry *e, struct ast_cli_entry *e
|
|||||||
AST_LIST_UNLOCK(&helpers);
|
AST_LIST_UNLOCK(&helpers);
|
||||||
free(e->_full_cmd);
|
free(e->_full_cmd);
|
||||||
e->_full_cmd = NULL;
|
e->_full_cmd = NULL;
|
||||||
if (e->command) {
|
if (e->new_handler) {
|
||||||
/* this is a new-style entry. Reset fields and free memory. */
|
/* this is a new-style entry. Reset fields and free memory. */
|
||||||
((char **)e->cmda)[0] = NULL;
|
bzero((char **)(e->cmda), sizeof(e->cmda));
|
||||||
free(e->command);
|
free(e->command);
|
||||||
e->command = NULL;
|
e->command = NULL;
|
||||||
e->usage = NULL;
|
e->usage = NULL;
|
||||||
@@ -1298,12 +1287,15 @@ static int __ast_cli_register(struct ast_cli_entry *e, struct ast_cli_entry *ed)
|
|||||||
char fulle[80] ="";
|
char fulle[80] ="";
|
||||||
int i, lf, ret = -1;
|
int i, lf, ret = -1;
|
||||||
|
|
||||||
if (e->cmda[0] == NULL) { /* new style entry, run the handler to init fields */
|
if (e->handler == NULL) { /* new style entry, run the handler to init fields */
|
||||||
char *args[2] = { (char *)e, NULL };
|
struct ast_cli_args a; /* fake argument */
|
||||||
char *s = (char *)(e->handler(-1, CLI_CMD_STRING, args+1));
|
|
||||||
char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
|
char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
|
||||||
|
char *s;
|
||||||
|
|
||||||
s = ast_skip_blanks(s);
|
bzero (&a, sizeof(a));
|
||||||
|
e->new_handler(e, CLI_INIT, &a);
|
||||||
|
/* XXX check that usage and command are filled up */
|
||||||
|
s = ast_skip_blanks(e->command);
|
||||||
s = e->command = ast_strdup(s);
|
s = e->command = ast_strdup(s);
|
||||||
for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
|
for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
|
||||||
*dst++ = s; /* store string */
|
*dst++ = s; /* store string */
|
||||||
@@ -1314,7 +1306,6 @@ static int __ast_cli_register(struct ast_cli_entry *e, struct ast_cli_entry *ed)
|
|||||||
s = ast_skip_blanks(s);
|
s = ast_skip_blanks(s);
|
||||||
}
|
}
|
||||||
*dst++ = NULL;
|
*dst++ = NULL;
|
||||||
e->usage = (char *)(e->handler(-1, CLI_USAGE, args+1));
|
|
||||||
}
|
}
|
||||||
for (i = 0; e->cmda[i]; i++)
|
for (i = 0; e->cmda[i]; i++)
|
||||||
;
|
;
|
||||||
@@ -1638,21 +1629,12 @@ static char *__ast_cli_generator(const char *text, const char *word, int state,
|
|||||||
*/
|
*/
|
||||||
if (e->generator)
|
if (e->generator)
|
||||||
ret = e->generator(matchstr, word, argindex, state - matchnum);
|
ret = e->generator(matchstr, word, argindex, state - matchnum);
|
||||||
else if (e->command) { /* new style command */
|
else if (e->new_handler) { /* new style command */
|
||||||
/* prepare fake arguments for the generator.
|
|
||||||
* argv[-1] is the cli entry we use,
|
|
||||||
* argv[0] is a pointer to the generator arguments,
|
|
||||||
* with a fake string '-' at the beginning so we can
|
|
||||||
* dereference it as a string with no trouble,
|
|
||||||
* and then the usual NULL terminator.
|
|
||||||
*/
|
|
||||||
struct ast_cli_args a = {
|
struct ast_cli_args a = {
|
||||||
.fake = "-",
|
|
||||||
.line = matchstr, .word = word,
|
.line = matchstr, .word = word,
|
||||||
.pos = argindex,
|
.pos = argindex,
|
||||||
.n = state - matchnum };
|
.n = state - matchnum };
|
||||||
char *args[] = { (char *)e, (char *)&a, NULL };
|
ret = e->new_handler(e, CLI_GENERATE, &a);
|
||||||
ret = (char *)e->handler(-1, CLI_GENERATE, args + 1);
|
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
@@ -1688,11 +1670,19 @@ int ast_cli_command(int fd, const char *s)
|
|||||||
e->inuse++;
|
e->inuse++;
|
||||||
AST_LIST_UNLOCK(&helpers);
|
AST_LIST_UNLOCK(&helpers);
|
||||||
if (e) {
|
if (e) {
|
||||||
|
int res;
|
||||||
/* within calling the handler, argv[-1] contains a pointer
|
/* within calling the handler, argv[-1] contains a pointer
|
||||||
* to the cli entry, and the array is null-terminated
|
* to the cli entry, and the array is null-terminated
|
||||||
*/
|
*/
|
||||||
args[0] = (char *)e;
|
args[0] = (char *)e;
|
||||||
switch(e->handler(fd, x, args + 1)) {
|
if (e->new_handler) { /* new style */
|
||||||
|
struct ast_cli_args a = {
|
||||||
|
.fd = fd, .argc = x, .argv = args+1 };
|
||||||
|
res = (int)e->new_handler(e, CLI_HANDLER, &a);
|
||||||
|
} else { /* old style */
|
||||||
|
res = e->handler(fd, x, args + 1);
|
||||||
|
}
|
||||||
|
switch (res) {
|
||||||
case RESULT_SHOWUSAGE:
|
case RESULT_SHOWUSAGE:
|
||||||
if (e->usage)
|
if (e->usage)
|
||||||
ast_cli(fd, "%s", e->usage);
|
ast_cli(fd, "%s", e->usage);
|
||||||
|
Reference in New Issue
Block a user