*** pbx/pbx_config.c.orig 2012-05-31 09:43:07.000000000 +0200 --- pbx/pbx_config.c 2012-05-31 09:39:59.000000000 +0200 *************** *** 1285,1348 **** static int pbx_load_module(void); - static char *handle_cli_dialplan_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) - { - switch (cmd) { - case CLI_INIT: - e->command = "dialplan reload"; - e->usage = - "Usage: dialplan reload\n" - " Reload extensions.conf without reloading any other\n" - " modules. This command does not delete global variables\n" - " unless clearglobalvars is set to yes in extensions.conf\n"; - return NULL; - case CLI_GENERATE: - return NULL; - } - - if (a->argc != 2) - return CLI_SHOWUSAGE; - - if (clearglobalvars_config) - pbx_builtin_clear_globals(); - - pbx_load_module(); - ast_cli(a->fd, "Dialplan reloaded.\n"); - return CLI_SUCCESS; - } - - /*! - * CLI entries for commands provided by this module - */ - 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_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"), - AST_CLI_DEFINE(handle_cli_dialplan_remove_include, "Remove a specified include from context"), - AST_CLI_DEFINE(handle_cli_dialplan_reload, "Reload extensions and *only* extensions"), - AST_CLI_DEFINE(handle_cli_dialplan_save, "Save current dialplan into a file") - }; - - static struct ast_cli_entry cli_dialplan_save = - AST_CLI_DEFINE(handle_cli_dialplan_save, "Save dialplan"); - - /*! - * Standard module functions ... - */ - static int unload_module(void) - { - if (static_config && !write_protect_config) - ast_cli_unregister(&cli_dialplan_save); - if (overrideswitch_config) { - ast_free(overrideswitch_config); - } - ast_cli_unregister_multiple(cli_pbx_config, ARRAY_LEN(cli_pbx_config)); - ast_context_destroy(NULL, registrar); - return 0; - } - /*!\note Protect against misparsing based upon commas in the middle of fields * like character classes. We've taken steps to permit pretty much every other * printable character in a character class, so properly handling a comma at --- 1285,1290 ---- *************** *** 1373,1449 **** return res; } ! static int pbx_load_config(const char *config_file) { ! struct ast_config *cfg; ! char *end; ! char *label; #ifdef LOW_MEMORY ! char realvalue[256]; #else ! char realvalue[8192]; #endif ! int lastpri = -2; ! struct ast_context *con; ! struct ast_variable *v; ! const char *cxt; ! const char *aft; ! const char *newpm, *ovsw; ! struct ast_flags config_flags = { 0 }; ! char lastextension[256]; ! cfg = ast_config_load(config_file, config_flags); ! if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) ! return 0; ! ! /* Use existing config to populate the PBX table */ ! static_config = ast_true(ast_variable_retrieve(cfg, "general", "static")); ! write_protect_config = ast_true(ast_variable_retrieve(cfg, "general", "writeprotect")); ! if ((aft = ast_variable_retrieve(cfg, "general", "autofallthrough"))) ! autofallthrough_config = ast_true(aft); ! if ((newpm = ast_variable_retrieve(cfg, "general", "extenpatternmatchnew"))) ! extenpatternmatchnew_config = ast_true(newpm); ! clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars")); ! if ((ovsw = ast_variable_retrieve(cfg, "general", "overrideswitch"))) { ! if (overrideswitch_config) { ! ast_free(overrideswitch_config); ! } ! if (!ast_strlen_zero(ovsw)) { ! overrideswitch_config = ast_strdup(ovsw); ! } else { ! overrideswitch_config = NULL; ! } ! } ! ! ast_copy_string(userscontext, ast_variable_retrieve(cfg, "general", "userscontext") ?: "default", sizeof(userscontext)); ! ! for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) { ! pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); ! pbx_builtin_setvar_helper(NULL, v->name, realvalue); ! } ! for (cxt = ast_category_browse(cfg, NULL); ! cxt; ! cxt = ast_category_browse(cfg, cxt)) { ! /* All categories but "general" or "globals" are considered contexts */ ! if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) { ! continue; ! } ! if (!(con = ast_context_find_or_create(&local_contexts, local_table, cxt, registrar))) { ! continue; ! } ! /* Reset continuation items at the beginning of each context */ lastextension[0] = '\0'; ! lastpri = -2; ! for (v = ast_variable_browse(cfg, cxt); v; v = v->next) { char *tc = NULL; char realext[256] = ""; char *stringp, *ext; const char *vfile; ! /* get filename for error reporting from top level or an #include */ vfile = !*v->file ? config_file : v->file; ! if (!strncasecmp(v->name, "same", 4)) { if (ast_strlen_zero(lastextension)) { ast_log(LOG_ERROR, --- 1315,1345 ---- return res; } ! static void parse_dialplan(const char *config_file, struct ast_config *cfg, const char *cxt, struct ast_context *con) { ! char *end; ! char *label; ! struct ast_variable *v; ! char lastextension[256]; ! int lastpri = -2; #ifdef LOW_MEMORY ! char realvalue[256]; #else ! char realvalue[8192]; #endif ! /* Reset continuation items at the beginning of each context */ lastextension[0] = '\0'; ! for (v = ast_variable_browse(cfg, cxt); v; v = v->next) { char *tc = NULL; char realext[256] = ""; char *stringp, *ext; const char *vfile; ! /* get filename for error reporting from top level or an #include */ vfile = !*v->file ? config_file : v->file; ! if (!strncasecmp(v->name, "same", 4)) { if (ast_strlen_zero(lastextension)) { ast_log(LOG_ERROR, *************** *** 1638,1645 **** --- 1534,1755 ---- "==!!== Unknown directive: %s at line %d of %s -- IGNORING!!!\n", v->name, v->lineno, vfile); } + + } + } + + static char *reload_dialplan_helper(const char *context) + { + const char *config_file = "extensions.conf"; + struct ast_config *cfg; + struct ast_flags config_flags = { 0 }; + struct ast_context *con; + const char *cxt; + + if (!strcasecmp(context, "general") || !strcasecmp(context, "globals")) { + ast_log(LOG_ERROR, "Unable to reload context '%s'. Use dialplan reload instead.\n", context); + return CLI_FAILURE; + } + + cfg = ast_config_load(config_file, config_flags); + if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) + return CLI_FAILURE; + + for (cxt = ast_category_browse(cfg, NULL); cxt; cxt = ast_category_browse(cfg, cxt)) { + /* All categories but "general" or "globals" are considered contexts */ + if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) + continue; + if (context && strcasecmp(cxt, context)) + continue; /* skip this one, name doesn't match */ + + /* find and delete context */ + if((con = ast_context_find(cxt))) + ast_context_destroy(con, registrar); + + if (!(con = ast_context_find_or_create(NULL, NULL, cxt, registrar))) + break; /* unable to find or create context */ + + /* context found an recreated */ + + /* parse dialplan within context */ + parse_dialplan(config_file, cfg, cxt, con); + + /* stop after processing the requested context */ + break; + } + + ast_config_destroy(cfg); + return CLI_SUCCESS; + } + + /* + * 'dialplan reload' CLI command implementation functions ... + */ + static char *complete_reload_dialplan_context(struct ast_cli_args *a) + { + const char *word = a->word; + int pos = a->pos; + int state = a->n; + + struct ast_context *c = NULL; + char *ret = NULL; + int which = 0; + int wordlen; + + /* we are do completion of context on second position only */ + if (pos != 2) + return NULL; + + ast_rdlock_contexts(); + + wordlen = strlen(word); + + /* walk through all contexts and return the n-th match */ + while ( (c = ast_walk_contexts(c)) ) { + if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) { + ret = ast_strdup(ast_get_context_name(c)); + break; } } + + ast_unlock_contexts(); + + return ret; + } + + static char *handle_cli_dialplan_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) + { + char *context = NULL; + + switch (cmd) { + case CLI_INIT: + e->command = "dialplan reload"; + e->usage = + "Usage: dialplan reload [context]\n" + " Reload extensions.conf without reloading any other\n" + " modules. This command does not delete global variables\n" + " unless clearglobalvars is set to yes in extensions.conf\n"; + return NULL; + case CLI_GENERATE: + return complete_reload_dialplan_context(a); + } + + if (a->argc != 2 && a->argc != 3) + return CLI_SHOWUSAGE; + + if (a->argc == 3) { // get context + context = ast_strdupa(a->argv[2]); + if (ast_strlen_zero(context)) + context = NULL; + } + + if (context == NULL) { // if no context is given, reload complete dialplan + if (clearglobalvars_config) + pbx_builtin_clear_globals(); + + pbx_load_module(); + } else { // else reload only context + return reload_dialplan_helper(context); + } + ast_cli(a->fd, "Dialplan reloaded.\n"); + return CLI_SUCCESS; + } + + + /*! + * CLI entries for commands provided by this module + */ + 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_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"), + AST_CLI_DEFINE(handle_cli_dialplan_remove_include, "Remove a specified include from context"), + AST_CLI_DEFINE(handle_cli_dialplan_reload, "Reload extensions and *only* extensions"), + AST_CLI_DEFINE(handle_cli_dialplan_save, "Save current dialplan into a file") + }; + + static struct ast_cli_entry cli_dialplan_save = + AST_CLI_DEFINE(handle_cli_dialplan_save, "Save dialplan"); + + /*! + * Standard module functions ... + */ + static int unload_module(void) + { + if (static_config && !write_protect_config) + ast_cli_unregister(&cli_dialplan_save); + if (overrideswitch_config) { + ast_free(overrideswitch_config); + } + ast_cli_unregister_multiple(cli_pbx_config, ARRAY_LEN(cli_pbx_config)); + ast_context_destroy(NULL, registrar); + return 0; + } + + static int pbx_load_config(const char *config_file) + { + struct ast_config *cfg; + #ifdef LOW_MEMORY + char realvalue[256]; + #else + char realvalue[8192]; + #endif + int lastpri = -2; + struct ast_context *con; + struct ast_variable *v; + const char *cxt; + const char *aft; + const char *newpm, *ovsw; + struct ast_flags config_flags = { 0 }; + char lastextension[256]; + cfg = ast_config_load(config_file, config_flags); + if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) + return 0; + + /* Use existing config to populate the PBX table */ + static_config = ast_true(ast_variable_retrieve(cfg, "general", "static")); + write_protect_config = ast_true(ast_variable_retrieve(cfg, "general", "writeprotect")); + if ((aft = ast_variable_retrieve(cfg, "general", "autofallthrough"))) + autofallthrough_config = ast_true(aft); + if ((newpm = ast_variable_retrieve(cfg, "general", "extenpatternmatchnew"))) + extenpatternmatchnew_config = ast_true(newpm); + clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars")); + if ((ovsw = ast_variable_retrieve(cfg, "general", "overrideswitch"))) { + if (overrideswitch_config) { + ast_free(overrideswitch_config); + } + if (!ast_strlen_zero(ovsw)) { + overrideswitch_config = ast_strdup(ovsw); + } else { + overrideswitch_config = NULL; + } + } + + ast_copy_string(userscontext, ast_variable_retrieve(cfg, "general", "userscontext") ?: "default", sizeof(userscontext)); + + for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) { + pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); + pbx_builtin_setvar_helper(NULL, v->name, realvalue); + } + for (cxt = ast_category_browse(cfg, NULL); + cxt; + cxt = ast_category_browse(cfg, cxt)) { + /* All categories but "general" or "globals" are considered contexts */ + if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) { + continue; + } + if (!(con = ast_context_find_or_create(&local_contexts, local_table, cxt, registrar))) { + continue; + } + + /* Reset continuation items at the beginning of each context */ + lastextension[0] = '\0'; + lastpri = -2; + + parse_dialplan(config_file, cfg, cxt, con); + } ast_config_destroy(cfg); return 1; }