00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00029
00030 #include <sys/types.h>
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <ctype.h>
00035 #include <errno.h>
00036
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/config.h"
00039 #include "asterisk/options.h"
00040 #include "asterisk/module.h"
00041 #include "asterisk/logger.h"
00042 #include "asterisk/cli.h"
00043 #include "asterisk/callerid.h"
00044
00045 static char *config = "extensions.conf";
00046 static char *registrar = "pbx_config";
00047 static char userscontext[AST_MAX_EXTENSION] = "default";
00048
00049 static int static_config = 0;
00050 static int write_protect_config = 1;
00051 static int autofallthrough_config = 1;
00052 static int clearglobalvars_config = 0;
00053
00054 AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
00055
00056 static struct ast_context *local_contexts = NULL;
00057
00058
00059
00060
00061 static char context_add_extension_help[] =
00062 "Usage: dialplan add extension <exten>,<priority>,<app>,<app-data>\n"
00063 " into <context> [replace]\n\n"
00064 " This command will add new extension into <context>. If there is an\n"
00065 " existence of extension with the same priority and last 'replace'\n"
00066 " arguments is given here we simply replace this extension.\n"
00067 "\n"
00068 "Example: dialplan add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n"
00069 " Now, you can dial 6123 and talk to Markster :)\n";
00070
00071 static char context_remove_extension_help[] =
00072 "Usage: dialplan remove extension exten@context [priority]\n"
00073 " Remove an extension from a given context. If a priority\n"
00074 " is given, only that specific priority from the given extension\n"
00075 " will be removed.\n";
00076
00077 static char context_add_ignorepat_help[] =
00078 "Usage: dialplan add ignorepat <pattern> into <context>\n"
00079 " This command adds a new ignore pattern into context <context>\n"
00080 "\n"
00081 "Example: dialplan add ignorepat _3XX into local\n";
00082
00083 static char context_remove_ignorepat_help[] =
00084 "Usage: dialplan remove ignorepat <pattern> from <context>\n"
00085 " This command removes an ignore pattern from context <context>\n"
00086 "\n"
00087 "Example: dialplan remove ignorepat _3XX from local\n";
00088
00089 static char context_add_include_help[] =
00090 "Usage: dialplan add include <context> into <context>\n"
00091 " Include a context in another context.\n";
00092
00093 static char context_remove_include_help[] =
00094 "Usage: dialplan remove include <context> from <context>\n"
00095 " Remove an included context from another context.\n";
00096
00097 static char save_dialplan_help[] =
00098 "Usage: dialplan save [/path/to/extension/file]\n"
00099 " Save dialplan created by pbx_config module.\n"
00100 "\n"
00101 "Example: dialplan save (/etc/asterisk/extensions.conf)\n"
00102 " dialplan save /home/markster (/home/markster/extensions.conf)\n";
00103
00104 static char reload_extensions_help[] =
00105 "Usage: dialplan reload\n"
00106 " reload extensions.conf without reloading any other modules\n"
00107 " This command does not delete global variables unless\n"
00108 " clearglobalvars is set to yes in extensions.conf\n";
00109
00110
00111
00112
00113
00114
00115
00116
00117 static int handle_context_dont_include_deprecated(int fd, int argc, char *argv[])
00118 {
00119 if (argc != 5)
00120 return RESULT_SHOWUSAGE;
00121
00122 if (strcmp(argv[3], "into"))
00123 return RESULT_SHOWUSAGE;
00124
00125 if (!ast_context_remove_include(argv[4], argv[2], registrar)) {
00126 ast_cli(fd, "We are not including '%s' into '%s' now\n",
00127 argv[2], argv[4]);
00128 return RESULT_SUCCESS;
00129 }
00130
00131 ast_cli(fd, "Failed to remove '%s' include from '%s' context\n",
00132 argv[2], argv[4]);
00133 return RESULT_FAILURE;
00134 }
00135
00136 static int handle_context_remove_include(int fd, int argc, char *argv[])
00137 {
00138 if (argc != 6)
00139 return RESULT_SHOWUSAGE;
00140
00141 if (strcmp(argv[4], "into"))
00142 return RESULT_SHOWUSAGE;
00143
00144 if (!ast_context_remove_include(argv[5], argv[3], registrar)) {
00145 ast_cli(fd, "We are not including '%s' into '%s' now\n",
00146 argv[3], argv[5]);
00147 return RESULT_SUCCESS;
00148 }
00149
00150 ast_cli(fd, "Failed to remove '%s' include from '%s' context\n",
00151 argv[3], argv[5]);
00152 return RESULT_FAILURE;
00153 }
00154
00155
00156 static int lookup_ci(struct ast_context *c, const char *name)
00157 {
00158 struct ast_include *i = NULL;
00159
00160 if (ast_lock_context(c))
00161 return 0;
00162 while ( (i = ast_walk_context_includes(c, i)) )
00163 if (!strcmp(name, ast_get_include_name(i)))
00164 break;
00165 ast_unlock_context(c);
00166 return i ? -1 : 0;
00167 }
00168
00169
00170 static int lookup_c_ip(struct ast_context *c, const char *name)
00171 {
00172 struct ast_ignorepat *ip = NULL;
00173
00174 if (ast_lock_context(c))
00175 return 0;
00176 while ( (ip = ast_walk_context_ignorepats(c, ip)) )
00177 if (!strcmp(name, ast_get_ignorepat_name(ip)))
00178 break;
00179 ast_unlock_context(c);
00180 return ip ? -1 : 0;
00181 }
00182
00183
00184 static const char *skip_words(const char *p, int n)
00185 {
00186 int in_blank = 0;
00187 for (;n && *p; p++) {
00188 if (isblank(*p) && !in_blank) {
00189 n--;
00190 in_blank = 1;
00191 } else if ( in_blank) {
00192 in_blank = 0;
00193 }
00194 }
00195 return p;
00196 }
00197
00198
00199 static int partial_match(const char *s, const char *word, int len)
00200 {
00201 return (len == 0 || !strncmp(s, word, len));
00202 }
00203
00204
00205
00206
00207 static int split_ec(const char *src, char **ext, char ** const ctx)
00208 {
00209 char *c, *e = ast_strdup(src);
00210
00211 if (e == NULL)
00212 return -1;
00213
00214 *ext = e;
00215 c = strchr(e, '@');
00216 if (c == NULL)
00217 *ctx = "";
00218 else {
00219 *c++ = '\0';
00220 *ctx = c;
00221 if (strchr(c, '@')) {
00222 free(e);
00223 return -1;
00224 }
00225 }
00226 return 0;
00227 }
00228
00229
00230 static char *complete_context_dont_include_deprecated(const char *line, const char *word,
00231 int pos, int state)
00232 {
00233 int which = 0;
00234 char *res = NULL;
00235 int len = strlen(word);
00236 struct ast_context *c = NULL;
00237
00238 if (pos == 2) {
00239 if (ast_lock_contexts()) {
00240 ast_log(LOG_ERROR, "Failed to lock context list\n");
00241 return NULL;
00242 }
00243
00244 while (!res && (c = ast_walk_contexts(c))) {
00245 struct ast_include *i = NULL;
00246
00247 if (ast_lock_context(c))
00248 continue;
00249
00250 while ( !res && (i = ast_walk_context_includes(c, i)) ) {
00251 const char *i_name = ast_get_include_name(i);
00252 struct ast_context *nc = NULL;
00253 int already_served = 0;
00254
00255 if (!partial_match(i_name, word, len))
00256 continue;
00257
00258
00259
00260
00261
00262
00263 while ( (nc = ast_walk_contexts(nc)) && nc != c && !already_served)
00264 already_served = lookup_ci(nc, i_name);
00265
00266 if (!already_served && ++which > state)
00267 res = strdup(i_name);
00268 }
00269 ast_unlock_context(c);
00270 }
00271
00272 ast_unlock_contexts();
00273 return res;
00274 } else if (pos == 3) {
00275
00276
00277
00278
00279 char *context, *dupline;
00280 const char *s = skip_words(line, 2);
00281
00282 if (state > 0)
00283 return NULL;
00284 context = dupline = strdup(s);
00285 if (!dupline) {
00286 ast_log(LOG_ERROR, "Out of free memory\n");
00287 return NULL;
00288 }
00289 strsep(&dupline, " ");
00290
00291 if (ast_lock_contexts()) {
00292 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
00293 free(context);
00294 return NULL;
00295 }
00296
00297
00298 while (!res && (c = ast_walk_contexts(c)))
00299 if (lookup_ci(c, context))
00300 res = strdup("in");
00301 ast_unlock_contexts();
00302 if (!res)
00303 ast_log(LOG_WARNING, "%s not included anywhere\n", context);
00304 free(context);
00305 return res;
00306 } else if (pos == 4) {
00307
00308
00309
00310 char *context, *dupline, *in;
00311 const char *s = skip_words(line, 2);
00312 context = dupline = strdup(s);
00313 if (!dupline) {
00314 ast_log(LOG_ERROR, "Out of free memory\n");
00315 return NULL;
00316 }
00317
00318 strsep(&dupline, " ");
00319
00320
00321 in = strsep(&dupline, " ");
00322 if (!in || strcmp(in, "in")) {
00323 free(context);
00324 return NULL;
00325 }
00326
00327 if (ast_lock_contexts()) {
00328 ast_log(LOG_ERROR, "Failed to lock context list\n");
00329 free(context);
00330 return NULL;
00331 }
00332
00333
00334 c = NULL;
00335 while ( !res && (c = ast_walk_contexts(c))) {
00336 const char *c_name = ast_get_context_name(c);
00337 if (!partial_match(c_name, word, len))
00338 continue;
00339
00340 if (lookup_ci(c, context) && ++which > state)
00341 res = strdup(c_name);
00342 }
00343 ast_unlock_contexts();
00344 free(context);
00345 return res;
00346 }
00347
00348 return NULL;
00349 }
00350
00351 static char *complete_context_remove_include(const char *line, const char *word,
00352 int pos, int state)
00353 {
00354 int which = 0;
00355 char *res = NULL;
00356 int len = strlen(word);
00357 struct ast_context *c = NULL;
00358
00359 if (pos == 3) {
00360 if (ast_lock_contexts()) {
00361 ast_log(LOG_ERROR, "Failed to lock context list\n");
00362 return NULL;
00363 }
00364
00365 while (!res && (c = ast_walk_contexts(c))) {
00366 struct ast_include *i = NULL;
00367
00368 if (ast_lock_context(c))
00369 continue;
00370
00371 while ( !res && (i = ast_walk_context_includes(c, i)) ) {
00372 const char *i_name = ast_get_include_name(i);
00373 struct ast_context *nc = NULL;
00374 int already_served = 0;
00375
00376 if (!partial_match(i_name, word, len))
00377 continue;
00378
00379
00380
00381
00382
00383
00384 while ( (nc = ast_walk_contexts(nc)) && nc != c && !already_served)
00385 already_served = lookup_ci(nc, i_name);
00386
00387 if (!already_served && ++which > state)
00388 res = strdup(i_name);
00389 }
00390 ast_unlock_context(c);
00391 }
00392
00393 ast_unlock_contexts();
00394 return res;
00395 } else if (pos == 4) {
00396
00397
00398
00399
00400 char *context, *dupline;
00401 const char *s = skip_words(line, 3);
00402
00403 if (state > 0)
00404 return NULL;
00405 context = dupline = strdup(s);
00406 if (!dupline) {
00407 ast_log(LOG_ERROR, "Out of free memory\n");
00408 return NULL;
00409 }
00410 strsep(&dupline, " ");
00411
00412 if (ast_lock_contexts()) {
00413 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
00414 free(context);
00415 return NULL;
00416 }
00417
00418
00419 while (!res && (c = ast_walk_contexts(c)))
00420 if (lookup_ci(c, context))
00421 res = strdup("from");
00422 ast_unlock_contexts();
00423 if (!res)
00424 ast_log(LOG_WARNING, "%s not included anywhere\n", context);
00425 free(context);
00426 return res;
00427 } else if (pos == 5) {
00428
00429
00430
00431 char *context, *dupline, *from;
00432 const char *s = skip_words(line, 3);
00433 context = dupline = strdup(s);
00434 if (!dupline) {
00435 ast_log(LOG_ERROR, "Out of free memory\n");
00436 return NULL;
00437 }
00438
00439 strsep(&dupline, " ");
00440
00441
00442 from = strsep(&dupline, " ");
00443 if (!from || strcmp(from, "from")) {
00444 free(context);
00445 return NULL;
00446 }
00447
00448 if (ast_lock_contexts()) {
00449 ast_log(LOG_ERROR, "Failed to lock context list\n");
00450 free(context);
00451 return NULL;
00452 }
00453
00454
00455 c = NULL;
00456 while ( !res && (c = ast_walk_contexts(c))) {
00457 const char *c_name = ast_get_context_name(c);
00458 if (!partial_match(c_name, word, len))
00459 continue;
00460
00461 if (lookup_ci(c, context) && ++which > state)
00462 res = strdup(c_name);
00463 }
00464 ast_unlock_contexts();
00465 free(context);
00466 return res;
00467 }
00468
00469 return NULL;
00470 }
00471
00472
00473
00474
00475 static int handle_context_remove_extension_deprecated(int fd, int argc, char *argv[])
00476 {
00477 int removing_priority = 0;
00478 char *exten, *context;
00479 int ret = RESULT_FAILURE;
00480
00481 if (argc != 4 && argc != 3) return RESULT_SHOWUSAGE;
00482
00483
00484
00485
00486 if (argc == 4) {
00487 char *c = argv[3];
00488
00489
00490
00491
00492
00493 if (!strcmp("hint", c))
00494 removing_priority = PRIORITY_HINT;
00495 else {
00496 while (*c && isdigit(*c))
00497 c++;
00498 if (*c) {
00499 ast_cli(fd, "Invalid priority '%s'\n", argv[3]);
00500 return RESULT_FAILURE;
00501 }
00502 removing_priority = atoi(argv[3]);
00503 }
00504
00505 if (removing_priority == 0) {
00506 ast_cli(fd, "If you want to remove whole extension, please " \
00507 "omit priority argument\n");
00508 return RESULT_FAILURE;
00509 }
00510 }
00511
00512
00513
00514
00515
00516 if (split_ec(argv[2], &exten, &context))
00517 return RESULT_FAILURE;
00518 if ((!strlen(exten)) || (!(strlen(context)))) {
00519 ast_cli(fd, "Missing extension or context name in second argument '%s'\n",
00520 argv[2]);
00521 free(exten);
00522 return RESULT_FAILURE;
00523 }
00524
00525 if (!ast_context_remove_extension(context, exten, removing_priority, registrar)) {
00526 if (!removing_priority)
00527 ast_cli(fd, "Whole extension %s@%s removed\n",
00528 exten, context);
00529 else
00530 ast_cli(fd, "Extension %s@%s with priority %d removed\n",
00531 exten, context, removing_priority);
00532
00533 ret = RESULT_SUCCESS;
00534 } else {
00535 ast_cli(fd, "Failed to remove extension %s@%s\n", exten, context);
00536 ret = RESULT_FAILURE;
00537 }
00538 free(exten);
00539 return ret;
00540 }
00541
00542 static int handle_context_remove_extension(int fd, int argc, char *argv[])
00543 {
00544 int removing_priority = 0;
00545 char *exten, *context;
00546 int ret = RESULT_FAILURE;
00547
00548 if (argc != 5 && argc != 4) return RESULT_SHOWUSAGE;
00549
00550
00551
00552
00553 if (argc == 5) {
00554 char *c = argv[4];
00555
00556
00557
00558
00559
00560 if (!strcmp("hint", c))
00561 removing_priority = PRIORITY_HINT;
00562 else {
00563 while (*c && isdigit(*c))
00564 c++;
00565 if (*c) {
00566 ast_cli(fd, "Invalid priority '%s'\n", argv[4]);
00567 return RESULT_FAILURE;
00568 }
00569 removing_priority = atoi(argv[4]);
00570 }
00571
00572 if (removing_priority == 0) {
00573 ast_cli(fd, "If you want to remove whole extension, please " \
00574 "omit priority argument\n");
00575 return RESULT_FAILURE;
00576 }
00577 }
00578
00579
00580
00581
00582
00583 if (split_ec(argv[3], &exten, &context))
00584 return RESULT_FAILURE;
00585 if ((!strlen(exten)) || (!(strlen(context)))) {
00586 ast_cli(fd, "Missing extension or context name in third argument '%s'\n",
00587 argv[3]);
00588 free(exten);
00589 return RESULT_FAILURE;
00590 }
00591
00592 if (!ast_context_remove_extension(context, exten, removing_priority, registrar)) {
00593 if (!removing_priority)
00594 ast_cli(fd, "Whole extension %s@%s removed\n",
00595 exten, context);
00596 else
00597 ast_cli(fd, "Extension %s@%s with priority %d removed\n",
00598 exten, context, removing_priority);
00599
00600 ret = RESULT_SUCCESS;
00601 } else {
00602 ast_cli(fd, "Failed to remove extension %s@%s\n", exten, context);
00603 ret = RESULT_FAILURE;
00604 }
00605 free(exten);
00606 return ret;
00607 }
00608
00609 #define BROKEN_READLINE 1
00610
00611 #ifdef BROKEN_READLINE
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 static int fix_complete_args(const char *line, char **word, int *pos)
00625 {
00626 char *_line, *_strsep_line, *_previous_word = NULL, *_word = NULL;
00627 int words = 0;
00628
00629 _line = strdup(line);
00630
00631 _strsep_line = _line;
00632 while (_strsep_line) {
00633 _previous_word = _word;
00634 _word = strsep(&_strsep_line, " ");
00635
00636 if (_word && strlen(_word)) words++;
00637 }
00638
00639
00640 if (_word || _previous_word) {
00641 if (_word) {
00642 if (!strlen(_word)) words++;
00643 *word = strdup(_word);
00644 } else
00645 *word = strdup(_previous_word);
00646 *pos = words - 1;
00647 free(_line);
00648 return 0;
00649 }
00650
00651 free(_line);
00652 return -1;
00653 }
00654 #endif
00655
00656 static char *complete_context_remove_extension_deprecated(const char *line, const char *word, int pos,
00657 int state)
00658 {
00659 char *ret = NULL;
00660 int which = 0;
00661
00662 #ifdef BROKEN_READLINE
00663 char *word2;
00664
00665
00666
00667
00668 if (fix_complete_args(line, &word2, &pos)) {
00669 ast_log(LOG_ERROR, "Out of free memory\n");
00670 return NULL;
00671 }
00672 word = word2;
00673 #endif
00674
00675 if (pos == 2) {
00676 struct ast_context *c = NULL;
00677 char *context = NULL, *exten = NULL;
00678 int le = 0;
00679 int lc = 0;
00680
00681 lc = split_ec(word, &exten, &context);
00682 #ifdef BROKEN_READLINE
00683 free(word2);
00684 #endif
00685 if (lc)
00686 return NULL;
00687 le = strlen(exten);
00688 lc = strlen(context);
00689
00690 if (ast_lock_contexts()) {
00691 ast_log(LOG_ERROR, "Failed to lock context list\n");
00692 goto error2;
00693 }
00694
00695
00696 while ( (c = ast_walk_contexts(c)) ) {
00697 struct ast_exten *e = NULL;
00698
00699 if (!partial_match(ast_get_context_name(c), context, lc))
00700 continue;
00701 while ( (e = ast_walk_context_extensions(c, e)) ) {
00702 if ( partial_match(ast_get_extension_name(e), exten, le) && ++which > state) {
00703
00704 if (exten)
00705 asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
00706 break;
00707 }
00708 }
00709 if (e)
00710 break;
00711 }
00712
00713 ast_unlock_contexts();
00714 error2:
00715 if (exten)
00716 free(exten);
00717 } else if (pos == 3) {
00718 char *exten = NULL, *context, *p;
00719 struct ast_context *c;
00720 int le, lc, len;
00721 const char *s = skip_words(line, 2);
00722 int i = split_ec(s, &exten, &context);
00723
00724 if (i)
00725 goto error3;
00726 if ( (p = strchr(exten, ' ')) )
00727 *p = '\0';
00728 if ( (p = strchr(context, ' ')) )
00729 *p = '\0';
00730 le = strlen(exten);
00731 lc = strlen(context);
00732 len = strlen(word);
00733 if (le == 0 || lc == 0)
00734 goto error3;
00735
00736 if (ast_lock_contexts()) {
00737 ast_log(LOG_ERROR, "Failed to lock context list\n");
00738 goto error3;
00739 }
00740
00741
00742 c = NULL;
00743 while ( (c = ast_walk_contexts(c)) ) {
00744
00745 struct ast_exten *e;
00746 if (strcmp(ast_get_context_name(c), context) != 0)
00747 continue;
00748
00749 e = NULL;
00750 while ( (e = ast_walk_context_extensions(c, e)) ) {
00751 struct ast_exten *priority;
00752 char buffer[10];
00753
00754 if (strcmp(ast_get_extension_name(e), exten) != 0)
00755 continue;
00756
00757 priority = NULL;
00758 while ( !ret && (priority = ast_walk_extension_priorities(e, priority)) ) {
00759 snprintf(buffer, sizeof(buffer), "%u", ast_get_extension_priority(priority));
00760 if (partial_match(buffer, word, len) && ++which > state)
00761 ret = strdup(buffer);
00762 }
00763 break;
00764 }
00765 break;
00766 }
00767 ast_unlock_contexts();
00768 error3:
00769 if (exten)
00770 free(exten);
00771 #ifdef BROKEN_READLINE
00772 free(word2);
00773 #endif
00774 }
00775 return ret;
00776 }
00777
00778 static char *complete_context_remove_extension(const char *line, const char *word, int pos,
00779 int state)
00780 {
00781 char *ret = NULL;
00782 int which = 0;
00783
00784 #ifdef BROKEN_READLINE
00785 char *word2;
00786
00787
00788
00789
00790 if (fix_complete_args(line, &word2, &pos)) {
00791 ast_log(LOG_ERROR, "Out of free memory\n");
00792 return NULL;
00793 }
00794 word = word2;
00795 #endif
00796
00797 if (pos == 3) {
00798 struct ast_context *c = NULL;
00799 char *context = NULL, *exten = NULL;
00800 int le = 0;
00801 int lc = 0;
00802
00803 lc = split_ec(word, &exten, &context);
00804 #ifdef BROKEN_READLINE
00805 free(word2);
00806 #endif
00807 if (lc)
00808 return NULL;
00809 le = strlen(exten);
00810 lc = strlen(context);
00811
00812 if (ast_lock_contexts()) {
00813 ast_log(LOG_ERROR, "Failed to lock context list\n");
00814 goto error2;
00815 }
00816
00817
00818 while ( (c = ast_walk_contexts(c)) ) {
00819 struct ast_exten *e = NULL;
00820
00821 if (!partial_match(ast_get_context_name(c), context, lc))
00822 continue;
00823 while ( (e = ast_walk_context_extensions(c, e)) ) {
00824 if ( partial_match(ast_get_extension_name(e), exten, le) && ++which > state) {
00825
00826 if (exten)
00827 asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
00828 break;
00829 }
00830 }
00831 if (e)
00832 break;
00833 }
00834
00835 ast_unlock_contexts();
00836 error2:
00837 if (exten)
00838 free(exten);
00839 } else if (pos == 4) {
00840 char *exten = NULL, *context, *p;
00841 struct ast_context *c;
00842 int le, lc, len;
00843 const char *s = skip_words(line, 3);
00844 int i = split_ec(s, &exten, &context);
00845
00846 if (i)
00847 goto error3;
00848 if ( (p = strchr(exten, ' ')) )
00849 *p = '\0';
00850 if ( (p = strchr(context, ' ')) )
00851 *p = '\0';
00852 le = strlen(exten);
00853 lc = strlen(context);
00854 len = strlen(word);
00855 if (le == 0 || lc == 0)
00856 goto error3;
00857
00858 if (ast_lock_contexts()) {
00859 ast_log(LOG_ERROR, "Failed to lock context list\n");
00860 goto error3;
00861 }
00862
00863
00864 c = NULL;
00865 while ( (c = ast_walk_contexts(c)) ) {
00866
00867 struct ast_exten *e;
00868 if (strcmp(ast_get_context_name(c), context) != 0)
00869 continue;
00870
00871 e = NULL;
00872 while ( (e = ast_walk_context_extensions(c, e)) ) {
00873 struct ast_exten *priority;
00874 char buffer[10];
00875
00876 if (strcmp(ast_get_extension_name(e), exten) != 0)
00877 continue;
00878
00879 priority = NULL;
00880 while ( !ret && (priority = ast_walk_extension_priorities(e, priority)) ) {
00881 snprintf(buffer, sizeof(buffer), "%u", ast_get_extension_priority(priority));
00882 if (partial_match(buffer, word, len) && ++which > state)
00883 ret = strdup(buffer);
00884 }
00885 break;
00886 }
00887 break;
00888 }
00889 ast_unlock_contexts();
00890 error3:
00891 if (exten)
00892 free(exten);
00893 #ifdef BROKEN_READLINE
00894 free(word2);
00895 #endif
00896 }
00897 return ret;
00898 }
00899
00900
00901
00902
00903 static int handle_context_add_include_deprecated(int fd, int argc, char *argv[])
00904 {
00905 if (argc != 5)
00906 return RESULT_SHOWUSAGE;
00907
00908
00909 if (strcmp(argv[3], "in") && strcmp(argv[3], "into"))
00910 return RESULT_SHOWUSAGE;
00911
00912 if (ast_context_add_include(argv[4], argv[2], registrar)) {
00913 switch (errno) {
00914 case ENOMEM:
00915 ast_cli(fd, "Out of memory for context addition\n");
00916 break;
00917
00918 case EBUSY:
00919 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
00920 break;
00921
00922 case EEXIST:
00923 ast_cli(fd, "Context '%s' already included in '%s' context\n",
00924 argv[2], argv[4]);
00925 break;
00926
00927 case ENOENT:
00928 case EINVAL:
00929 ast_cli(fd, "There is no existence of context '%s'\n",
00930 errno == ENOENT ? argv[4] : argv[2]);
00931 break;
00932
00933 default:
00934 ast_cli(fd, "Failed to include '%s' in '%s' context\n",
00935 argv[2], argv[4]);
00936 break;
00937 }
00938 return RESULT_FAILURE;
00939 }
00940
00941
00942 ast_cli(fd, "Context '%s' included in '%s' context\n",
00943 argv[2], argv[4]);
00944
00945 return RESULT_SUCCESS;
00946 }
00947
00948 static int handle_context_add_include(int fd, int argc, char *argv[])
00949 {
00950 if (argc != 6)
00951 return RESULT_SHOWUSAGE;
00952
00953
00954 if (strcmp(argv[4], "into"))
00955 return RESULT_SHOWUSAGE;
00956
00957 if (ast_context_add_include(argv[5], argv[3], registrar)) {
00958 switch (errno) {
00959 case ENOMEM:
00960 ast_cli(fd, "Out of memory for context addition\n");
00961 break;
00962
00963 case EBUSY:
00964 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
00965 break;
00966
00967 case EEXIST:
00968 ast_cli(fd, "Context '%s' already included in '%s' context\n",
00969 argv[3], argv[5]);
00970 break;
00971
00972 case ENOENT:
00973 case EINVAL:
00974 ast_cli(fd, "There is no existence of context '%s'\n",
00975 errno == ENOENT ? argv[5] : argv[3]);
00976 break;
00977
00978 default:
00979 ast_cli(fd, "Failed to include '%s' in '%s' context\n",
00980 argv[3], argv[5]);
00981 break;
00982 }
00983 return RESULT_FAILURE;
00984 }
00985
00986
00987 ast_cli(fd, "Context '%s' included in '%s' context\n",
00988 argv[3], argv[5]);
00989
00990 return RESULT_SUCCESS;
00991 }
00992
00993 static char *complete_context_add_include_deprecated(const char *line, const char *word, int pos,
00994 int state)
00995 {
00996 struct ast_context *c;
00997 int which = 0;
00998 char *ret = NULL;
00999 int len = strlen(word);
01000
01001 if (pos == 2) {
01002 if (ast_lock_contexts()) {
01003 ast_log(LOG_ERROR, "Failed to lock context list\n");
01004 return NULL;
01005 }
01006 for (c = NULL; !ret && (c = ast_walk_contexts(c)); )
01007 if (partial_match(ast_get_context_name(c), word, len) && ++which > state)
01008 ret = strdup(ast_get_context_name(c));
01009 ast_unlock_contexts();
01010 return ret;
01011 } else if (pos == 3) {
01012
01013 char *context, *dupline;
01014 struct ast_context *c;
01015 const char *s = skip_words(line, 2);
01016
01017 if (state != 0)
01018 return NULL;
01019
01020
01021 context = dupline = strdup(s);
01022 if (!context) {
01023 ast_log(LOG_ERROR, "Out of free memory\n");
01024 return strdup("in");
01025 }
01026 strsep(&dupline, " ");
01027
01028
01029 if (ast_lock_contexts()) {
01030 ast_log(LOG_ERROR, "Failed to lock context list\n");
01031
01032 ret = strdup("in");
01033 } else {
01034 for (c = NULL; !ret && (c = ast_walk_contexts(c)); )
01035 if (!strcmp(context, ast_get_context_name(c)))
01036 ret = strdup("in");
01037 ast_unlock_contexts();
01038 }
01039 free(context);
01040 return ret;
01041 } else if (pos == 4) {
01042 char *context, *dupline, *in;
01043 const char *s = skip_words(line, 2);
01044 context = dupline = strdup(s);
01045 if (!dupline) {
01046 ast_log(LOG_ERROR, "Out of free memory\n");
01047 return NULL;
01048 }
01049 strsep(&dupline, " ");
01050 in = strsep(&dupline, " ");
01051
01052 if (!strlen(context) || strcmp(in, "in")) {
01053 ast_log(LOG_ERROR, "bad context %s or missing in %s\n",
01054 context, in);
01055 goto error3;
01056 }
01057
01058 if (ast_lock_contexts()) {
01059 ast_log(LOG_ERROR, "Failed to lock context list\n");
01060 goto error3;
01061 }
01062
01063 for (c = NULL; (c = ast_walk_contexts(c)); )
01064 if (!strcmp(context, ast_get_context_name(c)))
01065 break;
01066 if (c) {
01067
01068 for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
01069 if (!strcmp(context, ast_get_context_name(c)))
01070 continue;
01071 if (partial_match(ast_get_context_name(c), word, len) &&
01072 !lookup_ci(c, context) &&
01073 ++which > state)
01074 ret = strdup(ast_get_context_name(c));
01075 }
01076 } else {
01077 ast_log(LOG_ERROR, "context %s not found\n", context);
01078 }
01079 ast_unlock_contexts();
01080 error3:
01081 free(context);
01082 return ret;
01083 }
01084
01085 return NULL;
01086 }
01087
01088 static char *complete_context_add_include(const char *line, const char *word, int pos,
01089 int state)
01090 {
01091 struct ast_context *c;
01092 int which = 0;
01093 char *ret = NULL;
01094 int len = strlen(word);
01095
01096 if (pos == 3) {
01097 if (ast_lock_contexts()) {
01098 ast_log(LOG_ERROR, "Failed to lock context list\n");
01099 return NULL;
01100 }
01101 for (c = NULL; !ret && (c = ast_walk_contexts(c)); )
01102 if (partial_match(ast_get_context_name(c), word, len) && ++which > state)
01103 ret = strdup(ast_get_context_name(c));
01104 ast_unlock_contexts();
01105 return ret;
01106 } else if (pos == 4) {
01107
01108 char *context, *dupline;
01109 struct ast_context *c;
01110 const char *s = skip_words(line, 3);
01111
01112 if (state != 0)
01113 return NULL;
01114
01115
01116 context = dupline = strdup(s);
01117 if (!context) {
01118 ast_log(LOG_ERROR, "Out of free memory\n");
01119 return strdup("into");
01120 }
01121 strsep(&dupline, " ");
01122
01123
01124 if (ast_lock_contexts()) {
01125 ast_log(LOG_ERROR, "Failed to lock context list\n");
01126
01127 ret = strdup("into");
01128 } else {
01129 for (c = NULL; !ret && (c = ast_walk_contexts(c)); )
01130 if (!strcmp(context, ast_get_context_name(c)))
01131 ret = strdup("into");
01132 ast_unlock_contexts();
01133 }
01134 free(context);
01135 return ret;
01136 } else if (pos == 5) {
01137 char *context, *dupline, *into;
01138 const char *s = skip_words(line, 3);
01139 context = dupline = strdup(s);
01140 if (!dupline) {
01141 ast_log(LOG_ERROR, "Out of free memory\n");
01142 return NULL;
01143 }
01144 strsep(&dupline, " ");
01145 into = strsep(&dupline, " ");
01146
01147 if (!strlen(context) || strcmp(into, "into")) {
01148 ast_log(LOG_ERROR, "bad context %s or missing into %s\n",
01149 context, into);
01150 goto error3;
01151 }
01152
01153 if (ast_lock_contexts()) {
01154 ast_log(LOG_ERROR, "Failed to lock context list\n");
01155 goto error3;
01156 }
01157
01158 for (c = NULL; (c = ast_walk_contexts(c)); )
01159 if (!strcmp(context, ast_get_context_name(c)))
01160 break;
01161 if (c) {
01162
01163 for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
01164 if (!strcmp(context, ast_get_context_name(c)))
01165 continue;
01166 if (partial_match(ast_get_context_name(c), word, len) &&
01167 !lookup_ci(c, context) &&
01168 ++which > state)
01169 ret = strdup(ast_get_context_name(c));
01170 }
01171 } else {
01172 ast_log(LOG_ERROR, "context %s not found\n", context);
01173 }
01174 ast_unlock_contexts();
01175 error3:
01176 free(context);
01177 return ret;
01178 }
01179
01180 return NULL;
01181 }
01182
01183
01184
01185
01186 static int handle_save_dialplan(int fd, int argc, char *argv[])
01187 {
01188 char filename[256];
01189 struct ast_context *c;
01190 struct ast_config *cfg;
01191 struct ast_variable *v;
01192 int incomplete = 0;
01193 FILE *output;
01194
01195 const char *base, *slash, *file;
01196
01197 if (! (static_config && !write_protect_config)) {
01198 ast_cli(fd,
01199 "I can't save dialplan now, see '%s' example file.\n",
01200 config);
01201 return RESULT_FAILURE;
01202 }
01203
01204 if (argc != 2 && argc != 3)
01205 return RESULT_SHOWUSAGE;
01206
01207 if (ast_mutex_lock(&save_dialplan_lock)) {
01208 ast_cli(fd,
01209 "Failed to lock dialplan saving (another proccess saving?)\n");
01210 return RESULT_FAILURE;
01211 }
01212
01213
01214
01215 if (argc == 3) {
01216 base = argv[2];
01217 if (!strstr(argv[2], ".conf")) {
01218
01219 slash = (*(argv[2] + strlen(argv[2]) -1) == '/') ? "/" : "";
01220 file = config;
01221 } else {
01222 slash = "";
01223 file = "";
01224 }
01225 } else {
01226
01227 base = ast_config_AST_CONFIG_DIR;
01228 slash = "/";
01229 file = config;
01230 }
01231 snprintf(filename, sizeof(filename), "%s%s%s", base, slash, config);
01232
01233 cfg = ast_config_load("extensions.conf");
01234
01235
01236 if (ast_lock_contexts()) {
01237 ast_cli(fd, "Failed to lock contexts list\n");
01238 ast_mutex_unlock(&save_dialplan_lock);
01239 ast_config_destroy(cfg);
01240 return RESULT_FAILURE;
01241 }
01242
01243
01244 if (!(output = fopen(filename, "wt"))) {
01245 ast_cli(fd, "Failed to create file '%s'\n",
01246 filename);
01247 ast_unlock_contexts();
01248 ast_mutex_unlock(&save_dialplan_lock);
01249 ast_config_destroy(cfg);
01250 return RESULT_FAILURE;
01251 }
01252
01253
01254 fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\npriorityjumping=%s\n\n",
01255 static_config ? "yes" : "no",
01256 write_protect_config ? "yes" : "no",
01257 autofallthrough_config ? "yes" : "no",
01258 clearglobalvars_config ? "yes" : "no",
01259 ast_true(ast_variable_retrieve(cfg, "general", "priorityjumping")) ? "yes" : "no");
01260
01261 if ((v = ast_variable_browse(cfg, "globals"))) {
01262 fprintf(output, "[globals]\n");
01263 while(v) {
01264 fprintf(output, "%s => %s\n", v->name, v->value);
01265 v = v->next;
01266 }
01267 fprintf(output, "\n");
01268 }
01269
01270 ast_config_destroy(cfg);
01271
01272 #define PUT_CTX_HDR do { \
01273 if (!context_header_written) { \
01274 fprintf(output, "[%s]\n", ast_get_context_name(c)); \
01275 context_header_written = 1; \
01276 } \
01277 } while (0)
01278
01279
01280 for (c = NULL; (c = ast_walk_contexts(c)); ) {
01281 int context_header_written = 0;
01282 struct ast_exten *e, *last_written_e = NULL;
01283 struct ast_include *i;
01284 struct ast_ignorepat *ip;
01285 struct ast_sw *sw;
01286
01287
01288 if (ast_lock_context(c)) {
01289 incomplete = 1;
01290 continue;
01291 }
01292
01293
01294 if (!strcmp(ast_get_context_registrar(c), registrar)) {
01295 fprintf(output, "[%s]\n", ast_get_context_name(c));
01296 context_header_written = 1;
01297 }
01298
01299
01300 for (e = NULL; (e = ast_walk_context_extensions(c, e)); ) {
01301 struct ast_exten *p = NULL;
01302
01303
01304 while ( (p = ast_walk_extension_priorities(e, p)) ) {
01305 if (strcmp(ast_get_extension_registrar(p), registrar) != 0)
01306 continue;
01307
01308
01309 if (last_written_e != NULL &&
01310 strcmp(ast_get_extension_name(last_written_e),
01311 ast_get_extension_name(p)))
01312 fprintf(output, "\n");
01313 last_written_e = p;
01314
01315 PUT_CTX_HDR;
01316
01317 if (ast_get_extension_priority(p)==PRIORITY_HINT) {
01318 fprintf(output, "exten => %s,hint,%s\n",
01319 ast_get_extension_name(p),
01320 ast_get_extension_app(p));
01321 } else {
01322 const char *sep, *cid;
01323 char *tempdata;
01324 char *s;
01325 const char *el = ast_get_extension_label(p);
01326 char label[128];
01327
01328 tempdata = ast_strdupa(ast_get_extension_app_data(p));
01329
01330 for (s = tempdata; *s; s++) {
01331 if (*s == '|')
01332 *s = ',';
01333 }
01334
01335 if (ast_get_extension_matchcid(p)) {
01336 sep = "/";
01337 cid = ast_get_extension_cidmatch(p);
01338 } else
01339 sep = cid = "";
01340
01341 if (el && (snprintf(label, 127, "(%s)", el) != (strlen(el) + 2)))
01342 incomplete = 1;
01343
01344 fprintf(output, "exten => %s%s%s,%d%s,%s(%s)\n",
01345 ast_get_extension_name(p), sep, cid,
01346 ast_get_extension_priority(p), label,
01347 ast_get_extension_app(p), tempdata);
01348 }
01349 }
01350 }
01351
01352
01353 if (last_written_e)
01354 fprintf(output, "\n");
01355
01356
01357 for (i = NULL; (i = ast_walk_context_includes(c, i)) ; ) {
01358 if (strcmp(ast_get_include_registrar(i), registrar) != 0)
01359 continue;
01360 PUT_CTX_HDR;
01361 fprintf(output, "include => %s\n", ast_get_include_name(i));
01362 }
01363 if (ast_walk_context_includes(c, NULL))
01364 fprintf(output, "\n");
01365
01366
01367 for (sw = NULL; (sw = ast_walk_context_switches(c, sw)) ; ) {
01368 if (strcmp(ast_get_switch_registrar(sw), registrar) != 0)
01369 continue;
01370 PUT_CTX_HDR;
01371 fprintf(output, "switch => %s/%s\n",
01372 ast_get_switch_name(sw), ast_get_switch_data(sw));
01373 }
01374
01375 if (ast_walk_context_switches(c, NULL))
01376 fprintf(output, "\n");
01377
01378
01379 for (ip = NULL; (ip = ast_walk_context_ignorepats(c, ip)); ) {
01380 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) != 0)
01381 continue;
01382 PUT_CTX_HDR;
01383 fprintf(output, "ignorepat => %s\n",
01384 ast_get_ignorepat_name(ip));
01385 }
01386
01387 ast_unlock_context(c);
01388 }
01389
01390 ast_unlock_contexts();
01391 ast_mutex_unlock(&save_dialplan_lock);
01392 fclose(output);
01393
01394 if (incomplete) {
01395 ast_cli(fd, "Saved dialplan is incomplete\n");
01396 return RESULT_FAILURE;
01397 }
01398
01399 ast_cli(fd, "Dialplan successfully saved into '%s'\n",
01400 filename);
01401 return RESULT_SUCCESS;
01402 }
01403
01404
01405
01406
01407 static int handle_context_add_extension_deprecated(int fd, int argc, char *argv[])
01408 {
01409 char *whole_exten;
01410 char *exten, *prior;
01411 int iprior = -2;
01412 char *cidmatch, *app, *app_data;
01413 char *start, *end;
01414
01415
01416 if (argc != 5 && argc != 6)
01417 return RESULT_SHOWUSAGE;
01418 if (strcmp(argv[3], "into"))
01419 return RESULT_SHOWUSAGE;
01420 if (argc == 6) if (strcmp(argv[5], "replace")) return RESULT_SHOWUSAGE;
01421
01422
01423 whole_exten = argv[2];
01424 exten = strsep(&whole_exten,",");
01425 if (strchr(exten, '/')) {
01426 cidmatch = exten;
01427 strsep(&cidmatch,"/");
01428 } else {
01429 cidmatch = NULL;
01430 }
01431 prior = strsep(&whole_exten,",");
01432 if (prior) {
01433 if (!strcmp(prior, "hint")) {
01434 iprior = PRIORITY_HINT;
01435 } else {
01436 if (sscanf(prior, "%d", &iprior) != 1) {
01437 ast_cli(fd, "'%s' is not a valid priority\n", prior);
01438 prior = NULL;
01439 }
01440 }
01441 }
01442 app = whole_exten;
01443 if (app && (start = strchr(app, '(')) && (end = strrchr(app, ')'))) {
01444 *start = *end = '\0';
01445 app_data = start + 1;
01446 ast_process_quotes_and_slashes(app_data, ',', '|');
01447 } else {
01448 if (app) {
01449 app_data = strchr(app, ',');
01450 if (app_data) {
01451 *app_data = '\0';
01452 app_data++;
01453 }
01454 } else
01455 app_data = NULL;
01456 }
01457
01458 if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT))
01459 return RESULT_SHOWUSAGE;
01460
01461 if (!app_data)
01462 app_data="";
01463 if (ast_add_extension(argv[4], argc == 6 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
01464 (void *)strdup(app_data), free, registrar)) {
01465 switch (errno) {
01466 case ENOMEM:
01467 ast_cli(fd, "Out of free memory\n");
01468 break;
01469
01470 case EBUSY:
01471 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
01472 break;
01473
01474 case ENOENT:
01475 ast_cli(fd, "No existence of '%s' context\n", argv[4]);
01476 break;
01477
01478 case EEXIST:
01479 ast_cli(fd, "Extension %s@%s with priority %s already exists\n",
01480 exten, argv[4], prior);
01481 break;
01482
01483 default:
01484 ast_cli(fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
01485 exten, prior, app, app_data, argv[4]);
01486 break;
01487 }
01488 return RESULT_FAILURE;
01489 }
01490
01491 if (argc == 6)
01492 ast_cli(fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
01493 exten, argv[4], prior, exten, prior, app, app_data);
01494 else
01495 ast_cli(fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
01496 exten, prior, app, app_data, argv[4]);
01497
01498 return RESULT_SUCCESS;
01499 }
01500 static int handle_context_add_extension(int fd, int argc, char *argv[])
01501 {
01502 char *whole_exten;
01503 char *exten, *prior;
01504 int iprior = -2;
01505 char *cidmatch, *app, *app_data;
01506 char *start, *end;
01507
01508
01509 if (argc != 6 && argc != 7)
01510 return RESULT_SHOWUSAGE;
01511 if (strcmp(argv[4], "into"))
01512 return RESULT_SHOWUSAGE;
01513 if (argc == 7) if (strcmp(argv[6], "replace")) return RESULT_SHOWUSAGE;
01514
01515
01516 whole_exten = argv[3];
01517 exten = strsep(&whole_exten,",");
01518 if (strchr(exten, '/')) {
01519 cidmatch = exten;
01520 strsep(&cidmatch,"/");
01521 } else {
01522 cidmatch = NULL;
01523 }
01524 prior = strsep(&whole_exten,",");
01525 if (prior) {
01526 if (!strcmp(prior, "hint")) {
01527 iprior = PRIORITY_HINT;
01528 } else {
01529 if (sscanf(prior, "%d", &iprior) != 1) {
01530 ast_cli(fd, "'%s' is not a valid priority\n", prior);
01531 prior = NULL;
01532 }
01533 }
01534 }
01535 app = whole_exten;
01536 if (app && (start = strchr(app, '(')) && (end = strrchr(app, ')'))) {
01537 *start = *end = '\0';
01538 app_data = start + 1;
01539 ast_process_quotes_and_slashes(app_data, ',', '|');
01540 } else {
01541 if (app) {
01542 app_data = strchr(app, ',');
01543 if (app_data) {
01544 *app_data = '\0';
01545 app_data++;
01546 }
01547 } else
01548 app_data = NULL;
01549 }
01550
01551 if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT))
01552 return RESULT_SHOWUSAGE;
01553
01554 if (!app_data)
01555 app_data="";
01556 if (ast_add_extension(argv[5], argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
01557 (void *)strdup(app_data), free, registrar)) {
01558 switch (errno) {
01559 case ENOMEM:
01560 ast_cli(fd, "Out of free memory\n");
01561 break;
01562
01563 case EBUSY:
01564 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
01565 break;
01566
01567 case ENOENT:
01568 ast_cli(fd, "No existence of '%s' context\n", argv[5]);
01569 break;
01570
01571 case EEXIST:
01572 ast_cli(fd, "Extension %s@%s with priority %s already exists\n",
01573 exten, argv[5], prior);
01574 break;
01575
01576 default:
01577 ast_cli(fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
01578 exten, prior, app, app_data, argv[5]);
01579 break;
01580 }
01581 return RESULT_FAILURE;
01582 }
01583
01584 if (argc == 7)
01585 ast_cli(fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
01586 exten, argv[5], prior, exten, prior, app, app_data);
01587 else
01588 ast_cli(fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
01589 exten, prior, app, app_data, argv[5]);
01590
01591 return RESULT_SUCCESS;
01592 }
01593
01594
01595 static char *complete_context_add_extension_deprecated(const char *line, const char *word, int pos, int state)
01596 {
01597 int which = 0;
01598
01599 if (pos == 3) {
01600 return (state == 0) ? strdup("into") : NULL;
01601 } else if (pos == 4) {
01602 struct ast_context *c = NULL;
01603 int len = strlen(word);
01604 char *res = NULL;
01605
01606
01607 if (ast_lock_contexts()) {
01608 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01609 return NULL;
01610 }
01611
01612
01613 while ( !res && (c = ast_walk_contexts(c)) )
01614 if (partial_match(ast_get_context_name(c), word, len) && ++which > state)
01615 res = strdup(ast_get_context_name(c));
01616 ast_unlock_contexts();
01617 return res;
01618 } else if (pos == 5) {
01619 return state == 0 ? strdup("replace") : NULL;
01620 }
01621 return NULL;
01622 }
01623
01624 static char *complete_context_add_extension(const char *line, const char *word, int pos, int state)
01625 {
01626 int which = 0;
01627
01628 if (pos == 4) {
01629 return (state == 0) ? strdup("into") : NULL;
01630 } else if (pos == 5) {
01631 struct ast_context *c = NULL;
01632 int len = strlen(word);
01633 char *res = NULL;
01634
01635
01636 if (ast_lock_contexts()) {
01637 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01638 return NULL;
01639 }
01640
01641
01642 while ( !res && (c = ast_walk_contexts(c)) )
01643 if (partial_match(ast_get_context_name(c), word, len) && ++which > state)
01644 res = strdup(ast_get_context_name(c));
01645 ast_unlock_contexts();
01646 return res;
01647 } else if (pos == 6) {
01648 return state == 0 ? strdup("replace") : NULL;
01649 }
01650 return NULL;
01651 }
01652
01653
01654
01655
01656 static int handle_context_add_ignorepat_deprecated(int fd, int argc, char *argv[])
01657 {
01658 if (argc != 5)
01659 return RESULT_SHOWUSAGE;
01660 if (strcmp(argv[3], "into"))
01661 return RESULT_SHOWUSAGE;
01662
01663 if (ast_context_add_ignorepat(argv[4], argv[2], registrar)) {
01664 switch (errno) {
01665 case ENOMEM:
01666 ast_cli(fd, "Out of free memory\n");
01667 break;
01668
01669 case ENOENT:
01670 ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
01671 break;
01672
01673 case EEXIST:
01674 ast_cli(fd, "Ignore pattern '%s' already included in '%s' context\n",
01675 argv[2], argv[4]);
01676 break;
01677
01678 case EBUSY:
01679 ast_cli(fd, "Failed to lock context(s) list, please, try again later\n");
01680 break;
01681
01682 default:
01683 ast_cli(fd, "Failed to add ingore pattern '%s' into '%s' context\n",
01684 argv[2], argv[4]);
01685 break;
01686 }
01687 return RESULT_FAILURE;
01688 }
01689
01690 ast_cli(fd, "Ignore pattern '%s' added into '%s' context\n",
01691 argv[2], argv[4]);
01692 return RESULT_SUCCESS;
01693 }
01694
01695 static int handle_context_add_ignorepat(int fd, int argc, char *argv[])
01696 {
01697 if (argc != 6)
01698 return RESULT_SHOWUSAGE;
01699 if (strcmp(argv[4], "into"))
01700 return RESULT_SHOWUSAGE;
01701
01702 if (ast_context_add_ignorepat(argv[5], argv[3], registrar)) {
01703 switch (errno) {
01704 case ENOMEM:
01705 ast_cli(fd, "Out of free memory\n");
01706 break;
01707
01708 case ENOENT:
01709 ast_cli(fd, "There is no existence of '%s' context\n", argv[5]);
01710 break;
01711
01712 case EEXIST:
01713 ast_cli(fd, "Ignore pattern '%s' already included in '%s' context\n",
01714 argv[3], argv[5]);
01715 break;
01716
01717 case EBUSY:
01718 ast_cli(fd, "Failed to lock context(s) list, please, try again later\n");
01719 break;
01720
01721 default:
01722 ast_cli(fd, "Failed to add ingore pattern '%s' into '%s' context\n",
01723 argv[3], argv[5]);
01724 break;
01725 }
01726 return RESULT_FAILURE;
01727 }
01728
01729 ast_cli(fd, "Ignore pattern '%s' added into '%s' context\n",
01730 argv[3], argv[5]);
01731 return RESULT_SUCCESS;
01732 }
01733
01734 static char *complete_context_add_ignorepat_deprecated(const char *line, const char *word,
01735 int pos, int state)
01736 {
01737 if (pos == 3)
01738 return state == 0 ? strdup("into") : NULL;
01739 else if (pos == 4) {
01740 struct ast_context *c;
01741 int which = 0;
01742 char *dupline, *ignorepat = NULL;
01743 const char *s;
01744 char *ret = NULL;
01745 int len = strlen(word);
01746
01747
01748 s = skip_words(line, 2);
01749 if (s == NULL)
01750 return NULL;
01751 dupline = strdup(s);
01752 if (!dupline) {
01753 ast_log(LOG_ERROR, "Malloc failure\n");
01754 return NULL;
01755 }
01756 ignorepat = strsep(&dupline, " ");
01757
01758 if (ast_lock_contexts()) {
01759 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
01760 return NULL;
01761 }
01762
01763 for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
01764 int found = 0;
01765
01766 if (!partial_match(ast_get_context_name(c), word, len))
01767 continue;
01768 if (ignorepat)
01769 found = lookup_c_ip(c, ignorepat);
01770 if (!found && ++which > state)
01771 ret = strdup(ast_get_context_name(c));
01772 }
01773
01774 if (ignorepat)
01775 free(ignorepat);
01776 ast_unlock_contexts();
01777 return ret;
01778 }
01779
01780 return NULL;
01781 }
01782
01783 static char *complete_context_add_ignorepat(const char *line, const char *word,
01784 int pos, int state)
01785 {
01786 if (pos == 4)
01787 return state == 0 ? strdup("into") : NULL;
01788 else if (pos == 5) {
01789 struct ast_context *c;
01790 int which = 0;
01791 char *dupline, *ignorepat = NULL;
01792 const char *s;
01793 char *ret = NULL;
01794 int len = strlen(word);
01795
01796
01797 s = skip_words(line, 3);
01798 if (s == NULL)
01799 return NULL;
01800 dupline = strdup(s);
01801 if (!dupline) {
01802 ast_log(LOG_ERROR, "Malloc failure\n");
01803 return NULL;
01804 }
01805 ignorepat = strsep(&dupline, " ");
01806
01807 if (ast_lock_contexts()) {
01808 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
01809 return NULL;
01810 }
01811
01812 for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
01813 int found = 0;
01814
01815 if (!partial_match(ast_get_context_name(c), word, len))
01816 continue;
01817 if (ignorepat)
01818 found = lookup_c_ip(c, ignorepat);
01819 if (!found && ++which > state)
01820 ret = strdup(ast_get_context_name(c));
01821 }
01822
01823 if (ignorepat)
01824 free(ignorepat);
01825 ast_unlock_contexts();
01826 return ret;
01827 }
01828
01829 return NULL;
01830 }
01831
01832 static int handle_context_remove_ignorepat_deprecated(int fd, int argc, char *argv[])
01833 {
01834 if (argc != 5)
01835 return RESULT_SHOWUSAGE;
01836 if (strcmp(argv[3], "from"))
01837 return RESULT_SHOWUSAGE;
01838
01839 if (ast_context_remove_ignorepat(argv[4], argv[2], registrar)) {
01840 switch (errno) {
01841 case EBUSY:
01842 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
01843 break;
01844
01845 case ENOENT:
01846 ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
01847 break;
01848
01849 case EINVAL:
01850 ast_cli(fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
01851 argv[2], argv[4]);
01852 break;
01853
01854 default:
01855 ast_cli(fd, "Failed to remove ignore pattern '%s' from '%s' context\n", argv[2], argv[4]);
01856 break;
01857 }
01858 return RESULT_FAILURE;
01859 }
01860
01861 ast_cli(fd, "Ignore pattern '%s' removed from '%s' context\n",
01862 argv[2], argv[4]);
01863 return RESULT_SUCCESS;
01864 }
01865
01866 static int handle_context_remove_ignorepat(int fd, int argc, char *argv[])
01867 {
01868 if (argc != 6)
01869 return RESULT_SHOWUSAGE;
01870 if (strcmp(argv[4], "from"))
01871 return RESULT_SHOWUSAGE;
01872
01873 if (ast_context_remove_ignorepat(argv[5], argv[3], registrar)) {
01874 switch (errno) {
01875 case EBUSY:
01876 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
01877 break;
01878
01879 case ENOENT:
01880 ast_cli(fd, "There is no existence of '%s' context\n", argv[5]);
01881 break;
01882
01883 case EINVAL:
01884 ast_cli(fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
01885 argv[3], argv[5]);
01886 break;
01887
01888 default:
01889 ast_cli(fd, "Failed to remove ignore pattern '%s' from '%s' context\n", argv[3], argv[5]);
01890 break;
01891 }
01892 return RESULT_FAILURE;
01893 }
01894
01895 ast_cli(fd, "Ignore pattern '%s' removed from '%s' context\n",
01896 argv[3], argv[5]);
01897 return RESULT_SUCCESS;
01898 }
01899
01900 static char *complete_context_remove_ignorepat_deprecated(const char *line, const char *word,
01901 int pos, int state)
01902 {
01903 struct ast_context *c;
01904 int which = 0;
01905 char *ret = NULL;
01906
01907 if (pos == 2) {
01908 int len = strlen(word);
01909 if (ast_lock_contexts()) {
01910 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01911 return NULL;
01912 }
01913
01914 for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
01915 struct ast_ignorepat *ip;
01916
01917 if (ast_lock_context(c))
01918 continue;
01919
01920 for (ip = NULL; !ret && (ip = ast_walk_context_ignorepats(c, ip));) {
01921 if (partial_match(ast_get_ignorepat_name(ip), word, len) && ++which > state) {
01922
01923 struct ast_context *cw = NULL;
01924 int found = 0;
01925 while ( (cw = ast_walk_contexts(cw)) && cw != c && !found) {
01926
01927 found = lookup_c_ip(cw, ast_get_ignorepat_name(ip));
01928 }
01929 if (!found)
01930 ret = strdup(ast_get_ignorepat_name(ip));
01931 }
01932 }
01933 ast_unlock_context(c);
01934 }
01935 ast_unlock_contexts();
01936 return ret;
01937 } else if (pos == 3) {
01938 return state == 0 ? strdup("from") : NULL;
01939 } else if (pos == 4) {
01940 char *dupline, *duplinet, *ignorepat;
01941 int len = strlen(word);
01942
01943 dupline = strdup(line);
01944 if (!dupline) {
01945 ast_log(LOG_WARNING, "Out of free memory\n");
01946 return NULL;
01947 }
01948
01949 duplinet = dupline;
01950 strsep(&duplinet, " ");
01951 strsep(&duplinet, " ");
01952 ignorepat = strsep(&duplinet, " ");
01953
01954 if (!ignorepat) {
01955 free(dupline);
01956 return NULL;
01957 }
01958
01959 if (ast_lock_contexts()) {
01960 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01961 free(dupline);
01962 return NULL;
01963 }
01964
01965 for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
01966 if (ast_lock_context(c))
01967 continue;
01968 if (!partial_match(ast_get_context_name(c), word, len))
01969 continue;
01970 if (lookup_c_ip(c, ignorepat) && ++which > state)
01971 ret = strdup(ast_get_context_name(c));
01972 ast_unlock_context(c);
01973 }
01974 ast_unlock_contexts();
01975 free(dupline);
01976 return NULL;
01977 }
01978
01979 return NULL;
01980 }
01981
01982 static char *complete_context_remove_ignorepat(const char *line, const char *word,
01983 int pos, int state)
01984 {
01985 struct ast_context *c;
01986 int which = 0;
01987 char *ret = NULL;
01988
01989 if (pos == 3) {
01990 int len = strlen(word);
01991 if (ast_lock_contexts()) {
01992 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01993 return NULL;
01994 }
01995
01996 for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
01997 struct ast_ignorepat *ip;
01998
01999 if (ast_lock_context(c))
02000 continue;
02001
02002 for (ip = NULL; !ret && (ip = ast_walk_context_ignorepats(c, ip));) {
02003 if (partial_match(ast_get_ignorepat_name(ip), word, len) && ++which > state) {
02004
02005 struct ast_context *cw = NULL;
02006 int found = 0;
02007 while ( (cw = ast_walk_contexts(cw)) && cw != c && !found) {
02008
02009 found = lookup_c_ip(cw, ast_get_ignorepat_name(ip));
02010 }
02011 if (!found)
02012 ret = strdup(ast_get_ignorepat_name(ip));
02013 }
02014 }
02015 ast_unlock_context(c);
02016 }
02017 ast_unlock_contexts();
02018 return ret;
02019 } else if (pos == 4) {
02020 return state == 0 ? strdup("from") : NULL;
02021 } else if (pos == 5) {
02022 char *dupline, *duplinet, *ignorepat;
02023 int len = strlen(word);
02024
02025 dupline = strdup(line);
02026 if (!dupline) {
02027 ast_log(LOG_WARNING, "Out of free memory\n");
02028 return NULL;
02029 }
02030
02031 duplinet = dupline;
02032 strsep(&duplinet, " ");
02033 strsep(&duplinet, " ");
02034 ignorepat = strsep(&duplinet, " ");
02035
02036 if (!ignorepat) {
02037 free(dupline);
02038 return NULL;
02039 }
02040
02041 if (ast_lock_contexts()) {
02042 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
02043 free(dupline);
02044 return NULL;
02045 }
02046
02047 for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
02048 if (ast_lock_context(c))
02049 continue;
02050 if (!partial_match(ast_get_context_name(c), word, len))
02051 continue;
02052 if (lookup_c_ip(c, ignorepat) && ++which > state)
02053 ret = strdup(ast_get_context_name(c));
02054 ast_unlock_context(c);
02055 }
02056 ast_unlock_contexts();
02057 free(dupline);
02058 return NULL;
02059 }
02060
02061 return NULL;
02062 }
02063
02064 static int pbx_load_module(void);
02065
02066 static int handle_reload_extensions(int fd, int argc, char *argv[])
02067 {
02068 if (argc != 2)
02069 return RESULT_SHOWUSAGE;
02070 if (clearglobalvars_config)
02071 pbx_builtin_clear_globals();
02072 pbx_load_module();
02073 return RESULT_SUCCESS;
02074 }
02075
02076
02077
02078
02079 static struct ast_cli_entry cli_dont_include_deprecated = {
02080 { "dont", "include", NULL },
02081 handle_context_dont_include_deprecated, NULL,
02082 NULL, complete_context_dont_include_deprecated };
02083
02084 static struct ast_cli_entry cli_remove_extension_deprecated = {
02085 { "remove", "extension", NULL },
02086 handle_context_remove_extension_deprecated, NULL,
02087 NULL, complete_context_remove_extension_deprecated };
02088
02089 static struct ast_cli_entry cli_include_context_deprecated = {
02090 { "include", "context", NULL },
02091 handle_context_add_include_deprecated, NULL,
02092 NULL, complete_context_add_include_deprecated };
02093
02094 static struct ast_cli_entry cli_add_extension_deprecated = {
02095 { "add", "extension", NULL },
02096 handle_context_add_extension_deprecated, NULL,
02097 NULL, complete_context_add_extension_deprecated };
02098
02099 static struct ast_cli_entry cli_add_ignorepat_deprecated = {
02100 { "add", "ignorepat", NULL },
02101 handle_context_add_ignorepat_deprecated, NULL,
02102 NULL, complete_context_add_ignorepat_deprecated };
02103
02104 static struct ast_cli_entry cli_remove_ignorepat_deprecated = {
02105 { "remove", "ignorepat", NULL },
02106 handle_context_remove_ignorepat_deprecated, NULL,
02107 NULL, complete_context_remove_ignorepat_deprecated };
02108
02109 static struct ast_cli_entry cli_extensions_reload_deprecated = {
02110 { "extensions", "reload", NULL },
02111 handle_reload_extensions, NULL,
02112 NULL };
02113
02114 static struct ast_cli_entry cli_save_dialplan_deprecated = {
02115 { "save", "dialplan", NULL },
02116 handle_save_dialplan, NULL,
02117 NULL };
02118
02119 static struct ast_cli_entry cli_pbx_config[] = {
02120 { { "dialplan", "add", "extension", NULL },
02121 handle_context_add_extension, "Add new extension into context",
02122 context_add_extension_help, complete_context_add_extension, &cli_add_extension_deprecated },
02123
02124 { { "dialplan", "remove", "extension", NULL },
02125 handle_context_remove_extension, "Remove a specified extension",
02126 context_remove_extension_help, complete_context_remove_extension, &cli_remove_extension_deprecated },
02127
02128 { { "dialplan", "add", "ignorepat", NULL },
02129 handle_context_add_ignorepat, "Add new ignore pattern",
02130 context_add_ignorepat_help, complete_context_add_ignorepat, &cli_add_ignorepat_deprecated },
02131
02132 { { "dialplan", "remove", "ignorepat", NULL },
02133 handle_context_remove_ignorepat, "Remove ignore pattern from context",
02134 context_remove_ignorepat_help, complete_context_remove_ignorepat, &cli_remove_ignorepat_deprecated },
02135
02136 { { "dialplan", "add", "include", NULL },
02137 handle_context_add_include, "Include context in other context",
02138 context_add_include_help, complete_context_add_include, &cli_include_context_deprecated },
02139
02140 { { "dialplan", "remove", "include", NULL },
02141 handle_context_remove_include, "Remove a specified include from context",
02142 context_remove_include_help, complete_context_remove_include, &cli_dont_include_deprecated },
02143
02144 { { "dialplan", "reload", NULL },
02145 handle_reload_extensions, "Reload extensions and *only* extensions",
02146 reload_extensions_help, NULL, &cli_extensions_reload_deprecated },
02147 };
02148
02149
02150 static struct ast_cli_entry cli_dialplan_save = {
02151 { "dialplan", "save", NULL },
02152 handle_save_dialplan, "Save dialplan",
02153 save_dialplan_help, NULL, &cli_save_dialplan_deprecated };
02154
02155
02156
02157
02158 static int unload_module(void)
02159 {
02160 if (static_config && !write_protect_config)
02161 ast_cli_unregister(&cli_dialplan_save);
02162 ast_cli_unregister_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry));
02163 ast_context_destroy(NULL, registrar);
02164 return 0;
02165 }
02166
02167 static int pbx_load_config(const char *config_file)
02168 {
02169 struct ast_config *cfg;
02170 char *end;
02171 char *label;
02172 char realvalue[256];
02173 int lastpri = -2;
02174 struct ast_context *con;
02175 struct ast_variable *v;
02176 const char *cxt;
02177 const char *aft;
02178
02179 cfg = ast_config_load(config_file);
02180 if (!cfg)
02181 return 0;
02182
02183
02184 static_config = ast_true(ast_variable_retrieve(cfg, "general", "static"));
02185 write_protect_config = ast_true(ast_variable_retrieve(cfg, "general", "writeprotect"));
02186 if ((aft = ast_variable_retrieve(cfg, "general", "autofallthrough")))
02187 autofallthrough_config = ast_true(aft);
02188 clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
02189 ast_set2_flag(&ast_options, ast_true(ast_variable_retrieve(cfg, "general", "priorityjumping")), AST_OPT_FLAG_PRIORITY_JUMPING);
02190
02191 if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))
02192 ast_copy_string(userscontext, cxt, sizeof(userscontext));
02193 else
02194 ast_copy_string(userscontext, "default", sizeof(userscontext));
02195
02196 for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) {
02197 memset(realvalue, 0, sizeof(realvalue));
02198 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
02199 pbx_builtin_setvar_helper(NULL, v->name, realvalue);
02200 }
02201 for (cxt = NULL; (cxt = ast_category_browse(cfg, cxt)); ) {
02202
02203 if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals"))
02204 continue;
02205 con=ast_context_find_or_create(&local_contexts,cxt, registrar);
02206 if (con == NULL)
02207 continue;
02208
02209 for (v = ast_variable_browse(cfg, cxt); v; v = v->next) {
02210 if (!strcasecmp(v->name, "exten")) {
02211 char *tc = ast_strdup(v->value);
02212 if (tc) {
02213 int ipri = -2;
02214 char realext[256]="";
02215 char *plus, *firstp, *firstc;
02216 char *pri, *appl, *data, *cidmatch;
02217 char *stringp = tc;
02218 char *ext = strsep(&stringp, ",");
02219 if (!ext)
02220 ext="";
02221 pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
02222 cidmatch = strchr(realext, '/');
02223 if (cidmatch) {
02224 *cidmatch++ = '\0';
02225 ast_shrink_phone_number(cidmatch);
02226 }
02227 pri = strsep(&stringp, ",");
02228 if (!pri)
02229 pri="";
02230 label = strchr(pri, '(');
02231 if (label) {
02232 *label++ = '\0';
02233 end = strchr(label, ')');
02234 if (end)
02235 *end = '\0';
02236 else
02237 ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno);
02238 }
02239 plus = strchr(pri, '+');
02240 if (plus)
02241 *plus++ = '\0';
02242 if (!strcmp(pri,"hint"))
02243 ipri=PRIORITY_HINT;
02244 else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
02245 if (lastpri > -2)
02246 ipri = lastpri + 1;
02247 else
02248 ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
02249 } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
02250 if (lastpri > -2)
02251 ipri = lastpri;
02252 else
02253 ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
02254 } else if (sscanf(pri, "%d", &ipri) != 1 &&
02255 (ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
02256 ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
02257 ipri = 0;
02258 }
02259 appl = S_OR(stringp, "");
02260
02261 firstc = strchr(appl, ',');
02262 firstp = strchr(appl, '(');
02263 if (firstc && (!firstp || firstc < firstp)) {
02264
02265
02266 appl = strsep(&stringp, ",");
02267 data = stringp;
02268 } else if (!firstc && !firstp) {
02269
02270 data = "";
02271 } else {
02272
02273 appl = strsep(&stringp, "(");
02274 data = stringp;
02275 end = strrchr(data, ')');
02276 if ((end = strrchr(data, ')'))) {
02277 *end = '\0';
02278 } else {
02279 ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
02280 }
02281 ast_process_quotes_and_slashes(data, ',', '|');
02282 }
02283
02284 if (!data)
02285 data="";
02286 appl = ast_skip_blanks(appl);
02287 if (ipri) {
02288 if (plus)
02289 ipri += atoi(plus);
02290 lastpri = ipri;
02291 if (!ast_opt_dont_warn && !strcmp(realext, "_."))
02292 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);
02293 if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), ast_free, registrar)) {
02294 ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
02295 }
02296 }
02297 free(tc);
02298 }
02299 } else if (!strcasecmp(v->name, "include")) {
02300 memset(realvalue, 0, sizeof(realvalue));
02301 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
02302 if (ast_context_add_include2(con, realvalue, registrar))
02303 ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
02304 } else if (!strcasecmp(v->name, "ignorepat")) {
02305 memset(realvalue, 0, sizeof(realvalue));
02306 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
02307 if (ast_context_add_ignorepat2(con, realvalue, registrar))
02308 ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
02309 } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
02310 char *stringp= realvalue;
02311 char *appl, *data;
02312
02313 memset(realvalue, 0, sizeof(realvalue));
02314 if (!strcasecmp(v->name, "switch"))
02315 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
02316 else
02317 ast_copy_string(realvalue, v->value, sizeof(realvalue));
02318 appl = strsep(&stringp, "/");
02319 data = strsep(&stringp, "");
02320 if (!data)
02321 data = "";
02322 if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar))
02323 ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
02324 }
02325 }
02326 }
02327 ast_config_destroy(cfg);
02328 return 1;
02329 }
02330
02331 static void append_interface(char *iface, int maxlen, char *add)
02332 {
02333 int len = strlen(iface);
02334 if (strlen(add) + len < maxlen - 2) {
02335 if (strlen(iface)) {
02336 iface[len] = '&';
02337 strcpy(iface + len + 1, add);
02338 } else
02339 strcpy(iface, add);
02340 }
02341 }
02342
02343 static void pbx_load_users(void)
02344 {
02345 struct ast_config *cfg;
02346 char *cat, *chan;
02347 const char *zapchan;
02348 const char *hasexten;
02349 char tmp[256];
02350 char iface[256];
02351 char zapcopy[256];
02352 char *c;
02353 int len;
02354 int hasvoicemail;
02355 int start, finish, x;
02356 struct ast_context *con;
02357
02358 cfg = ast_config_load("users.conf");
02359 if (!cfg)
02360 return;
02361 con = ast_context_find_or_create(&local_contexts, userscontext, registrar);
02362 if (!con)
02363 return;
02364
02365 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
02366 if (!strcasecmp(cat, "general"))
02367 continue;
02368 iface[0] = '\0';
02369 len = sizeof(iface);
02370 if (ast_true(ast_config_option(cfg, cat, "hassip"))) {
02371 snprintf(tmp, sizeof(tmp), "SIP/%s", cat);
02372 append_interface(iface, sizeof(iface), tmp);
02373 }
02374 if (ast_true(ast_config_option(cfg, cat, "hasiax"))) {
02375 snprintf(tmp, sizeof(tmp), "IAX2/%s", cat);
02376 append_interface(iface, sizeof(iface), tmp);
02377 }
02378 if (ast_true(ast_config_option(cfg, cat, "hash323"))) {
02379 snprintf(tmp, sizeof(tmp), "H323/%s", cat);
02380 append_interface(iface, sizeof(iface), tmp);
02381 }
02382 hasexten = ast_config_option(cfg, cat, "hasexten");
02383 if (hasexten && !ast_true(hasexten))
02384 continue;
02385 hasvoicemail = ast_true(ast_config_option(cfg, cat, "hasvoicemail"));
02386 zapchan = ast_variable_retrieve(cfg, cat, "zapchan");
02387 if (!zapchan)
02388 zapchan = ast_variable_retrieve(cfg, "general", "zapchan");
02389 if (!ast_strlen_zero(zapchan)) {
02390 ast_copy_string(zapcopy, zapchan, sizeof(zapcopy));
02391 c = zapcopy;
02392 chan = strsep(&c, ",");
02393 while (chan) {
02394 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
02395
02396 } else if (sscanf(chan, "%d", &start)) {
02397
02398 finish = start;
02399 } else {
02400 start = 0; finish = 0;
02401 }
02402 if (finish < start) {
02403 x = finish;
02404 finish = start;
02405 start = x;
02406 }
02407 for (x = start; x <= finish; x++) {
02408 snprintf(tmp, sizeof(tmp), "Zap/%d", x);
02409 append_interface(iface, sizeof(iface), tmp);
02410 }
02411 chan = strsep(&c, ",");
02412 }
02413 }
02414 if (!ast_strlen_zero(iface)) {
02415
02416 ast_add_extension2(con, 0, cat, -1, NULL, NULL, iface, NULL, NULL, registrar);
02417
02418 if (hasvoicemail) {
02419 snprintf(tmp, sizeof(tmp), "stdexten|%s|${HINT}", cat);
02420 ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Macro", strdup(tmp), ast_free, registrar);
02421 } else {
02422 ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Dial", strdup("${HINT}"), ast_free, registrar);
02423 }
02424 }
02425 }
02426 ast_config_destroy(cfg);
02427 }
02428
02429 static int pbx_load_module(void)
02430 {
02431 struct ast_context *con;
02432
02433 if(!pbx_load_config(config))
02434 return AST_MODULE_LOAD_DECLINE;
02435
02436 pbx_load_users();
02437
02438 ast_merge_contexts_and_delete(&local_contexts, registrar);
02439
02440 for (con = NULL; (con = ast_walk_contexts(con));)
02441 ast_context_verify_includes(con);
02442
02443 pbx_set_autofallthrough(autofallthrough_config);
02444
02445 return 0;
02446 }
02447
02448 static int load_module(void)
02449 {
02450 if (pbx_load_module())
02451 return AST_MODULE_LOAD_DECLINE;
02452
02453 if (static_config && !write_protect_config)
02454 ast_cli_register(&cli_dialplan_save);
02455 ast_cli_register_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry));
02456
02457 return 0;
02458 }
02459
02460 static int reload(void)
02461 {
02462 if (clearglobalvars_config)
02463 pbx_builtin_clear_globals();
02464 pbx_load_module();
02465 return 0;
02466 }
02467
02468 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Text Extension Configuration",
02469 .load = load_module,
02470 .unload = unload_module,
02471 .reload = reload,
02472 );