Index: pbx/pbx_config.c =================================================================== RCS file: /usr/cvsroot/asterisk/pbx/pbx_config.c,v retrieving revision 1.71 diff -u -r1.71 pbx_config.c --- pbx/pbx_config.c 24 Oct 2005 20:12:06 -0000 1.71 +++ pbx/pbx_config.c 14 Nov 2005 08:31:36 -0000 @@ -19,6 +19,7 @@ /*! \file * * \brief Populate and remember extensions from static config file + * * */ @@ -40,6 +41,14 @@ #include "asterisk/logger.h" #include "asterisk/cli.h" #include "asterisk/callerid.h" +#include "asterisk/manager.h" + +enum dialplanreloadreasons { + PBX_MODULE_LOAD, + PBX_CLI_RELOAD, + PBX_MODULE_RELOAD, + PBX_MANAGER_RELOAD, +}; #ifdef __AST_DEBUG_MALLOC static void FREE(void *ptr) @@ -120,14 +129,16 @@ * Implementation of functions provided by this module */ -/* +/*! * REMOVE INCLUDE command stuff */ static int handle_context_dont_include(int fd, int argc, char *argv[]) { - if (argc != 5) return RESULT_SHOWUSAGE; + if (argc != 5) + return RESULT_SHOWUSAGE; - if (strcmp(argv[3], "in")) return RESULT_SHOWUSAGE; + if (strcmp(argv[3], "in")) + return RESULT_SHOWUSAGE; if (!ast_context_remove_include(argv[4], argv[2], registrar)) { ast_cli(fd, "We are not including '%s' in '%s' now\n", @@ -361,7 +372,7 @@ return NULL; } -/* +/*! * REMOVE EXTENSION command stuff */ static int handle_context_remove_extension(int fd, int argc, char *argv[]) @@ -701,7 +712,7 @@ return NULL; } -/* +/*! * Include context ... */ static int handle_context_add_include(int fd, int argc, char *argv[]) @@ -913,8 +924,8 @@ return NULL; } -/* - * 'save dialplan' CLI command implementation functions ... +/*! + * \brief 'save dialplan' CLI command implementation functions ... */ static int handle_save_dialplan(int fd, int argc, char *argv[]) { @@ -1151,8 +1162,8 @@ return RESULT_SUCCESS; } -/* - * ADD EXTENSION command stuff +/*! + * \brief ADD EXTENSION command stuff */ static int handle_context_add_extension(int fd, int argc, char *argv[]) { @@ -1239,7 +1250,7 @@ return RESULT_SUCCESS; } -/* add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local */ +/*! add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local */ static char *complete_context_add_extension(char *line, char *word, int pos, int state) { @@ -1284,7 +1295,7 @@ return NULL; } -/* +/*! * IGNOREPAT CLI stuff */ static int handle_context_add_ignorepat(int fd, int argc, char *argv[]) @@ -1415,15 +1426,33 @@ return RESULT_SUCCESS; } -static int pbx_load_module(void); +static int pbx_load_module(enum dialplanreloadreasons reason); static int handle_reload_extensions(int fd, int argc, char *argv[]) { - if (argc!=2) return RESULT_SHOWUSAGE; - pbx_load_module(); + if (argc!=2) + return RESULT_SHOWUSAGE; + pbx_load_module(PBX_CLI_RELOAD); return RESULT_SUCCESS; } +static char mandescr_extreload[] = +"Description: Reload dial plan. ExtensionsReload event will\n" +"be sent after reload reporting number of loaded extensions,\n" +"contexts and switches.\n\n" +"Variables: (Names marked with * are required)\n" +" ActionID: ActionID to be returned in response\n"; + +/*! \brief Reload dial plan from manager API + \ingroup Group_AMI +*/ +static int action_extreload(struct mansession *s, struct message *m) +{ + pbx_load_module(PBX_MANAGER_RELOAD); + astman_send_ack(s, m, "Reload initiated"); + return 0; +} + static char *complete_context_remove_ignorepat(char *line, char *word, int pos, int state) { @@ -1542,7 +1571,7 @@ return NULL; } -/* +/*! * CLI entries for commands provided by this module */ static struct ast_cli_entry context_dont_include_cli = @@ -1583,7 +1612,7 @@ { { "extensions", "reload", NULL}, handle_reload_extensions, "Reload extensions and *only* extensions", reload_extensions_help }; -/* +/*! * Standard module functions ... */ int unload_module(void) @@ -1598,10 +1627,12 @@ ast_cli_unregister(&context_add_ignorepat_cli); ast_cli_unregister(&reload_extensions_cli); ast_context_destroy(NULL, registrar); + ast_manager_unregister("ExtReload"); return 0; } -static int pbx_load_module(void) +/*! \brief Load PBX with updated dialplan */ +static int pbx_load_module(enum dialplanreloadreasons reason) { struct ast_config *cfg; struct ast_variable *v; @@ -1611,6 +1642,8 @@ char *label; char realvalue[256]; int lastpri = -2; + char *textreason = ""; + int context_count = 0, extension_count = 0, switch_count = 0; cfg = ast_config_load(config); if (cfg) { @@ -1635,142 +1668,148 @@ } cxt = ast_category_browse(cfg, NULL); while(cxt) { + context_count ++; /* All categories but "general" or "globals" are considered contexts */ if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) { cxt = ast_category_browse(cfg, cxt); continue; } - if ((con=ast_context_create(&local_contexts,cxt, registrar))) { - v = ast_variable_browse(cfg, cxt); - while(v) { - if (!strcasecmp(v->name, "exten")) { - char *stringp=NULL; - int ipri = -2; - char realext[256]=""; - char *plus, *firstp, *firstc; - tc = strdup(v->value); - if(tc!=NULL){ - stringp=tc; - ext = strsep(&stringp, ","); - if (!ext) - ext=""; - pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1); - cidmatch = strchr(realext, '/'); - if (cidmatch) { - *cidmatch = '\0'; - cidmatch++; - ast_shrink_phone_number(cidmatch); - } - pri = strsep(&stringp, ","); - if (!pri) - pri=""; - label = strchr(pri, '('); - if (label) { - *label = '\0'; - label++; - end = strchr(label, ')'); - if (end) - *end = '\0'; - else - ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno); - } - plus = strchr(pri, '+'); - if (plus) { - *plus = '\0'; - plus++; - } - if (!strcmp(pri,"hint")) - ipri=PRIORITY_HINT; - else if (!strcmp(pri, "next") || !strcmp(pri, "n")) { - if (lastpri > -2) - ipri = lastpri + 1; - else - ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n"); - } 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"); - } else { - if (sscanf(pri, "%d", &ipri) != 1) { - if ((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; - } + if (!(con=ast_context_create(&local_contexts,cxt, registrar))) { + ast_log(LOG_ERROR, "Failed to create context %s\n", cxt); + continue; + } + v = ast_variable_browse(cfg, cxt); + while(v) { + if (!strcasecmp(v->name, "exten")) { + char *stringp=NULL; + int ipri = -2; + char realext[256]=""; + char *plus, *firstp, *firstc; + tc = strdup(v->value); + if(tc!=NULL){ + stringp=tc; + ext = strsep(&stringp, ","); + if (!ext) + ext=""; + pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1); + cidmatch = strchr(realext, '/'); + if (cidmatch) { + *cidmatch = '\0'; + cidmatch++; + ast_shrink_phone_number(cidmatch); + } + pri = strsep(&stringp, ","); + if (!pri) + pri=""; + label = strchr(pri, '('); + if (label) { + *label = '\0'; + label++; + end = strchr(label, ')'); + if (end) + *end = '\0'; + else + ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno); + } + plus = strchr(pri, '+'); + if (plus) { + *plus = '\0'; + plus++; + } + if (!strcmp(pri,"hint")) + ipri=PRIORITY_HINT; + else if (!strcmp(pri, "next") || !strcmp(pri, "n")) { + if (lastpri > -2) + ipri = lastpri + 1; + else + ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n"); + } 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"); + } else { + if (sscanf(pri, "%d", &ipri) != 1) { + if ((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; } } - appl = stringp; - if (!appl) - appl=""; - /* Find the first occurrence of either '(' or ',' */ - firstc = strchr(appl, ','); - firstp = strchr(appl, '('); - if (firstc && ((!firstp) || (firstc < firstp))) { - /* comma found, no parenthesis */ - /* or both found, but comma found first */ - appl = strsep(&stringp, ","); - data = stringp; - } else if ((!firstc) && (!firstp)) { - /* Neither found */ - data = ""; + } + appl = stringp; + if (!appl) + appl=""; + /* Find the first occurrence of either '(' or ',' */ + firstc = strchr(appl, ','); + firstp = strchr(appl, '('); + if (firstc && ((!firstp) || (firstc < firstp))) { + /* comma found, no parenthesis */ + /* or both found, but comma found first */ + appl = strsep(&stringp, ","); + data = stringp; + } else if ((!firstc) && (!firstp)) { + /* Neither found */ + data = ""; + } else { + /* Final remaining case is parenthesis found first */ + appl = strsep(&stringp, "("); + data = stringp; + end = strrchr(data, ')'); + if ((end = strrchr(data, ')'))) { + *end = '\0'; } else { - /* Final remaining case is parenthesis found first */ - appl = strsep(&stringp, "("); - data = stringp; - end = strrchr(data, ')'); - if ((end = strrchr(data, ')'))) { - *end = '\0'; - } else { - ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data); - } - ast_process_quotes_and_slashes(data, ',', '|'); + ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data); } + ast_process_quotes_and_slashes(data, ',', '|'); + } - if (!data) - data=""; - while(*appl && (*appl < 33)) appl++; - if (ipri) { - if (plus) - ipri += atoi(plus); - lastpri = ipri; - if(!option_dontwarn) { - if (!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_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), FREE, registrar)) { - ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno); - } + if (!data) + data=""; + while(*appl && (*appl < 33)) appl++; + if (ipri) { + if (plus) + ipri += atoi(plus); + lastpri = ipri; + if(!option_dontwarn) { + if (!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); } - free(tc); - } else fprintf(stderr,"Error strdup returned NULL in %s\n",__PRETTY_FUNCTION__); - } else if(!strcasecmp(v->name, "include")) { - memset(realvalue, 0, sizeof(realvalue)); - pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); - if (ast_context_add_include2(con, realvalue, registrar)) - ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt); - } else if(!strcasecmp(v->name, "ignorepat")) { - memset(realvalue, 0, sizeof(realvalue)); + if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), FREE, registrar)) { + ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno); + } else + extension_count++; + } + free(tc); + } else fprintf(stderr,"Error strdup returned NULL in %s\n",__PRETTY_FUNCTION__); + } else if(!strcasecmp(v->name, "include")) { + memset(realvalue, 0, sizeof(realvalue)); + pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); + if (ast_context_add_include2(con, realvalue, registrar)) + ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt); + } else if(!strcasecmp(v->name, "ignorepat")) { + memset(realvalue, 0, sizeof(realvalue)); + 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); + } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) { + char *stringp=NULL; + memset(realvalue, 0, sizeof(realvalue)); + if (!strcasecmp(v->name, "switch")) 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); - } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) { - char *stringp=NULL; - memset(realvalue, 0, sizeof(realvalue)); - if (!strcasecmp(v->name, "switch")) - pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); - else - strncpy(realvalue, v->value, sizeof(realvalue) - 1); - tc = realvalue; - stringp=tc; - appl = strsep(&stringp, "/"); - data = strsep(&stringp, ""); - if (!data) - data = ""; - 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); - } - v = v->next; + else + strncpy(realvalue, v->value, sizeof(realvalue) - 1); + tc = realvalue; + stringp=tc; + appl = strsep(&stringp, "/"); + data = strsep(&stringp, ""); + if (!data) + data = ""; + 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); + else + switch_count++; } + v = v->next; } cxt = ast_category_browse(cfg, cxt); } @@ -1782,13 +1821,27 @@ ast_context_verify_includes(con); pbx_set_autofallthrough(autofallthrough_config); + + switch (reason) { + case PBX_MODULE_LOAD: textreason = "PBX_LOAD_MODULE - PBX startup (load module)"; + break; + case PBX_CLI_RELOAD: textreason = "PBX_CLI_RELOAD - CLI reload command"; + break; + case PBX_MODULE_RELOAD: textreason = "PBX_MODULE_RELOAD - Module reload"; + break; + case PBX_MANAGER_RELOAD: textreason = "PBX_MANAGER_RELOAD - Manager forced dialplan reload"; + break; + }; + manager_event(EVENT_FLAG_SYSTEM, "ExtensionsReload", "Module: Extensions\r\nReloadReason: %s\r\nContext_Count: %d\r\nExtension_Count: %d\r\nSwitch_Count: %d\r\nRegistrar: %s\r\n", textreason, context_count, extension_count, switch_count, registrar); + ast_log(LOG_EVENT, "PBX Dial plan loaded. Contexts: %d Extensions: %d Switches: %d Reason: %s\n", context_count, extension_count, switch_count, textreason); return 0; } int load_module(void) { - if (pbx_load_module()) return -1; + if (pbx_load_module(PBX_MODULE_LOAD)) + return -1; ast_cli_register(&context_remove_extension_cli); ast_cli_register(&context_dont_include_cli); @@ -1799,6 +1852,7 @@ ast_cli_register(&context_add_ignorepat_cli); ast_cli_register(&context_remove_ignorepat_cli); ast_cli_register(&reload_extensions_cli); + ast_manager_register2("ExtReload", EVENT_FLAG_SYSTEM, action_extreload, "Reload Asterisk dial plan", mandescr_extreload); return 0; } @@ -1808,7 +1862,7 @@ ast_context_destroy(NULL, registrar); if (clearglobalvars_config) pbx_builtin_clear_globals(); - pbx_load_module(); + pbx_load_module(PBX_MODULE_RELOAD); return 0; }