CLI commands are described by a struct ast_cli_entry that contains all the components for their implementation.
In the "old-style" format, the record must contain:
int old_setdebug(int fd, int argc, char *argv[]); char *dbg_complete(const char *line, const char *word, int pos, int n);
{ { "set", "debug", "on", NULL }, do_setdebug, "Enable debugging", set_debug_usage, dbg_complete },
In the "new-style" format, all the above functionalities are implemented by a single function, and the arguments tell which output is required. The prototype is the following:
char *new_setdebug(const struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
... this is how we create the entry to register AST_CLI_DEFINE(new_setdebug, "short description") ...
To help the transition, we make the pointer to the struct ast_cli_entry available to old-style handlers via argv[-1].
An example of new-style handler is the following
static char *test_new_cli(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { static const char * const choices[] = { "one", "two", "three", NULL }; switch (cmd) { case CLI_INIT: e->command = "do this well"; e->usage = "Usage: do this well <arg>\n" " typically multiline with body indented\n"; return NULL; case CLI_GENERATE: if (a->pos > e->args) return NULL; return ast_cli_complete(a->word, choices, a->n); default: // we are guaranteed to be called with argc >= e->args; if (a->argc > e->args + 1) // we accept one extra argument return CLI_SHOWUSAGE; ast_cli(a->fd, "done this well for %s\n", e->args[argc-1]); return CLI_SUCCESS; } }