Add "dialplan remove context" and modify "dialplan add include"

From corruptor's review board posting:

"I've noticed that we can remove particular extension from context with
dialplan remove extension command but in order to remove all extensions
in the context we should delete them on by one. I've created dialplan
remove context command which uses ast_context_destroy to destroy the
whole context with all extensions. I've created to functions for in
pbx_config.c: handle_cli_dialplan_remove_context which actually removes
context and complete_dialplan_remove_context which completes input.
They are based on other similar functions and pretty trivial but I can be
mistaken somewhere.

"I've also modified dialplan add include <context2> into <context1>. I've
made it similar dialplan add extension ... command. It creates <context1>
if it doesn't exist and I've also modified complete_dialplan_add_include
and removed check for existance of <context2> because we can include
non-existent context into another one. (I usually include empty
(non-existent) contexts in advance). Should we raise warning in this case
as it's raised while reading extensions.conf?

"I use those functions with AMI. I think manager commands should be created
in addition to those CLI commands."

I've addressed the latest comments on review board and have made some other
coding guidelines-related cleanup. I also have modified the CHANGES file to
mention these new commands.

(closes issue ASTERISK-19292)
reported by Andrey Solovyev

Patches:
	dialplan_add_include.patch
    uploaded by Andrey Solovyev (license #5214)
    dialplan_remove_context.patch
    uploaded by Andrey Solovyev (license #5214)

Review: https://reviewboard.asterisk.org/r/2042



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@370644 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Michelson
2012-07-31 19:57:21 +00:00
parent e5210366e4
commit 6c23a60f80
2 changed files with 97 additions and 42 deletions

View File

@@ -478,6 +478,13 @@ AMI (Asterisk Manager Interface)
CLI CLI
------------------- -------------------
* The "dialplan add include" command has been modified to create context a context
if one does not already exist. For instance, "dialplan add include foo into bar"
will create context "bar" if it does not already exist.
* A "dialplan remove context" command has been added to remove a context from
the dialplan
* The "mixmonitor list <channel>" command will now show MixMonitor ID, and the * The "mixmonitor list <channel>" command will now show MixMonitor ID, and the
filenames of all running mixmonitors on a channel. filenames of all running mixmonitors on a channel.

View File

@@ -68,11 +68,48 @@ static char *complete_dialplan_remove_ignorepat(struct ast_cli_args *);
static char *complete_dialplan_add_ignorepat(struct ast_cli_args *); static char *complete_dialplan_add_ignorepat(struct ast_cli_args *);
static char *complete_dialplan_remove_extension(struct ast_cli_args *); static char *complete_dialplan_remove_extension(struct ast_cli_args *);
static char *complete_dialplan_add_extension(struct ast_cli_args *); static char *complete_dialplan_add_extension(struct ast_cli_args *);
static char *complete_dialplan_remove_context(struct ast_cli_args *);
/* /*
* Implementation of functions provided by this module * Implementation of functions provided by this module
*/ */
/*!
* * REMOVE context command stuff
*/
static char *handle_cli_dialplan_remove_context(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ast_context *con;
switch (cmd) {
case CLI_INIT:
e->command = "dialplan remove context";
e->usage =
"Usage: dialplan remove context <context>\n"
" Removes all extensions from a specified context.\n";
return NULL;
case CLI_GENERATE:
return complete_dialplan_remove_context(a);
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
con = ast_context_find(a->argv[3]);
if (!con) {
ast_cli(a->fd, "There is no such context as '%s'\n",
a->argv[3]);
return CLI_SUCCESS;
} else {
ast_context_destroy(con, registrar);
ast_cli(a->fd, "Removing context '%s'\n",
a->argv[3]);
return CLI_SUCCESS;
}
}
/*! /*!
* REMOVE INCLUDE command stuff * REMOVE INCLUDE command stuff
*/ */
@@ -523,6 +560,8 @@ static char *complete_dialplan_remove_extension(struct ast_cli_args *a)
*/ */
static char *handle_cli_dialplan_add_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) static char *handle_cli_dialplan_add_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{ {
const char *into_context;
switch (cmd) { switch (cmd) {
case CLI_INIT: case CLI_INIT:
e->command = "dialplan add include"; e->command = "dialplan add include";
@@ -541,6 +580,18 @@ static char *handle_cli_dialplan_add_include(struct ast_cli_entry *e, int cmd, s
if (strcmp(a->argv[4], "into")) if (strcmp(a->argv[4], "into"))
return CLI_SHOWUSAGE; return CLI_SHOWUSAGE;
into_context = a->argv[5];
if (!ast_context_find(into_context)) {
ast_cli(a->fd, "Context '%s' did not exist prior to add include - the context will be created.\n", into_context);
}
if (!ast_context_find_or_create(NULL, NULL, into_context, registrar)) {
ast_cli(a->fd, "ast_context_find_or_create() failed\n");
ast_cli(a->fd, "Failed to include '%s' in '%s' context\n",a->argv[3], a->argv[5]);
return CLI_FAILURE;
}
if (ast_context_add_include(a->argv[5], a->argv[3], registrar)) { if (ast_context_add_include(a->argv[5], a->argv[3], registrar)) {
switch (errno) { switch (errno) {
case ENOMEM: case ENOMEM:
@@ -595,43 +646,18 @@ static char *complete_dialplan_add_include(struct ast_cli_args *a)
ast_unlock_contexts(); ast_unlock_contexts();
return ret; return ret;
} else if (a->pos == 4) { /* dialplan add include CTX _X_ */ } else if (a->pos == 4) { /* dialplan add include CTX _X_ */
/* complete as 'into' if context exists or we are unable to check */ /* always complete as 'into' */
char *context, *dupline; return (a->n == 0) ? strdup("into") : NULL;
const char *s = skip_words(a->line, 3); /* should not fail */
if (a->n != 0) /* only once */
return NULL;
/* parse context from line ... */
context = dupline = strdup(s);
if (!context) {
ast_log(LOG_ERROR, "Out of free memory\n");
return strdup("into");
}
strsep(&dupline, " ");
/* check for context existence ... */
if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
/* our fault, we can't check, so complete 'into' ... */
ret = strdup("into");
} else {
struct ast_context *ctx;
for (ctx = NULL; !ret && (ctx = ast_walk_contexts(ctx)); )
if (!strcmp(context, ast_get_context_name(ctx)))
ret = strdup("into"); /* found */
ast_unlock_contexts();
}
free(context);
return ret;
} else if (a->pos == 5) { /* 'dialplan add include CTX into _X_' (dst context) */ } else if (a->pos == 5) { /* 'dialplan add include CTX into _X_' (dst context) */
char *context, *dupline, *into; char *context, *dupline, *into;
const char *s = skip_words(a->line, 3); /* should not fail */ const char *s = skip_words(a->line, 3); /* should not fail */
context = dupline = strdup(s); context = dupline = strdup(s);
if (!dupline) { if (!dupline) {
ast_log(LOG_ERROR, "Out of free memory\n"); ast_log(LOG_ERROR, "Out of free memory\n");
return NULL; return NULL;
} }
strsep(&dupline, " "); /* skip context */ strsep(&dupline, " "); /* skip context */
into = strsep(&dupline, " "); into = strsep(&dupline, " ");
/* error if missing context or fifth word is not 'into' */ /* error if missing context or fifth word is not 'into' */
@@ -646,21 +672,14 @@ static char *complete_dialplan_add_include(struct ast_cli_args *a)
goto error3; goto error3;
} }
for (c = NULL; (c = ast_walk_contexts(c)); )
if (!strcmp(context, ast_get_context_name(c)))
break;
if (c) { /* first context exists, go on... */
/* go through all contexts ... */
for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) { for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
if (!strcmp(context, ast_get_context_name(c))) if (!strcmp(context, ast_get_context_name(c)))
continue; /* skip ourselves */ continue; /* skip ourselves */
if (partial_match(ast_get_context_name(c), a->word, len) && if (partial_match(ast_get_context_name(c), a->word, len) &&
!lookup_ci(c, context) /* not included yet */ && !lookup_ci(c, context) /* not included yet */ &&
++which > a->n) ++which > a->n) {
ret = strdup(ast_get_context_name(c)); ret = strdup(ast_get_context_name(c));
} }
} else {
ast_log(LOG_ERROR, "context %s not found\n", context);
} }
ast_unlock_contexts(); ast_unlock_contexts();
error3: error3:
@@ -1038,6 +1057,34 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
return CLI_SUCCESS; return CLI_SUCCESS;
} }
static char *complete_dialplan_remove_context(struct ast_cli_args *a)
{
struct ast_context *c = NULL;
int len = strlen(a->word);
char *res = NULL;
int which = 0;
if (a->pos != 3) {
return NULL;
}
/* try to lock contexts list ... */
if (ast_rdlock_contexts()) {
ast_log(LOG_WARNING, "Failed to lock contexts list\n");
return NULL;
}
/* walk through all contexts */
while ( !res && (c = ast_walk_contexts(c)) ) {
if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n) {
res = strdup(ast_get_context_name(c));
}
}
ast_unlock_contexts();
return res;
}
/*! dialplan add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local */ /*! dialplan add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local */
static char *complete_dialplan_add_extension(struct ast_cli_args *a) static char *complete_dialplan_add_extension(struct ast_cli_args *a)
{ {
@@ -1336,6 +1383,7 @@ static char *handle_cli_dialplan_reload(struct ast_cli_entry *e, int cmd, struct
static struct ast_cli_entry cli_pbx_config[] = { static struct ast_cli_entry cli_pbx_config[] = {
AST_CLI_DEFINE(handle_cli_dialplan_add_extension, "Add new extension into context"), AST_CLI_DEFINE(handle_cli_dialplan_add_extension, "Add new extension into context"),
AST_CLI_DEFINE(handle_cli_dialplan_remove_extension, "Remove a specified extension"), AST_CLI_DEFINE(handle_cli_dialplan_remove_extension, "Remove a specified extension"),
AST_CLI_DEFINE(handle_cli_dialplan_remove_context, "Remove a specified context"),
AST_CLI_DEFINE(handle_cli_dialplan_add_ignorepat, "Add new ignore pattern"), AST_CLI_DEFINE(handle_cli_dialplan_add_ignorepat, "Add new ignore pattern"),
AST_CLI_DEFINE(handle_cli_dialplan_remove_ignorepat, "Remove ignore pattern from context"), AST_CLI_DEFINE(handle_cli_dialplan_remove_ignorepat, "Remove ignore pattern from context"),
AST_CLI_DEFINE(handle_cli_dialplan_add_include, "Include context in other context"), AST_CLI_DEFINE(handle_cli_dialplan_add_include, "Include context in other context"),