96 static const char config[] =
"extensions.conf";
97 static const char registrar[] =
"pbx_config";
100 static int static_config = 0;
101 static int write_protect_config = 1;
102 static int autofallthrough_config = 1;
103 static int clearglobalvars_config = 0;
104 static int extenpatternmatchnew_config = 0;
105 static char *overrideswitch_config = NULL;
109 AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
111 AST_MUTEX_DEFINE_STATIC(reload_lock);
118 static char *complete_dialplan_remove_include(
struct ast_cli_args *);
119 static char *complete_dialplan_add_include(
struct ast_cli_args *);
120 static char *complete_dialplan_remove_ignorepat(
struct ast_cli_args *);
121 static char *complete_dialplan_add_ignorepat(
struct ast_cli_args *);
122 static char *complete_dialplan_remove_extension(
struct ast_cli_args *);
124 static char *complete_dialplan_remove_context(
struct ast_cli_args *);
138 e->
command =
"dialplan remove context";
140 "Usage: dialplan remove context <context>\n"
141 " Removes all extensions from a specified context.\n";
144 return complete_dialplan_remove_context(a);
148 return CLI_SHOWUSAGE;
152 ast_cli(a->fd,
"There is no such context as '%s'\n", a->argv[3]);
155 ast_cli(a->fd,
"Removed context '%s'\n", a->argv[3]);
166 e->
command =
"dialplan remove include";
168 "Usage: dialplan remove include <context> from <context>\n"
169 " Remove an included context from another context.\n";
172 return complete_dialplan_remove_include(a);
175 if (a->argc != 6 || strcmp(a->argv[4],
"from"))
176 return CLI_SHOWUSAGE;
179 ast_cli(a->fd,
"We are not including '%s' into '%s' now\n",
180 a->argv[3], a->argv[5]);
184 ast_cli(a->fd,
"Failed to remove '%s' include from '%s' context\n",
185 a->argv[3], a->argv[5]);
200 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
201 const struct ast_include *i = ast_context_includes_get(c, idx);
203 if (!strcmp(name, ast_get_include_name(i))) {
224 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
225 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
227 if (!strcmp(name, ast_get_ignorepat_name(ip))) {
241 for (;n && *p; p++) {
242 if (isblank(*p) && !in_blank) {
245 }
else if ( in_blank) {
255 return (len == 0 || !strncmp(s, word, len));
261 static int split_ec(
const char *src,
char **ext,
char **
const ctx,
char **
const cid)
275 if (strchr(c,
'@')) {
280 if (cid && (i = strchr(e,
'/'))) {
291 static char *complete_dialplan_remove_include(
struct ast_cli_args *a)
295 int len = strlen(a->word);
300 ast_log(LOG_ERROR,
"Failed to lock context list\n");
304 while (!res && (c = ast_walk_contexts(c))) {
310 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
311 const struct ast_include *i = ast_context_includes_get(c, idx);
312 const char *i_name = ast_get_include_name(i);
314 int already_served = 0;
324 while ( (nc = ast_walk_contexts(nc)) && nc != c && !already_served)
327 if (!already_served && ++which > a->n) {
337 }
else if (a->pos == 4) {
342 char *context, *dupline;
349 ast_log(LOG_ERROR,
"Out of free memory\n");
352 strsep(&dupline,
" ");
355 ast_log(LOG_ERROR,
"Failed to lock contexts list\n");
361 while (!res && (c = ast_walk_contexts(c)))
366 ast_log(LOG_WARNING,
"%s not included anywhere\n", context);
369 }
else if (a->pos == 5) {
373 char *context, *dupline, *from;
377 ast_log(LOG_ERROR,
"Out of free memory\n");
381 strsep(&dupline,
" ");
384 from = strsep(&dupline,
" ");
385 if (!from || strcmp(from,
"from")) {
391 ast_log(LOG_ERROR,
"Failed to lock context list\n");
398 while ( !res && (c = ast_walk_contexts(c))) {
399 const char *c_name = ast_get_context_name(c);
403 if (
lookup_ci(c, context) && ++which > a->n)
419 int removing_priority = 0;
420 char *exten, *context, *cid;
421 char *ret = CLI_FAILURE;
425 e->
command =
"dialplan remove extension";
427 "Usage: dialplan remove extension exten[/cid]@context [priority]\n"
428 " Remove an extension from a given context. If a priority\n"
429 " is given, only that specific priority from the given extension\n"
430 " will be removed.\n";
433 return complete_dialplan_remove_extension(a);
436 if (a->argc != 5 && a->argc != 4)
437 return CLI_SHOWUSAGE;
443 const char *c = a->argv[4];
449 if (!strcmp(
"hint", c))
452 while (*c && isdigit(*c))
455 ast_cli(a->fd,
"Invalid priority '%s'\n", a->argv[4]);
458 removing_priority = atoi(a->argv[4]);
461 if (removing_priority == 0) {
462 ast_cli(a->fd,
"If you want to remove whole extension, please " \
463 "omit priority argument\n");
472 if (
split_ec(a->argv[3], &exten, &context, &cid))
474 if ((!strlen(exten)) || (!(strlen(context)))) {
475 ast_cli(a->fd,
"Missing extension or context name in third argument '%s'\n",
481 if (!ast_context_remove_extension_callerid(context, exten, removing_priority,
483 cid ? cid : (removing_priority ?
"" : NULL), cid ? 1 : 0,
registrar)) {
484 if (!removing_priority)
485 ast_cli(a->fd,
"Whole extension %s@%s removed\n",
488 ast_cli(a->fd,
"Extension %s@%s with priority %d removed\n",
489 exten, context, removing_priority);
494 ast_cli(a->fd,
"Failed to remove extension %s/%s@%s\n", exten, cid, context);
496 ast_cli(a->fd,
"Failed to remove extension %s@%s\n", exten, context);
504 static int manager_dialplan_extension_remove(
struct mansession *s,
const struct message *m)
512 char *cidmatch = NULL;
514 if (ast_strlen_zero(context) || ast_strlen_zero(extension)) {
516 "for DialplanExtensionRemove");
522 if (strchr(exten,
'/')) {
524 strsep(&cidmatch,
"/");
527 if (ast_strlen_zero(priority)) {
529 }
else if (!strcmp(
"hint", priority)) {
531 }
else if ((sscanf(priority,
"%30d", &ipriority) != 1) || ipriority <= 0) {
536 if (!ast_context_remove_extension_callerid(context, exten, ipriority,
538 !ast_strlen_zero(cidmatch) ? cidmatch : (ipriority ?
"" : NULL),
539 !ast_strlen_zero(cidmatch) ? 1 : 0,
registrar)) {
541 astman_send_ack(s, m,
"Removed the requested priority from the extension");
552 static char *complete_dialplan_remove_extension(
struct ast_cli_args *a)
559 char *context = NULL, *exten = NULL, *cid = NULL;
564 lc =
split_ec(a->word, &exten, &context, &cid);
569 lc = strlen(context);
570 lcid = cid ? strlen(cid) : -1;
573 ast_log(LOG_ERROR,
"Failed to lock context list\n");
578 while ( (c = ast_walk_contexts(c)) ) {
583 while ( (e = ast_walk_context_extensions(c, e)) ) {
584 if ( !strchr(a->word,
'/') ||
585 (!strchr(a->word,
'@') &&
partial_match(ast_get_extension_cidmatch(e), cid, lcid)) ||
586 (strchr(a->word,
'@') && !strcmp(ast_get_extension_cidmatch(e), cid))) {
587 if ( ((strchr(a->word,
'/') || strchr(a->word,
'@')) && !strcmp(ast_get_extension_name(e), exten)) ||
588 (!strchr(a->word,
'/') && !strchr(a->word,
'@') &&
partial_match(ast_get_extension_name(e), exten, le))) {
589 if (++which > a->n) {
591 if (ast_get_extension_matchcid(e) && (!strchr(a->word,
'@') || strchr(a->word,
'/'))) {
592 if (
ast_asprintf(&ret,
"%s/%s@%s", ast_get_extension_name(e), ast_get_extension_cidmatch(e), ast_get_context_name(c)) < 0) {
596 }
else if (!ast_get_extension_matchcid(e) && !strchr(a->word,
'/')) {
597 if (
ast_asprintf(&ret,
"%s@%s", ast_get_extension_name(e), ast_get_context_name(c)) < 0) {
613 }
else if (a->pos == 4) {
614 char *exten = NULL, *context, *cid, *p;
618 int i =
split_ec(s, &exten, &context, &cid);
622 if ( (p = strchr(exten,
' ')) )
624 if ( (p = strchr(context,
' ')) )
627 lc = strlen(context);
628 len = strlen(a->word);
629 if (le == 0 || lc == 0)
633 ast_log(LOG_ERROR,
"Failed to lock context list\n");
639 while ( (c = ast_walk_contexts(c)) ) {
642 if (strcmp(ast_get_context_name(c), context) != 0)
646 while ( (e = ast_walk_context_extensions(c, e)) ) {
650 if (cid && strcmp(ast_get_extension_cidmatch(e), cid) != 0) {
653 if (strcmp(ast_get_extension_name(e), exten) != 0)
657 while ( !ret && (priority = ast_walk_extension_priorities(e, priority)) ) {
658 snprintf(buffer,
sizeof(buffer),
"%d", ast_get_extension_priority(priority));
678 const char *into_context;
682 e->
command =
"dialplan add include";
684 "Usage: dialplan add include <context> into <context>\n"
685 " Include a context in another context.\n";
688 return complete_dialplan_add_include(a);
692 return CLI_SHOWUSAGE;
695 if (strcmp(a->argv[4],
"into"))
696 return CLI_SHOWUSAGE;
698 into_context = a->argv[5];
701 ast_cli(a->fd,
"Context '%s' did not exist prior to add include - the context will be created.\n", into_context);
705 ast_cli(a->fd,
"ast_context_find_or_create() failed\n");
706 ast_cli(a->fd,
"Failed to include '%s' in '%s' context\n",a->argv[3], a->argv[5]);
713 ast_cli(a->fd,
"Out of memory for context addition\n");
717 ast_cli(a->fd,
"Failed to lock context(s) list, please try again later\n");
721 ast_cli(a->fd,
"Context '%s' already included in '%s' context\n",
722 a->argv[3], a->argv[5]);
727 ast_cli(a->fd,
"There is no existence of context '%s'\n",
728 errno == ENOENT ? a->argv[5] : a->argv[3]);
732 ast_cli(a->fd,
"Failed to include '%s' in '%s' context\n",
733 a->argv[3], a->argv[5]);
740 ast_cli(a->fd,
"Context '%s' included in '%s' context\n",
741 a->argv[3], a->argv[5]);
746 static char *complete_dialplan_add_include(
struct ast_cli_args *a)
751 int len = strlen(a->word);
755 ast_log(LOG_ERROR,
"Failed to lock context list\n");
758 for (c = NULL; !ret && (c = ast_walk_contexts(c)); )
759 if (
partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n)
763 }
else if (a->pos == 4) {
765 return (a->n == 0) ?
ast_strdup(
"into") : NULL;
766 }
else if (a->pos == 5) {
767 char *context, *dupline, *into;
772 ast_log(LOG_ERROR,
"Out of free memory\n");
776 strsep(&dupline,
" ");
777 into = strsep(&dupline,
" ");
779 if (!strlen(context) || strcmp(into,
"into")) {
780 ast_log(LOG_ERROR,
"bad context %s or missing into %s\n",
786 ast_log(LOG_ERROR,
"Failed to lock context list\n");
790 for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
791 if (!strcmp(context, ast_get_context_name(c)))
813 char filename[256], overrideswitch[256] =
"";
820 const char *base, *slash;
826 "Usage: dialplan save [/path/to/extension/file]\n"
827 " Save dialplan created by pbx_config module.\n"
829 "Example: dialplan save (/etc/asterisk/extensions.conf)\n"
830 " dialplan save /home/markster (/home/markster/extensions.conf)\n";
836 if (! (static_config && !write_protect_config)) {
838 "I can't save dialplan now, see '%s' example file.\n",
843 if (a->argc != 2 && a->argc != 3)
844 return CLI_SHOWUSAGE;
846 if (ast_mutex_lock(&save_dialplan_lock)) {
848 "Failed to lock dialplan saving (another process saving?)\n");
856 if (!strstr(a->argv[2],
".conf")) {
858 slash = (*(a->argv[2] + strlen(a->argv[2]) -1) ==
'/') ?
"/" :
"";
864 base = ast_config_AST_CONFIG_DIR;
867 snprintf(filename,
sizeof(filename),
"%s%s%s", base, slash, config);
871 ast_cli(a->fd,
"Failed to load extensions.conf\n");
872 ast_mutex_unlock(&save_dialplan_lock);
878 ast_cli(a->fd,
"Failed to lock contexts list\n");
879 ast_mutex_unlock(&save_dialplan_lock);
885 if (!(output = fopen(filename,
"wt"))) {
886 ast_cli(a->fd,
"Failed to create file '%s'\n",
889 ast_mutex_unlock(&save_dialplan_lock);
895 if (overrideswitch_config) {
896 snprintf(overrideswitch,
sizeof(overrideswitch),
"overrideswitch=%s\n", overrideswitch_config);
898 fprintf(output,
"[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\n%sextenpatternmatchnew=%s\n\n",
899 static_config ?
"yes" :
"no",
900 write_protect_config ?
"yes" :
"no",
901 autofallthrough_config ?
"yes" :
"no",
902 clearglobalvars_config ?
"yes" :
"no",
903 overrideswitch_config ? overrideswitch :
"",
904 extenpatternmatchnew_config ?
"yes" :
"no");
906 if ((v = ast_variable_browse(cfg,
"globals"))) {
907 fprintf(output,
"[globals]\n");
909 int escaped_len = 2 * strlen(v->
value) + 1;
910 char escaped[escaped_len];
913 fprintf(output,
"%s => %s\n", v->
name, escaped);
916 fprintf(output,
"\n");
921 #define PUT_CTX_HDR do { \
922 if (!context_header_written) { \
923 fprintf(output, "[%s]\n", ast_get_context_name(c)); \
924 context_header_written = 1; \
929 for (c = NULL; (c = ast_walk_contexts(c)); ) {
930 int context_header_written = 0;
931 struct ast_exten *ext, *last_written_e = NULL;
941 if (!strcmp(ast_get_context_registrar(c),
registrar)) {
942 fprintf(output,
"[%s]\n", ast_get_context_name(c));
943 context_header_written = 1;
947 for (ext = NULL; (ext = ast_walk_context_extensions(c, ext)); ) {
951 while ( (p = ast_walk_extension_priorities(ext, p)) ) {
952 if (strcmp(ast_get_extension_registrar(p),
registrar) != 0)
956 if (last_written_e != NULL &&
957 strcmp(ast_get_extension_name(last_written_e),
958 ast_get_extension_name(p)))
959 fprintf(output,
"\n");
965 fprintf(output,
"exten => %s,hint,%s\n",
966 ast_get_extension_name(p),
967 ast_get_extension_app(p));
969 const char *sep, *cid;
970 const char *el = ast_get_extension_label(p);
971 char label[128] =
"";
972 char *appdata = ast_get_extension_app_data(p);
974 int escaped_len = (!ast_strlen_zero(appdata)) ? 2 * strlen(appdata) + 1 : 1;
975 char escaped[escaped_len];
977 if (ast_get_extension_matchcid(p)) {
979 cid = ast_get_extension_cidmatch(p);
984 if (el && (snprintf(label,
sizeof(label),
"(%s)", el) != (strlen(el) + 2))) {
988 if (!ast_strlen_zero(appdata)) {
994 fprintf(output,
"exten => %s%s%s,%d%s,%s(%s)\n",
995 ast_get_extension_name(p), (ast_strlen_zero(sep) ?
"" : sep), (ast_strlen_zero(cid) ?
"" : cid),
996 ast_get_extension_priority(p), label,
997 ast_get_extension_app(p), escaped);
1004 fprintf(output,
"\n");
1007 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
1008 const struct ast_include *i = ast_context_includes_get(c, idx);
1010 if (strcmp(ast_get_include_registrar(i),
registrar) != 0)
1013 fprintf(output,
"include => %s\n", ast_get_include_name(i));
1015 if (ast_context_includes_count(c)) {
1016 fprintf(output,
"\n");
1020 for (idx = 0; idx < ast_context_switches_count(c); idx++) {
1021 const struct ast_sw *sw = ast_context_switches_get(c, idx);
1023 if (strcmp(ast_get_switch_registrar(sw),
registrar) != 0)
1026 fprintf(output,
"switch => %s/%s\n",
1027 ast_get_switch_name(sw), ast_get_switch_data(sw));
1030 if (ast_context_switches_count(c)) {
1031 fprintf(output,
"\n");
1035 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
1036 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
1038 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) != 0)
1041 fprintf(output,
"ignorepat => %s\n",
1042 ast_get_ignorepat_name(ip));
1049 ast_mutex_unlock(&save_dialplan_lock);
1053 ast_cli(a->fd,
"Saved dialplan is incomplete\n");
1057 ast_cli(a->fd,
"Dialplan successfully saved into '%s'\n",
1068 char *exten, *prior;
1072 const char *into_context;
1076 e->
command =
"dialplan add extension";
1078 "Usage: dialplan add extension <exten>,<priority>,<app> into <context> [replace]\n"
1080 " app can be either:\n"
1082 " app-name(app-data)\n"
1083 " app-name,<app-data>\n"
1085 " This command will add the new extension into <context>. If\n"
1086 " an extension with the same priority already exists and the\n"
1087 " 'replace' option is given we will replace the extension.\n"
1089 "Example: dialplan add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n"
1090 " Now, you can dial 6123 and talk to Markster :)\n";
1097 if (a->argc != 6 && a->argc != 7)
1098 return CLI_SHOWUSAGE;
1099 if (strcmp(a->argv[4],
"into"))
1100 return CLI_SHOWUSAGE;
1102 if (strcmp(a->argv[6],
"replace"))
1103 return CLI_SHOWUSAGE;
1106 exten = strsep(&whole_exten,
",");
1107 if (strchr(exten,
'/')) {
1109 strsep(&cidmatch,
"/");
1113 prior = strsep(&whole_exten,
",");
1115 if (!strcmp(prior,
"hint")) {
1118 if (sscanf(prior,
"%30d", &iprior) != 1) {
1119 ast_cli(a->fd,
"'%s' is not a valid priority\n", prior);
1126 if ((start = strchr(app,
'(')) && (end = strrchr(app,
')'))) {
1127 *start = *end =
'\0';
1128 app_data = start + 1;
1130 app_data = strchr(app,
',');
1139 if (!exten || !prior || !app) {
1140 return CLI_SHOWUSAGE;
1146 into_context = a->argv[5];
1149 ast_cli(a->fd,
"Context '%s' did not exist prior to add extension - the context will be created.\n", into_context);
1153 ast_cli(a->fd,
"Failed to add '%s,%s,%s(%s)' extension into '%s' context\n",
1154 exten, prior, app, app_data, into_context);
1158 if (
ast_add_extension(into_context, a->argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
1162 ast_cli(a->fd,
"Out of free memory\n");
1166 ast_cli(a->fd,
"Failed to lock context(s) list, please try again later\n");
1170 ast_cli(a->fd,
"No existence of '%s' context\n", into_context);
1174 ast_cli(a->fd,
"Extension %s@%s with priority %s already exists\n",
1175 exten, into_context, prior);
1179 ast_cli(a->fd,
"Failed to add '%s,%s,%s(%s)' extension into '%s' context\n",
1180 exten, prior, app, app_data, into_context);
1187 ast_cli(a->fd,
"Extension %s@%s (%s) replace by '%s,%s,%s(%s)'\n",
1188 exten, into_context, prior, exten, prior, app, app_data);
1190 ast_cli(a->fd,
"Extension '%s,%s,%s(%s)' added into '%s' context\n",
1191 exten, prior, app, app_data, into_context);
1197 static int manager_dialplan_extension_add(
struct mansession *s,
const struct message *m)
1207 char *cidmatch = NULL;
1210 if (ast_strlen_zero(context) || ast_strlen_zero(extension) ||
1211 ast_strlen_zero(priority) || ast_strlen_zero(application)) {
1213 "Application must be defined for DialplanExtensionAdd.");
1218 if (!strcmp(priority,
"hint")) {
1220 }
else if ((sscanf(priority,
"%30d", &ipriority) != 1) || (ipriority < 0)) {
1228 if (strchr(exten,
'/')) {
1230 strsep(&cidmatch,
"/");
1241 "for the extension.");
1263 astman_send_error(s, m,
"That extension and priority already exist at that context");
1279 static char *complete_dialplan_remove_context(
struct ast_cli_args *a)
1282 int len = strlen(a->word);
1293 ast_log(LOG_WARNING,
"Failed to lock contexts list\n");
1298 while ( !res && (c = ast_walk_contexts(c)) ) {
1299 if (
partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n) {
1313 return (a->n == 0) ?
ast_strdup(
"into") : NULL;
1314 }
else if (a->pos == 5) {
1316 int len = strlen(a->word);
1321 ast_log(LOG_WARNING,
"Failed to lock contexts list\n");
1326 while ( !res && (c = ast_walk_contexts(c)) )
1327 if (
partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n)
1331 }
else if (a->pos == 6) {
1332 return a->n == 0 ?
ast_strdup(
"replace") : NULL;
1344 e->
command =
"dialplan add ignorepat";
1346 "Usage: dialplan add ignorepat <pattern> into <context>\n"
1347 " This command adds a new ignore pattern into context <context>\n"
1349 "Example: dialplan add ignorepat _3XX into local\n";
1352 return complete_dialplan_add_ignorepat(a);
1356 return CLI_SHOWUSAGE;
1358 if (strcmp(a->argv[4],
"into"))
1359 return CLI_SHOWUSAGE;
1364 ast_cli(a->fd,
"Out of free memory\n");
1368 ast_cli(a->fd,
"There is no existence of '%s' context\n", a->argv[5]);
1372 ast_cli(a->fd,
"Ignore pattern '%s' already included in '%s' context\n",
1373 a->argv[3], a->argv[5]);
1377 ast_cli(a->fd,
"Failed to lock context(s) list, please, try again later\n");
1381 ast_cli(a->fd,
"Failed to add ignore pattern '%s' into '%s' context\n",
1382 a->argv[3], a->argv[5]);
1388 ast_cli(a->fd,
"Ignore pattern '%s' added into '%s' context\n",
1389 a->argv[3], a->argv[5]);
1394 static char *complete_dialplan_add_ignorepat(
struct ast_cli_args *a)
1397 return a->n == 0 ?
ast_strdup(
"into") : NULL;
1398 else if (a->pos == 5) {
1401 char *dupline, *ignorepat = NULL;
1404 int len = strlen(a->word);
1412 ast_log(LOG_ERROR,
"Malloc failure\n");
1415 ignorepat = strsep(&dupline,
" ");
1418 ast_log(LOG_ERROR,
"Failed to lock contexts list\n");
1422 for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
1429 if (!found && ++which > a->n)
1433 ast_free(ignorepat);
1445 e->
command =
"dialplan remove ignorepat";
1447 "Usage: dialplan remove ignorepat <pattern> from <context>\n"
1448 " This command removes an ignore pattern from context <context>\n"
1450 "Example: dialplan remove ignorepat _3XX from local\n";
1453 return complete_dialplan_remove_ignorepat(a);
1457 return CLI_SHOWUSAGE;
1459 if (strcmp(a->argv[4],
"from"))
1460 return CLI_SHOWUSAGE;
1465 ast_cli(a->fd,
"Failed to lock context(s) list, please try again later\n");
1469 ast_cli(a->fd,
"There is no existence of '%s' context\n", a->argv[5]);
1473 ast_cli(a->fd,
"There is no existence of '%s' ignore pattern in '%s' context\n",
1474 a->argv[3], a->argv[5]);
1478 ast_cli(a->fd,
"Failed to remove ignore pattern '%s' from '%s' context\n",
1479 a->argv[3], a->argv[5]);
1485 ast_cli(a->fd,
"Ignore pattern '%s' removed from '%s' context\n",
1486 a->argv[3], a->argv[5]);
1490 static char *complete_dialplan_remove_ignorepat(
struct ast_cli_args *a)
1497 int len = strlen(a->word);
1499 ast_log(LOG_WARNING,
"Failed to lock contexts list\n");
1503 for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
1508 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
1509 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
1511 if (
partial_match(ast_get_ignorepat_name(ip), a->word, len) && ++which > a->n) {
1515 while ( (cw = ast_walk_contexts(cw)) && cw != c && !found) {
1517 found =
lookup_c_ip(cw, ast_get_ignorepat_name(ip));
1520 ret =
ast_strdup(ast_get_ignorepat_name(ip));
1527 }
else if (a->pos == 4) {
1528 return a->n == 0 ?
ast_strdup(
"from") : NULL;
1529 }
else if (a->pos == 5) {
1530 char *dupline, *duplinet, *ignorepat;
1531 int len = strlen(a->word);
1535 ast_log(LOG_WARNING,
"Out of free memory\n");
1540 strsep(&duplinet,
" ");
1541 strsep(&duplinet,
" ");
1542 ignorepat = strsep(&duplinet,
" ");
1550 ast_log(LOG_WARNING,
"Failed to lock contexts list\n");
1555 for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
1560 if (!
partial_match(ast_get_context_name(c), a->word, len)) {
1576 static int pbx_load_module(
void);
1582 e->
command =
"dialplan reload";
1584 "Usage: dialplan reload\n"
1585 " Reload extensions.conf without reloading any other\n"
1586 " modules. This command does not delete global variables\n"
1587 " unless clearglobalvars is set to yes in extensions.conf\n";
1594 return CLI_SHOWUSAGE;
1596 if (clearglobalvars_config)
1597 pbx_builtin_clear_globals();
1600 ast_cli(a->fd,
"Dialplan reloaded.\n");
1612 AST_CLI_DEFINE(handle_cli_dialplan_remove_ignorepat,
"Remove ignore pattern from context"),
1615 AST_CLI_DEFINE(handle_cli_dialplan_reload,
"Reload extensions and *only* extensions")
1621 #define AMI_EXTENSION_ADD "DialplanExtensionAdd"
1622 #define AMI_EXTENSION_REMOVE "DialplanExtensionRemove"
1630 ast_free(overrideswitch_config);
1631 overrideswitch_config = NULL;
1653 if (!destructible || !*destructible) {
1656 res = *destructible;
1657 for (; **destructible; (*destructible)++) {
1658 if (**destructible ==
'[' && !strchr(delim,
'[')) {
1660 }
else if (**destructible ==
']' && !strchr(delim,
']')) {
1664 }
else if (**destructible ==
'\\' && !strchr(delim,
'\\')) {
1666 }
else if (strchr(delim, **destructible) && !square) {
1667 **destructible =
'\0';
1672 if (**destructible ==
'\0') {
1673 *destructible = NULL;
1678 static int pbx_load_config(
const char *
config_file)
1684 char realvalue[256];
1686 char realvalue[8192];
1693 const char *newpm, *ovsw;
1695 char lastextension[256];
1697 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID)
1701 static_config =
ast_true(ast_variable_retrieve(cfg,
"general",
"static"));
1702 write_protect_config =
ast_true(ast_variable_retrieve(cfg,
"general",
"writeprotect"));
1703 if ((aft = ast_variable_retrieve(cfg,
"general",
"autofallthrough")))
1704 autofallthrough_config =
ast_true(aft);
1705 if ((newpm = ast_variable_retrieve(cfg,
"general",
"extenpatternmatchnew")))
1706 extenpatternmatchnew_config =
ast_true(newpm);
1707 clearglobalvars_config =
ast_true(ast_variable_retrieve(cfg,
"general",
"clearglobalvars"));
1708 if ((ovsw = ast_variable_retrieve(cfg,
"general",
"overrideswitch"))) {
1709 if (overrideswitch_config) {
1710 ast_free(overrideswitch_config);
1712 if (!ast_strlen_zero(ovsw)) {
1715 overrideswitch_config = NULL;
1719 ast_copy_string(userscontext, ast_variable_retrieve(cfg,
"general",
"userscontext") ?:
"default",
sizeof(userscontext));
1725 if (strcasecmp(cxt,
"globals")) {
1729 for (v = ast_variable_browse(cfg, cxt); v; v = v->
next) {
1730 pbx_substitute_variables_helper(NULL, v->
value, realvalue,
sizeof(realvalue) - 1);
1739 if (!strcasecmp(cxt,
"general") || !strcasecmp(cxt,
"globals")) {
1747 lastextension[0] =
'\0';
1750 for (v = ast_variable_browse(cfg, cxt); v; v = v->
next) {
1752 char realext[256] =
"";
1753 char *stringp, *ext;
1757 vfile = !*v->
file ? config_file : v->
file;
1759 if (!strncasecmp(v->
name,
"same", 4)) {
1760 if (ast_strlen_zero(lastextension)) {
1762 "No previous pattern in the first entry of context '%s' to match '%s' at line %d of %s!\n",
1763 cxt, v->
name, v->lineno, vfile);
1768 goto process_extension;
1770 }
else if (!strcasecmp(v->
name,
"exten")) {
1773 char *pri, *appl, *data, *cidmatch;
1780 pbx_substitute_variables_helper(NULL, ext, realext,
sizeof(realext) - 1);
1784 if ((cidmatch = strchr(realext,
'/'))) {
1789 if ((label = strchr(pri,
'('))) {
1791 if ((end = strchr(label,
')'))) {
1794 ast_log(LOG_WARNING,
1795 "Label missing trailing ')' at line %d of %s\n",
1801 if ((plus = strchr(pri,
'+'))) {
1804 if (!strcmp(pri,
"hint")) {
1806 }
else if (!strcmp(pri,
"next") || !strcmp(pri,
"n")) {
1810 ast_log(LOG_WARNING,
1811 "Can't use 'next' priority on the first entry at line %d of %s!\n",
1816 }
else if (!strcmp(pri,
"same") || !strcmp(pri,
"s")) {
1820 ast_log(LOG_WARNING,
1821 "Can't use 'same' priority on the first entry at line %d of %s!\n",
1826 }
else if (sscanf(pri,
"%30d", &ipri) != 1 &&
1828 ast_log(LOG_WARNING,
1829 "Invalid priority/label '%s' at line %d of %s\n",
1830 pri, v->lineno, vfile);
1834 }
else if (ipri < 1) {
1835 ast_log(LOG_WARNING,
"Invalid priority '%s' at line %d of %s\n",
1836 pri, v->lineno, vfile);
1840 appl =
S_OR(stringp,
"");
1842 if (!strchr(appl,
'(')) {
1853 appl = strsep(&stringp,
"(");
1856 if (strstr(appl,
"${") || strstr(appl,
"$[")){
1858 strcpy(appl, orig_appl);
1863 data =
S_OR(stringp,
"");
1864 if ((end = strrchr(data,
')'))) {
1867 ast_log(LOG_WARNING,
1868 "No closing parenthesis found? '%s(%s' at line %d of %s\n",
1869 appl, data, v->lineno, vfile);
1872 ast_free(orig_appl);
1877 const char *registrar_file;
1882 if (!ast_opt_dont_warn && (!strcmp(realext,
"_.") || !strcmp(realext,
"_!"))) {
1883 ast_log(LOG_WARNING,
1884 "The use of '%s' for an extension is strongly discouraged and can have unexpected behavior. Please use '_X%c' instead at line %d of %s\n",
1885 realext, realext[1], v->lineno, vfile);
1888 registrar_file = strrchr(vfile,
'/');
1889 if (!registrar_file) {
1890 registrar_file = vfile;
1894 if (
ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl,
ast_strdup(data),
ast_free_ptr, registrar, registrar_file, v->lineno)) {
1895 ast_log(LOG_WARNING,
1896 "Unable to register extension at line %d of %s\n",
1901 }
else if (!strcasecmp(v->
name,
"include")) {
1902 pbx_substitute_variables_helper(NULL, v->
value, realvalue,
sizeof(realvalue) - 1);
1906 ast_log(LOG_WARNING,
"Out of memory for context addition\n");
1910 ast_log(LOG_WARNING,
"Failed to lock context(s) list, please try again later\n");
1914 ast_log(LOG_WARNING,
1915 "Context '%s' already included in '%s' context on include at line %d of %s\n",
1916 v->
value, cxt, v->lineno, vfile);
1921 ast_log(LOG_WARNING,
1922 "There is no existence of context '%s' included at line %d of %s\n",
1923 errno == ENOENT ? v->
value : cxt, v->lineno, vfile);
1927 ast_log(LOG_WARNING,
1928 "Failed to include '%s' in '%s' context at line %d of %s\n",
1929 v->
value, cxt, v->lineno, vfile);
1933 }
else if (!strcasecmp(v->
name,
"ignorepat")) {
1934 pbx_substitute_variables_helper(NULL, v->
value, realvalue,
sizeof(realvalue) - 1);
1935 if (ast_context_add_ignorepat2(con, realvalue, registrar)) {
1936 ast_log(LOG_WARNING,
1937 "Unable to include ignorepat '%s' in context '%s' at line %d of %s\n",
1938 v->
value, cxt, v->lineno, vfile);
1940 }
else if (!strcasecmp(v->
name,
"switch") || !strcasecmp(v->
name,
"lswitch") || !strcasecmp(v->
name,
"eswitch")) {
1942 stringp = realvalue;
1944 if (!strcasecmp(v->
name,
"switch")) {
1945 pbx_substitute_variables_helper(NULL, v->
value, realvalue,
sizeof(realvalue) - 1);
1949 appl = strsep(&stringp,
"/");
1950 data =
S_OR(stringp,
"");
1952 ast_log(LOG_WARNING,
1953 "Unable to include switch '%s' in context '%s' at line %d of %s\n",
1954 v->
value, cxt, v->lineno, vfile);
1956 }
else if (!strcasecmp(v->
name,
"autohints")) {
1959 ast_log(LOG_WARNING,
1960 "==!!== Unknown directive: %s at line %d of %s -- IGNORING!!!\n",
1961 v->
name, v->lineno, vfile);
1969 static void append_interface(
char *iface,
int maxlen,
char *add)
1971 int len = strlen(iface);
1972 if (strlen(add) + len < maxlen - 2) {
1973 if (strlen(iface)) {
1975 strcpy(iface + len + 1, add);
1993 if (strcmp(type,
"FullyBooted")) {
1997 ast_log(LOG_WARNING,
"users.conf is deprecated and will be removed in a future version of Asterisk\n");
2006 const char *dahdichan;
2007 const char *hasexten, *altexts;
2010 char dahdicopy[256];
2011 char *ext, altcopy[256];
2014 int start, finish, x;
2023 fully_booted_subscription =
2027 if (!strcasecmp(cat,
"general"))
2031 snprintf(tmp,
sizeof(tmp),
"IAX2/%s", cat);
2032 append_interface(iface,
sizeof(iface), tmp);
2035 snprintf(tmp,
sizeof(tmp),
"H323/%s", cat);
2036 append_interface(iface,
sizeof(iface), tmp);
2039 if (hasexten && !
ast_true(hasexten))
2042 dahdichan = ast_variable_retrieve(cfg, cat,
"dahdichan");
2044 dahdichan = ast_variable_retrieve(cfg,
"general",
"dahdichan");
2045 if (!ast_strlen_zero(dahdichan)) {
2048 chan = strsep(&c,
",");
2050 if (sscanf(chan,
"%30d-%30d", &start, &finish) == 2) {
2052 }
else if (sscanf(chan,
"%30d", &start)) {
2056 start = 0; finish = 0;
2058 if (finish < start) {
2063 for (x = start; x <= finish; x++) {
2064 snprintf(tmp,
sizeof(tmp),
"DAHDI/%d", x);
2065 append_interface(iface,
sizeof(iface), tmp);
2067 chan = strsep(&c,
",");
2070 if (!ast_strlen_zero(iface)) {
2077 ast_log(LOG_ERROR,
"Can't find/create user context '%s'\n", userscontext);
2082 ast_add_extension2(con, 0, cat, -1, NULL, NULL, iface, NULL, NULL, registrar, NULL, 0);
2085 snprintf(tmp,
sizeof(tmp),
"%s,stdexten(${HINT})", cat);
2086 ast_add_extension2(con, 0, cat, 1, NULL, NULL,
"Gosub",
ast_strdup(tmp),
ast_free_ptr, registrar, NULL, 0);
2088 ast_add_extension2(con, 0, cat, 1, NULL, NULL,
"Dial",
ast_strdup(
"${HINT}"),
ast_free_ptr, registrar, NULL, 0);
2090 altexts = ast_variable_retrieve(cfg, cat,
"alternateexts");
2091 if (!ast_strlen_zero(altexts)) {
2092 snprintf(tmp,
sizeof(tmp),
"%s,1", cat);
2095 ext = strsep(&c,
",");
2097 ast_add_extension2(con, 0, ext, 1, NULL, NULL,
"Goto",
ast_strdup(tmp),
ast_free_ptr, registrar, NULL, 0);
2098 ext = strsep(&c,
",");
2106 static int pbx_load_module(
void)
2110 ast_mutex_lock(&reload_lock);
2115 ast_mutex_unlock(&reload_lock);
2120 if (!pbx_load_config(config)) {
2123 ast_mutex_unlock(&reload_lock);
2131 local_contexts = NULL;
2133 ast_mutex_unlock(&reload_lock);
2135 for (con = NULL; (con = ast_walk_contexts(con));)
2145 static int load_module(
void)
2149 if (pbx_load_module()) {
2154 if (static_config && !write_protect_config)
2159 EVENT_FLAG_SYSTEM, manager_dialplan_extension_add);
2161 EVENT_FLAG_SYSTEM, manager_dialplan_extension_remove);
2171 static int reload(
void)
2173 if (clearglobalvars_config)
2174 pbx_builtin_clear_globals();
2175 return pbx_load_module();
2178 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,
"Text Extension Configuration",
2179 .support_level = AST_MODULE_SUPPORT_CORE,
2180 .load = load_module,
ast_include: include= support in extensions.conf
struct ast_variable * next
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
int ast_unlock_context(struct ast_context *con)
static char * handle_cli_dialplan_remove_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
int ast_context_remove_include(const char *context, const char *include, const char *registrar)
Remove a context include.
int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
Remove an ignorepat.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
descriptor for a cli entry.
Structure for variables, used for configurations and for channel variables.
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
static char * handle_cli_dialplan_remove_context(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
static char * complete_dialplan_add_extension(struct ast_cli_args *)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
int ast_rdlock_contexts(void)
Read locks the context list.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
int ast_wrlock_contexts(void)
Write locks the context list.
char * ast_escape_semicolons(const char *string, char *outbuf, int buflen)
Escape semicolons found in a string.
#define ast_strdup(str)
A wrapper for strdup()
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
static int partial_match(const char *s, const char *word, int len)
match the first 'len' chars of word. len==0 always succeeds
void ast_free_ptr(void *ptr)
free() wrapper
int ast_context_add_include(const char *context, const char *include, const char *registrar)
Add a context include.
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
int ast_context_destroy_by_name(const char *context, const char *registrar)
Destroy a context by name.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
#define ast_cli_register(e)
Registers a command or an array of commands.
static char * handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
ADD EXTENSION command stuff.
static int lookup_ci(struct ast_context *c, const char *name)
return true if 'name' is included by context c
Configuration File Parser.
static const char config_file[]
static void pbx_load_users(void)
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
struct ast_context * ast_context_find(const char *name)
Find a context.
#define ast_config_load(filename, flags)
Load a config file.
ast_sw: Switch statement in extensions.conf
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
int ast_context_add_ignorepat(const char *context, const char *ignorepat, const char *registrar)
Add an ignorepat.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static char * handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
'save dialplan' CLI command implementation functions ...
#define AST_MAX_EXTENSION
int pbx_set_extenpatternmatchnew(int newval)
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
structure to hold extensions
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
int pbx_set_autofallthrough(int newval)
Core PBX routines and definitions.
static char * handle_cli_dialplan_remove_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
static char * handle_cli_dialplan_add_ignorepat(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int lookup_c_ip(struct ast_context *c, const char *name)
return true if 'name' is in the ignorepats for context c
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
ast_ignorepat: Ignore patterns in dial plan
int ast_unlock_contexts(void)
Unlocks contexts.
static int split_ec(const char *src, char **ext, char **const ctx, char **const cid)
split extension@context in two parts, return -1 on error. The return string is malloc'ed and pointed ...
static int unload_module(void)
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
static char * pbx_strsep(char **destructible, const char *delim)
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Support for logging to various files, console and syslog Configuration in file logger.conf.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Module has failed to load, may be in an inconsistent state.
static struct ast_cli_entry cli_pbx_config[]
Structure used to handle boolean flags.
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Add an extension to an extension context, this time with an ast_context *.
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Standard Command Line Interface.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void pbx_set_overrideswitch(const char *newval)
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
static char * handle_cli_dialplan_add_include(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
int ast_context_verify_includes(struct ast_context *con)
Verifies includes in an ast_contect structure.
static const char * skip_words(const char *p, int n)
moves to the n-th word in the string, or empty string if none
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
void ast_context_set_autohints(struct ast_context *con, int enabled)
Enable or disable autohints support on a context.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
#define ASTERISK_GPL_KEY
The text the key() function should return.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
ast_context: An extension context
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
void ast_hashtab_destroy(struct ast_hashtab *tab, void(*objdestroyfunc)(void *obj))
This func will free the hash table and all its memory.