Merged revisions 310462 via svnmerge from
[asterisk/asterisk.git] / pbx / pbx_config.c
index 0c90ec0..0baa8e1 100644 (file)
@@ -38,8 +38,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"  /* AST_MAX_EXTENSION */
 #include "asterisk/callerid.h"
 
-static char *config = "extensions.conf";
-static char *registrar = "pbx_config";
+static const char config[] = "extensions.conf";
+static const char registrar[] = "pbx_config";
 static char userscontext[AST_MAX_EXTENSION] = "default";
 
 static int static_config = 0;
@@ -328,7 +328,7 @@ static char *handle_cli_dialplan_remove_extension(struct ast_cli_entry *e, int c
         * Priority input checking ...
         */
        if (a->argc == 5) {
-               char *c = a->argv[4];
+               const char *c = a->argv[4];
 
                /* check for digits in whole parameter for right priority ...
                 * why? because atoi (strtol) returns 0 if any characters in
@@ -389,71 +389,11 @@ static char *handle_cli_dialplan_remove_extension(struct ast_cli_entry *e, int c
        return ret;
 }
 
-#define BROKEN_READLINE 1
-
-#ifdef BROKEN_READLINE
-/*
- * There is one funny thing, when you have word like 300@ and you hit
- * <tab>, you arguments will act as your word is '300 ', so the '@'
- * character acts sometimes as a word delimiter and sometimes as a part
- * of a word.
- *
- * This fix function allocates a new word variable and stores it every
- * time as xxx@yyy. The correct pos is set, too.
- *
- * It's ugly, I know, but I'm waiting for Mark's suggestion if the
- * previous is a bug or a feature ...
- */
-static int fix_complete_args(const char *line, char **word, int *pos)
-{
-       char *_line, *_strsep_line, *_previous_word = NULL, *_word = NULL;
-       int words = 0;
-
-       _line = strdup(line);
-
-       _strsep_line = _line;
-       while (_strsep_line) {
-               _previous_word = _word;
-               _word = strsep(&_strsep_line, " ");
-
-               if (_word && strlen(_word)) words++;
-       }
-
-
-       if (_word || _previous_word) {
-               if (_word) {
-                       if (!strlen(_word)) words++;
-                       *word = strdup(_word);
-               } else
-                       *word = strdup(_previous_word);
-               *pos = words - 1;
-               free(_line);
-               return 0;
-       }
-
-       free(_line);
-       return -1;
-}
-#endif /* BROKEN_READLINE */
-
 static char *complete_dialplan_remove_extension(struct ast_cli_args *a)
 {
        char *ret = NULL;
        int which = 0;
 
-#ifdef BROKEN_READLINE
-       char *word2;
-       /*
-        * Fix arguments, *word is a new allocated structure, REMEMBER to
-        * free *word when you want to return from this function ...
-        */
-       if (fix_complete_args(a->line, &word2, &a->pos)) {
-               ast_log(LOG_ERROR, "Out of free memory\n");
-               return NULL;
-       }
-       a->word = word2;
-#endif
-
        if (a->pos == 3) { /* 'dialplan remove extension _X_' (exten@context ... */
                struct ast_context *c = NULL;
                char *context = NULL, *exten = NULL, *cid = NULL;
@@ -463,9 +403,6 @@ static char *complete_dialplan_remove_extension(struct ast_cli_args *a)
 
                lc = split_ec(a->word, &exten, &context, &cid);
                if (lc) { /* error */
-#ifdef BROKEN_READLINE
-                       free(word2);
-#endif
                        return NULL;
                }
                le = strlen(exten);
@@ -514,12 +451,11 @@ static char *complete_dialplan_remove_extension(struct ast_cli_args *a)
 
                ast_unlock_contexts();
        error2:
-               if (exten)
-                       free(exten);
+               free(exten);
        } else if (a->pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */
                char *exten = NULL, *context, *cid, *p;
                struct ast_context *c;
-               int le, lc, lcid, len;
+               int le, lc, len;
                const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'extension' */
                int i = split_ec(s, &exten, &context, &cid);    /* parse ext@context */
 
@@ -531,7 +467,6 @@ static char *complete_dialplan_remove_extension(struct ast_cli_args *a)
                        *p = '\0';
                le = strlen(exten);
                lc = strlen(context);
-               lcid = strlen(cid);
                len = strlen(a->word);
                if (le == 0 || lc == 0)
                        goto error3;
@@ -572,12 +507,8 @@ static char *complete_dialplan_remove_extension(struct ast_cli_args *a)
                }
                ast_unlock_contexts();
        error3:
-               if (exten)
-                       free(exten);
+               free(exten);
        }
-#ifdef BROKEN_READLINE
-       free(word2);
-#endif
        return ret; 
 }
 
@@ -1001,8 +932,7 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
                if (strcmp(a->argv[6], "replace"))
                        return CLI_SHOWUSAGE;
 
-       /* XXX overwrite argv[3] */
-       whole_exten = a->argv[3];
+       whole_exten = ast_strdupa(a->argv[3]);
        exten = strsep(&whole_exten,",");
        if (strchr(exten, '/')) {
                cidmatch = exten;
@@ -1015,7 +945,7 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
                if (!strcmp(prior, "hint")) {
                        iprior = PRIORITY_HINT;
                } else {
-                       if (sscanf(prior, "%d", &iprior) != 1) {
+                       if (sscanf(prior, "%30d", &iprior) != 1) {
                                ast_cli(a->fd, "'%s' is not a valid priority\n", prior);
                                prior = NULL;
                        }
@@ -1205,8 +1135,7 @@ static char *complete_dialplan_add_ignorepat(struct ast_cli_args *a)
                                ret = strdup(ast_get_context_name(c));
                }
 
-               if (ignorepat)
-                       free(ignorepat);
+               free(ignorepat);
                ast_unlock_contexts();
                return ret;
        }
@@ -1502,7 +1431,7 @@ static int pbx_load_config(const char *config_file)
 
                        if (!strncasecmp(v->name, "same", 4)) {
                                if (ast_strlen_zero(lastextension)) {
-                                       ast_log(LOG_ERROR, "No previous pattern in the first entry of context '%s' to match '%s'!\n", cxt, v->name);
+                                       ast_log(LOG_ERROR, "No previous pattern in the first entry of context '%s' to match '%s' at line %d!\n", cxt, v->name, v->lineno);
                                        continue;
                                }
                                if ((stringp = tc = ast_strdup(v->value))) {
@@ -1510,7 +1439,7 @@ static int pbx_load_config(const char *config_file)
                                        goto process_extension;
                                }
                        } else if (!strcasecmp(v->name, "exten")) {
-                               int ipri = -2;
+                               int ipri;
                                char *plus, *firstp;
                                char *pri, *appl, *data, *cidmatch;
 
@@ -1522,19 +1451,20 @@ static int pbx_load_config(const char *config_file)
                                pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
                                ast_copy_string(lastextension, realext, sizeof(lastextension));
 process_extension:
+                               ipri = -2;
                                if ((cidmatch = strchr(realext, '/'))) {
                                        *cidmatch++ = '\0';
                                        ast_shrink_phone_number(cidmatch);
                                }
-                               pri = S_OR(strsep(&stringp, ","), "");
-                               pri = ast_skip_blanks(pri);
-                               pri = ast_trim_blanks(pri);
+                               pri = ast_strip(S_OR(strsep(&stringp, ","), ""));
                                if ((label = strchr(pri, '('))) {
                                        *label++ = '\0';
                                        if ((end = strchr(label, ')'))) {
                                                *end = '\0';
                                        } else {
                                                ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno);
+                                               ast_free(tc);
+                                               continue;
                                        }
                                }
                                if ((plus = strchr(pri, '+'))) {
@@ -1546,18 +1476,28 @@ process_extension:
                                        if (lastpri > -2) {
                                                ipri = lastpri + 1;
                                        } else {
-                                               ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
+                                               ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry at line %d!\n", v->lineno);
+                                               ast_free(tc);
+                                               continue;
                                        }
                                } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
                                        if (lastpri > -2) {
                                                ipri = lastpri;
                                        } else {
-                                               ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
+                                               ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry at line %d!\n", v->lineno);
+                                               ast_free(tc);
+                                               continue;
                                        }
-                               } else if (sscanf(pri, "%d", &ipri) != 1 &&
+                               } else if (sscanf(pri, "%30d", &ipri) != 1 &&
                                           (ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
                                        ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
                                        ipri = 0;
+                                       ast_free(tc);
+                                       continue;
+                               } else if (ipri < 1) {
+                                       ast_log(LOG_WARNING, "Invalid priority '%s' at line %d\n", pri, v->lineno);
+                                       ast_free(tc);
+                                       continue;
                                }
                                appl = S_OR(stringp, "");
                                /* Find the first occurrence of '(' */
@@ -1565,13 +1505,31 @@ process_extension:
                                        /* No arguments */
                                        data = "";
                                } else {
+                                       char *orig_appl = ast_strdup(appl);
+
+                                       if (!orig_appl) {
+                                               ast_free(tc);
+                                               continue;
+                                       }
+
                                        appl = strsep(&stringp, "(");
-                                       data = S_OR(stringp, "");
-                                       if ((end = strrchr(data, ')'))) {
-                                               *end = '\0';
+
+                                       /* check if there are variables or expressions without an application, like: exten => 100,hint,DAHDI/g0/${GLOBAL(var)}  */
+                                       if (strstr(appl, "${") || strstr(appl, "$[")){
+                                               /* set appl to original one */
+                                               strcpy(appl, orig_appl);
+                                               /* set no data */
+                                               data = "";
+                                       /* no variable before application found -> go ahead */
                                        } else {
-                                               ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
+                                               data = S_OR(stringp, "");
+                                               if ((end = strrchr(data, ')'))) {
+                                                       *end = '\0';
+                                               } else {
+                                                       ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s' at line %d\n", appl, data, v->lineno);
+                                               }
                                        }
+                                       ast_free(orig_appl);
                                }
 
                                appl = ast_skip_blanks(appl);
@@ -1580,8 +1538,8 @@ process_extension:
                                                ipri += atoi(plus);
                                        }
                                        lastpri = ipri;
-                                       if (!ast_opt_dont_warn && !strcmp(realext, "_.")) {
-                                               ast_log(LOG_WARNING, "The use of '_.' for an extension is strongly discouraged and can have unexpected behavior.  Please use '_X.' instead at line %d\n", v->lineno);
+                                       if (!ast_opt_dont_warn && (!strcmp(realext, "_.") || !strcmp(realext, "_!"))) {
+                                               ast_log(LOG_WARNING, "The use of '%s' for an extension is strongly discouraged and can have unexpected behavior.  Please use '_X%c' instead at line %d\n", realext, realext[1], v->lineno);
                                        }
                                        if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), ast_free_ptr, registrar)) {
                                                ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
@@ -1601,26 +1559,26 @@ process_extension:
                                                        break;
 
                                                case EEXIST:
-                                                       ast_log(LOG_WARNING, "Context '%s' already included in '%s' context\n",
-                                                                       v->value, cxt);
+                                                       ast_log(LOG_WARNING, "Context '%s' already included in '%s' context on include at line %d\n",
+                                                                       v->value, cxt, v->lineno);
                                                        break;
 
                                                case ENOENT:
                                                case EINVAL:
-                                                       ast_log(LOG_WARNING, "There is no existence of context '%s'\n",
-                                                                       errno == ENOENT ? v->value : cxt);
+                                                       ast_log(LOG_WARNING, "There is no existence of context '%s' included at line %d\n",
+                                                                       errno == ENOENT ? v->value : cxt, v->lineno);
                                                        break;
 
                                                default:
-                                                       ast_log(LOG_WARNING, "Failed to include '%s' in '%s' context\n",
-                                                                       v->value, cxt);
+                                                       ast_log(LOG_WARNING, "Failed to include '%s' in '%s' context at line %d\n",
+                                                                       v->value, cxt, v->lineno);
                                                        break;
                                        }
                                }
                        } else if (!strcasecmp(v->name, "ignorepat")) {
                                pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
                                if (ast_context_add_ignorepat2(con, realvalue, registrar)) {
-                                       ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
+                                       ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s' at line %d\n", v->value, cxt, v->lineno);
                                }
                        } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
                                char *stringp = realvalue;
@@ -1634,7 +1592,7 @@ process_extension:
                                appl = strsep(&stringp, "/");
                                data = S_OR(stringp, "");
                                if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar)) {
-                                       ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
+                                       ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s' at line %d\n", v->value, cxt, v->lineno);
                                }
                        } else {
                                ast_log(LOG_WARNING, "==!!== Unknown directive: %s at line %d -- IGNORING!!!\n", v->name, v->lineno);
@@ -1707,9 +1665,9 @@ static void pbx_load_users(void)
                        c = dahdicopy;
                        chan = strsep(&c, ",");
                        while (chan) {
-                               if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
+                               if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
                                        /* Range */
-                               } else if (sscanf(chan, "%d", &start)) {
+                               } else if (sscanf(chan, "%30d", &start)) {
                                        /* Just one */
                                        finish = start;
                                } else {
@@ -1791,13 +1749,13 @@ static int pbx_load_module(void)
 
 static int load_module(void)
 {
-       if (pbx_load_module())
-               return AST_MODULE_LOAD_DECLINE;
        if (static_config && !write_protect_config)
                ast_cli_register(&cli_dialplan_save);
        ast_cli_register_multiple(cli_pbx_config, ARRAY_LEN(cli_pbx_config));
 
+       if (pbx_load_module())
+               return AST_MODULE_LOAD_DECLINE;
+
        return AST_MODULE_LOAD_SUCCESS;
 }