Add "dialplan remove context" and modify "dialplan add include"
authorMark Michelson <mmichelson@digium.com>
Tue, 31 Jul 2012 19:57:21 +0000 (19:57 +0000)
committerMark Michelson <mmichelson@digium.com>
Tue, 31 Jul 2012 19:57:21 +0000 (19:57 +0000)
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

CHANGES
pbx/pbx_config.c

diff --git a/CHANGES b/CHANGES
index 526427f..7d5e7fb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -478,6 +478,13 @@ AMI (Asterisk Manager Interface)
 
 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
    filenames of all running mixmonitors on a channel.
 
index 488241a..014f7f6 100644 (file)
@@ -68,12 +68,49 @@ static char *complete_dialplan_remove_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_add_extension(struct ast_cli_args *);
+static char *complete_dialplan_remove_context(struct ast_cli_args *);
 
 /*
  * 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
  */
 static char *handle_cli_dialplan_remove_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -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)
 {
+       const char *into_context;
+
        switch (cmd) {
        case CLI_INIT:
                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"))
                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)) {
                switch (errno) {
                case ENOMEM:
@@ -595,43 +646,18 @@ static char *complete_dialplan_add_include(struct ast_cli_args *a)
                ast_unlock_contexts();
                return ret;
        } else if (a->pos == 4) { /* dialplan add include CTX _X_ */
-               /* complete  as 'into' if context exists or we are unable to check */
-               char *context, *dupline;
-               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;
+               /* always complete  as 'into' */
+               return (a->n == 0) ? strdup("into") : NULL;
        } else if (a->pos == 5) { /* 'dialplan add include CTX into _X_' (dst context) */
                char *context, *dupline, *into;
                const char *s = skip_words(a->line, 3); /* should not fail */
                context = dupline = strdup(s);
+
                if (!dupline) {
                        ast_log(LOG_ERROR, "Out of free memory\n");
                        return NULL;
                }
+
                strsep(&dupline, " "); /* skip context */
                into = strsep(&dupline, " ");
                /* 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;
                }
 
-               for (c = NULL; (c = ast_walk_contexts(c)); )
+               for (c = NULL; !ret && (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)); ) {
-                               if (!strcmp(context, ast_get_context_name(c)))
-                                       continue; /* skip ourselves */
-                               if (partial_match(ast_get_context_name(c), a->word, len) &&
-                                               !lookup_ci(c, context) /* not included yet */ &&
-                                               ++which > a->n)
-                                       ret = strdup(ast_get_context_name(c));
+                               continue; /* skip ourselves */
+                       if (partial_match(ast_get_context_name(c), a->word, len) &&
+                                       !lookup_ci(c, context) /* not included yet */ &&
+                                       ++which > a->n) {
+                               ret = strdup(ast_get_context_name(c));
                        }
-               } else {
-                       ast_log(LOG_ERROR, "context %s not found\n", context);
                }
                ast_unlock_contexts();
        error3:
@@ -1038,6 +1057,34 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
        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 */
 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[] = {
        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_context,   "Remove a specified context"),
        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_add_include,      "Include context in other context"),