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 <sys/types.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <ctype.h>
00031 #include <errno.h>
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 37417 $")
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 #ifdef __AST_DEBUG_MALLOC
00046 static void FREE(void *ptr)
00047 {
00048 free(ptr);
00049 }
00050 #else
00051 #define FREE free
00052 #endif
00053
00054 static char *dtext = "Text Extension Configuration";
00055 static char *config = "extensions.conf";
00056 static char *registrar = "pbx_config";
00057
00058 static int static_config = 0;
00059 static int write_protect_config = 1;
00060 static int autofallthrough_config = 0;
00061 static int clearglobalvars_config = 0;
00062
00063 AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
00064
00065 static struct ast_context *local_contexts = NULL;
00066
00067
00068
00069
00070 static char context_dont_include_help[] =
00071 "Usage: dont include <context> in <context>\n"
00072 " Remove an included context from another context.\n";
00073
00074 static char context_remove_extension_help[] =
00075 "Usage: remove extension exten@context [priority]\n"
00076 " Remove an extension from a given context. If a priority\n"
00077 " is given, only that specific priority from the given extension\n"
00078 " will be removed.\n";
00079
00080 static char context_add_include_help[] =
00081 "Usage: include <context> in <context>\n"
00082 " Include a context in another context.\n";
00083
00084 static char save_dialplan_help[] =
00085 "Usage: save dialplan [/path/to/extension/file]\n"
00086 " Save dialplan created by pbx_config module.\n"
00087 "\n"
00088 "Example: save dialplan (/etc/asterisk/extensions.conf)\n"
00089 " save dialplan /home/markster (/home/markster/extensions.conf)\n";
00090
00091 static char context_add_extension_help[] =
00092 "Usage: add extension <exten>,<priority>,<app>,<app-data> into <context>\n"
00093 " [replace]\n\n"
00094 " This command will add new extension into <context>. If there is an\n"
00095 " existence of extension with the same priority and last 'replace'\n"
00096 " arguments is given here we simply replace this extension.\n"
00097 "\n"
00098 "Example: add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n"
00099 " Now, you can dial 6123 and talk to Markster :)\n";
00100
00101 static char context_add_ignorepat_help[] =
00102 "Usage: add ignorepat <pattern> into <context>\n"
00103 " This command adds a new ignore pattern into context <context>\n"
00104 "\n"
00105 "Example: add ignorepat _3XX into local\n";
00106
00107 static char context_remove_ignorepat_help[] =
00108 "Usage: remove ignorepat <pattern> from <context>\n"
00109 " This command removes an ignore pattern from context <context>\n"
00110 "\n"
00111 "Example: remove ignorepat _3XX from local\n";
00112
00113 static char reload_extensions_help[] =
00114 "Usage: reload extensions.conf without reloading any other modules\n"
00115 " This command does not delete global variables unless\n"
00116 " clearglobalvars is set to yes in extensions.conf\n"
00117 "\n"
00118 "Example: extensions reload\n";
00119
00120
00121
00122
00123
00124
00125
00126
00127 static int handle_context_dont_include(int fd, int argc, char *argv[])
00128 {
00129 if (argc != 5)
00130 return RESULT_SHOWUSAGE;
00131
00132 if (strcmp(argv[3], "in"))
00133 return RESULT_SHOWUSAGE;
00134
00135 if (!ast_context_remove_include(argv[4], argv[2], registrar)) {
00136 ast_cli(fd, "We are not including '%s' in '%s' now\n",
00137 argv[2], argv[4]);
00138 return RESULT_SUCCESS;
00139 }
00140
00141 ast_cli(fd, "Failed to remove '%s' include from '%s' context\n",
00142 argv[2], argv[4]);
00143 return RESULT_FAILURE;
00144 }
00145
00146 static char *complete_context_dont_include(char *line, char *word,
00147 int pos, int state)
00148 {
00149 int which = 0;
00150
00151
00152
00153
00154 if (pos == 2) {
00155 struct ast_context *c;
00156
00157 if (ast_lock_contexts()) {
00158 ast_log(LOG_ERROR, "Failed to lock context list\n");
00159 return NULL;
00160 }
00161
00162
00163 c = ast_walk_contexts(NULL);
00164 while (c) {
00165 struct ast_include *i;
00166
00167 if (ast_lock_context(c)) {
00168 c = ast_walk_contexts(c);
00169 continue;
00170 }
00171
00172 i = ast_walk_context_includes(c, NULL);
00173 while (i) {
00174 if (!strlen(word) ||
00175 !strncmp(ast_get_include_name(i), word, strlen(word))) {
00176 struct ast_context *nc;
00177 int already_served = 0;
00178
00179
00180
00181
00182
00183
00184 nc = ast_walk_contexts(NULL);
00185 while (nc && nc != c && !already_served) {
00186 if (!ast_lock_context(nc)) {
00187 struct ast_include *ni;
00188
00189 ni = ast_walk_context_includes(nc, NULL);
00190 while (ni && !already_served) {
00191 if (!strcmp(ast_get_include_name(i),
00192 ast_get_include_name(ni)))
00193 already_served = 1;
00194 ni = ast_walk_context_includes(nc, ni);
00195 }
00196
00197 ast_unlock_context(nc);
00198 }
00199 nc = ast_walk_contexts(nc);
00200 }
00201
00202 if (!already_served) {
00203 if (++which > state) {
00204 char *res =
00205 strdup(ast_get_include_name(i));
00206 ast_unlock_context(c);
00207 ast_unlock_contexts();
00208 return res;
00209 }
00210 }
00211 }
00212 i = ast_walk_context_includes(c, i);
00213 }
00214
00215 ast_unlock_context(c);
00216 c = ast_walk_contexts(c);
00217 }
00218
00219 ast_unlock_contexts();
00220 return NULL;
00221 }
00222
00223
00224
00225
00226
00227 if (pos == 3) {
00228 struct ast_context *c;
00229 char *context, *dupline, *duplinet;
00230
00231 if (state > 0) return NULL;
00232
00233
00234 if (!(dupline = strdup(line))) {
00235 ast_log(LOG_ERROR, "Out of free memory\n");
00236 return NULL;
00237 }
00238
00239 duplinet = dupline;
00240 strsep(&duplinet, " ");
00241 strsep(&duplinet, " ");
00242 context = strsep(&duplinet, " ");
00243
00244 if (!context) {
00245 free(dupline);
00246 return NULL;
00247 }
00248
00249 if (ast_lock_contexts()) {
00250 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
00251 free(dupline);
00252 return NULL;
00253 }
00254
00255
00256 c = ast_walk_contexts(NULL);
00257 while (c) {
00258 struct ast_include *i;
00259 if (ast_lock_context(c)) {
00260 free(dupline);
00261 ast_unlock_contexts();
00262 return NULL;
00263 }
00264
00265 i = ast_walk_context_includes(c, NULL);
00266 while (i) {
00267
00268 if (!strcmp(ast_get_include_name(i), context)) {
00269
00270
00271
00272 free(dupline);
00273 ast_unlock_context(c);
00274 ast_unlock_contexts();
00275 return strdup("in");
00276 }
00277 i = ast_walk_context_includes(c, i);
00278 }
00279 ast_unlock_context(c);
00280 c = ast_walk_contexts(c);
00281 }
00282 free(dupline);
00283 ast_unlock_contexts();
00284 return NULL;
00285 }
00286
00287
00288
00289
00290 if (pos == 4) {
00291 struct ast_context *c;
00292 char *context, *dupline, *duplinet, *in;
00293
00294 if (!(dupline = strdup(line))) {
00295 ast_log(LOG_ERROR, "Out of free memory\n");
00296 return NULL;
00297 }
00298
00299 duplinet = dupline;
00300
00301 strsep(&duplinet, " ");
00302 strsep(&duplinet, " ");
00303
00304 if (!(context = strsep(&duplinet, " "))) {
00305 free(dupline);
00306 return NULL;
00307 }
00308
00309
00310 in = strsep(&duplinet, " ");
00311 if (!in ||
00312 strcmp(in, "in")) {
00313 free(dupline);
00314 return NULL;
00315 }
00316
00317 if (ast_lock_contexts()) {
00318 ast_log(LOG_ERROR, "Failed to lock context list\n");
00319 free(dupline);
00320 return NULL;
00321 }
00322
00323
00324 c = ast_walk_contexts(NULL);
00325 while (c) {
00326 struct ast_include *i;
00327 if (ast_lock_context(c)) {
00328 free(dupline);
00329 return NULL;
00330 }
00331
00332
00333 i = ast_walk_context_includes(c, NULL);
00334 while (i) {
00335
00336
00337
00338 if (!strcmp(context, ast_get_include_name(i))) {
00339
00340 if (!strncmp(ast_get_context_name(c),
00341 word, strlen(word))) {
00342
00343 if (++which > state) {
00344 char *res = strdup(ast_get_context_name(c));
00345 free(dupline);
00346 ast_unlock_context(c);
00347 ast_unlock_contexts();
00348 return res;
00349 }
00350 }
00351 break;
00352 }
00353 i = ast_walk_context_includes(c, i);
00354 }
00355 ast_unlock_context(c);
00356 c = ast_walk_contexts(c);
00357 }
00358
00359 free(dupline);
00360 ast_unlock_contexts();
00361 return NULL;
00362 }
00363
00364 return NULL;
00365 }
00366
00367
00368
00369
00370 static int handle_context_remove_extension(int fd, int argc, char *argv[])
00371 {
00372 int removing_priority = 0;
00373 char *exten, *context;
00374
00375 if (argc != 4 && argc != 3) return RESULT_SHOWUSAGE;
00376
00377
00378
00379
00380 if (argc == 4) {
00381 char *c = argv[3];
00382
00383
00384
00385
00386
00387 if (strcmp("hint", c)) {
00388 while (*c != '\0') {
00389 if (!isdigit(*c++)) {
00390 ast_cli(fd, "Invalid priority '%s'\n", argv[3]);
00391 return RESULT_FAILURE;
00392 }
00393 }
00394 removing_priority = atoi(argv[3]);
00395 } else
00396 removing_priority = PRIORITY_HINT;
00397
00398 if (removing_priority == 0) {
00399 ast_cli(fd, "If you want to remove whole extension, please " \
00400 "omit priority argument\n");
00401 return RESULT_FAILURE;
00402 }
00403 }
00404
00405
00406
00407
00408 if (!(context = strchr(argv[2], (int)'@'))) {
00409 ast_cli(fd, "First argument must be in exten@context format\n");
00410 return RESULT_FAILURE;
00411 }
00412
00413 *context++ = '\0';
00414 exten = argv[2];
00415 if ((!strlen(exten)) || (!(strlen(context)))) {
00416 ast_cli(fd, "Missing extension or context name in second argument '%s@%s'\n",
00417 exten == NULL ? "?" : exten, context == NULL ? "?" : context);
00418 return RESULT_FAILURE;
00419 }
00420
00421 if (!ast_context_remove_extension(context, exten, removing_priority, registrar)) {
00422 if (!removing_priority)
00423 ast_cli(fd, "Whole extension %s@%s removed\n",
00424 exten, context);
00425 else
00426 ast_cli(fd, "Extension %s@%s with priority %d removed\n",
00427 exten, context, removing_priority);
00428
00429 return RESULT_SUCCESS;
00430 }
00431
00432 ast_cli(fd, "Failed to remove extension %s@%s\n", exten, context);
00433
00434 return RESULT_FAILURE;
00435 }
00436
00437 #define BROKEN_READLINE 1
00438
00439 #ifdef BROKEN_READLINE
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 static int fix_complete_args(char *line, char **word, int *pos)
00453 {
00454 char *_line, *_strsep_line, *_previous_word = NULL, *_word = NULL;
00455 int words = 0;
00456
00457 _line = strdup(line);
00458
00459 _strsep_line = _line;
00460 while (_strsep_line) {
00461 _previous_word = _word;
00462 _word = strsep(&_strsep_line, " ");
00463
00464 if (_word && strlen(_word)) words++;
00465 }
00466
00467
00468 if (_word || _previous_word) {
00469 if (_word) {
00470 if (!strlen(_word)) words++;
00471 *word = strdup(_word);
00472 } else
00473 *word = strdup(_previous_word);
00474 *pos = words - 1;
00475 free(_line);
00476 return 0;
00477 }
00478
00479 free(_line);
00480 return -1;
00481 }
00482 #endif
00483
00484 static char *complete_context_remove_extension(char *line, char *word, int pos,
00485 int state)
00486 {
00487 char *ret = NULL;
00488 int which = 0;
00489
00490 #ifdef BROKEN_READLINE
00491
00492
00493
00494
00495 if (fix_complete_args(line, &word, &pos)) {
00496 ast_log(LOG_ERROR, "Out of free memory\n");
00497 return NULL;
00498 }
00499 #endif
00500
00501
00502
00503
00504 if (pos == 2) {
00505 struct ast_context *c;
00506 struct ast_exten *e;
00507 char *context = NULL, *exten = NULL, *delim = NULL;
00508
00509
00510 if ((delim = strchr(word, (int)'@'))) {
00511
00512 if (delim != strrchr(word, (int)'@')) {
00513 #ifdef BROKEN_READLINE
00514 free(word);
00515 #endif
00516 return NULL;
00517 }
00518
00519 *delim = '\0';
00520 exten = strdup(word);
00521 context = strdup(delim + 1);
00522 *delim = '@';
00523 } else {
00524 exten = strdup(word);
00525 }
00526 #ifdef BROKEN_READLINE
00527 free(word);
00528 #endif
00529
00530 if (ast_lock_contexts()) {
00531 ast_log(LOG_ERROR, "Failed to lock context list\n");
00532 free(context); free(exten);
00533 return NULL;
00534 }
00535
00536
00537 c = ast_walk_contexts(NULL);
00538 while (c) {
00539
00540 if ( (!context || !strlen(context)) ||
00541 (context && !strncmp(ast_get_context_name(c),
00542 context, strlen(context))) ) {
00543
00544 e = ast_walk_context_extensions(c, NULL);
00545 while (e) {
00546
00547 if ( (!exten || !strlen(exten)) ||
00548 (exten && !strncmp(ast_get_extension_name(e), exten,
00549 strlen(exten))) ) {
00550 if (++which > state) {
00551
00552
00553
00554 if (exten) {
00555 ret = malloc(strlen(ast_get_extension_name(e)) +
00556 strlen(ast_get_context_name(c)) + 2);
00557 if (ret)
00558 sprintf(ret, "%s@%s", ast_get_extension_name(e),
00559 ast_get_context_name(c));
00560 }
00561 free(exten); free(context);
00562
00563 ast_unlock_contexts();
00564
00565 return ret;
00566 }
00567 }
00568 e = ast_walk_context_extensions(c, e);
00569 }
00570 }
00571 c = ast_walk_contexts(c);
00572 }
00573
00574 ast_unlock_contexts();
00575
00576 free(exten); free(context);
00577
00578 return NULL;
00579 }
00580
00581
00582
00583
00584 if (pos == 3) {
00585 char *delim, *exten, *context, *dupline, *duplinet, *ec;
00586 struct ast_context *c;
00587
00588 dupline = strdup(line);
00589 if (!dupline) {
00590 #ifdef BROKEN_READLINE
00591 free(word);
00592 #endif
00593 return NULL;
00594 }
00595 duplinet = dupline;
00596
00597 strsep(&duplinet, " ");
00598 strsep(&duplinet, " ");
00599
00600 if (!(ec = strsep(&duplinet, " "))) {
00601 free(dupline);
00602 #ifdef BROKEN_READLINE
00603 free(word);
00604 #endif
00605 return NULL;
00606 }
00607
00608
00609 if (!(delim = strchr(ec, (int)'@')) ||
00610 (strchr(ec, (int)'@') != strrchr(ec, (int)'@'))) {
00611 #ifdef BROKEN_READLINE
00612 free(word);
00613 #endif
00614 free(dupline);
00615 return NULL;
00616 }
00617
00618
00619 *delim = '\0';
00620 if ((!strlen(ec)) || (!strlen(delim + 1))) {
00621 #ifdef BROKEN_READLINE
00622 free(word);
00623 #endif
00624 free(dupline);
00625 return NULL;
00626 }
00627
00628 exten = strdup(ec);
00629 context = strdup(delim + 1);
00630 free(dupline);
00631
00632 if (ast_lock_contexts()) {
00633 ast_log(LOG_ERROR, "Failed to lock context list\n");
00634 #ifdef BROKEN_READLINE
00635 free(word);
00636 #endif
00637 free(exten); free(context);
00638 return NULL;
00639 }
00640
00641
00642 c = ast_walk_contexts(NULL);
00643 while (c) {
00644 if (!strcmp(ast_get_context_name(c), context)) {
00645 struct ast_exten *e;
00646
00647
00648 free(context);
00649 e = ast_walk_context_extensions(c, NULL);
00650 while (e) {
00651 if (!strcmp(ast_get_extension_name(e), exten)) {
00652 struct ast_exten *priority;
00653 char buffer[10];
00654
00655 free(exten);
00656 priority = ast_walk_extension_priorities(e, NULL);
00657
00658 do {
00659 snprintf(buffer, 10, "%u",
00660 ast_get_extension_priority(priority));
00661 if (!strncmp(word, buffer, strlen(word))) {
00662 if (++which > state) {
00663 #ifdef BROKEN_READLINE
00664 free(word);
00665 #endif
00666 ast_unlock_contexts();
00667 return strdup(buffer);
00668 }
00669 }
00670 priority = ast_walk_extension_priorities(e,
00671 priority);
00672 } while (priority);
00673
00674 #ifdef BROKEN_READLINE
00675 free(word);
00676 #endif
00677 ast_unlock_contexts();
00678 return NULL;
00679 }
00680 e = ast_walk_context_extensions(c, e);
00681 }
00682 #ifdef BROKEN_READLINE
00683 free(word);
00684 #endif
00685 free(exten);
00686 ast_unlock_contexts();
00687 return NULL;
00688 }
00689 c = ast_walk_contexts(c);
00690 }
00691
00692 #ifdef BROKEN_READLINE
00693 free(word);
00694 #endif
00695 free(exten); free(context);
00696
00697 ast_unlock_contexts();
00698 return NULL;
00699 }
00700
00701 #ifdef BROKEN_READLINE
00702 free(word);
00703 #endif
00704 return NULL;
00705 }
00706
00707
00708
00709
00710 static int handle_context_add_include(int fd, int argc, char *argv[])
00711 {
00712 if (argc != 5) return RESULT_SHOWUSAGE;
00713
00714
00715 if (strcmp(argv[3], "in") && strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
00716
00717 if (ast_context_add_include(argv[4], argv[2], registrar)) {
00718 switch (errno) {
00719 case ENOMEM:
00720 ast_cli(fd, "Out of memory for context addition\n"); break;
00721
00722 case EBUSY:
00723 ast_cli(fd, "Failed to lock context(s) list, please try again later\n"); break;
00724
00725 case EEXIST:
00726 ast_cli(fd, "Context '%s' already included in '%s' context\n",
00727 argv[2], argv[4]); break;
00728
00729 case ENOENT:
00730 case EINVAL:
00731 ast_cli(fd, "There is no existence of context '%s'\n",
00732 errno == ENOENT ? argv[4] : argv[2]); break;
00733
00734 default:
00735 ast_cli(fd, "Failed to include '%s' in '%s' context\n",
00736 argv[2], argv[4]); break;
00737 }
00738 return RESULT_FAILURE;
00739 }
00740
00741
00742 ast_cli(fd, "Context '%s' included in '%s' context\n",
00743 argv[2], argv[4]);
00744
00745 return RESULT_SUCCESS;
00746 }
00747
00748 static char *complete_context_add_include(char *line, char *word, int pos,
00749 int state)
00750 {
00751 struct ast_context *c;
00752 int which = 0;
00753
00754
00755 if (pos == 1)
00756 {
00757 if (ast_lock_contexts()) {
00758 ast_log(LOG_ERROR, "Failed to lock context list\n");
00759 return NULL;
00760 }
00761
00762
00763 c = ast_walk_contexts(NULL);
00764 while (c) {
00765 if ((!strlen(word) ||
00766 !strncmp(ast_get_context_name(c), word, strlen(word))) &&
00767 ++which > state)
00768 {
00769 char *context = strdup(ast_get_context_name(c));
00770 ast_unlock_contexts();
00771 return context;
00772 }
00773 c = ast_walk_contexts(c);
00774 }
00775
00776 ast_unlock_contexts();
00777 }
00778
00779
00780 if (pos == 2)
00781 {
00782 char *context, *dupline, *duplinet;
00783
00784 if (state != 0) return NULL;
00785
00786
00787 if (!(dupline = strdup(line))) {
00788 ast_log(LOG_ERROR, "Out of free memory\n");
00789 if (state == 0) return strdup("in");
00790 return NULL;
00791 }
00792
00793 duplinet = dupline;
00794
00795 strsep(&duplinet, " ");
00796 context = strsep(&duplinet, " ");
00797 if (context) {
00798 struct ast_context *c;
00799 int context_existence = 0;
00800
00801
00802 if (ast_lock_contexts()) {
00803 ast_log(LOG_ERROR, "Failed to lock context list\n");
00804 free(dupline);
00805
00806 return strdup("in");
00807 }
00808
00809 c = ast_walk_contexts(NULL);
00810 while (c && !context_existence) {
00811 if (!strcmp(context, ast_get_context_name(c))) {
00812 context_existence = 1;
00813 continue;
00814 }
00815 c = ast_walk_contexts(c);
00816 }
00817
00818
00819 if (context_existence) {
00820 free(dupline);
00821 ast_unlock_contexts();
00822 return strdup("into");
00823 }
00824
00825 ast_unlock_contexts();
00826 }
00827
00828 free(dupline);
00829 return NULL;
00830 }
00831
00832
00833 if (pos == 3)
00834 {
00835 char *context, *dupline, *duplinet, *in;
00836 int context_existence = 0;
00837
00838 if (!(dupline = strdup(line))) {
00839 ast_log(LOG_ERROR, "Out of free memory\n");
00840 return NULL;
00841 }
00842
00843 duplinet = dupline;
00844
00845 strsep(&duplinet, " ");
00846 context = strsep(&duplinet, " ");
00847 in = strsep(&duplinet, " ");
00848
00849
00850 if (!strlen(context) || strcmp(in, "in")) {
00851 free(dupline);
00852 return NULL;
00853 }
00854
00855 if (ast_lock_contexts()) {
00856 ast_log(LOG_ERROR, "Failed to lock context list\n");
00857 free(dupline);
00858 return NULL;
00859 }
00860
00861
00862 c = ast_walk_contexts(NULL);
00863 while (c && !context_existence) {
00864 if (!strcmp(context, ast_get_context_name(c))) {
00865 context_existence = 1;
00866 continue;
00867 }
00868 c = ast_walk_contexts(c);
00869 }
00870
00871 if (!context_existence) {
00872 free(dupline);
00873 ast_unlock_contexts();
00874 return NULL;
00875 }
00876
00877
00878 c = ast_walk_contexts(NULL);
00879 while (c) {
00880
00881 if (strcmp(context, ast_get_context_name(c))) {
00882 if (!ast_lock_context(c)) {
00883 struct ast_include *i;
00884 int included = 0;
00885
00886
00887 i = ast_walk_context_includes(c, NULL);
00888 while (i && !included) {
00889 if (!strcmp(ast_get_include_name(i), context))
00890 included = 1;
00891 i = ast_walk_context_includes(c, i);
00892 }
00893 ast_unlock_context(c);
00894
00895
00896 if (!included &&
00897 !strncmp(ast_get_context_name(c), word, strlen(word))){
00898
00899 if (++which > state) {
00900 char *res = strdup(ast_get_context_name(c));
00901 free(dupline);
00902 ast_unlock_contexts();
00903 return res;
00904 }
00905 }
00906 }
00907 }
00908 c = ast_walk_contexts(c);
00909 }
00910
00911 ast_unlock_contexts();
00912 free(dupline);
00913 return NULL;
00914 }
00915
00916 return NULL;
00917 }
00918
00919
00920
00921
00922 static int handle_save_dialplan(int fd, int argc, char *argv[])
00923 {
00924 char filename[256];
00925 struct ast_context *c;
00926 struct ast_config *cfg;
00927 struct ast_variable *v;
00928 int context_header_written;
00929 int incomplete = 0;
00930 FILE *output;
00931
00932 if (! (static_config && !write_protect_config)) {
00933 ast_cli(fd,
00934 "I can't save dialplan now, see '%s' example file.\n",
00935 config);
00936 return RESULT_FAILURE;
00937 }
00938
00939 if (argc != 2 && argc != 3) return RESULT_SHOWUSAGE;
00940
00941 if (ast_mutex_lock(&save_dialplan_lock)) {
00942 ast_cli(fd,
00943 "Failed to lock dialplan saving (another proccess saving?)\n");
00944 return RESULT_FAILURE;
00945 }
00946
00947
00948 if (argc == 3) {
00949
00950 if (!strstr(argv[2], ".conf")) {
00951
00952 if (*(argv[2] + strlen(argv[2]) -1) == '/')
00953 snprintf(filename, sizeof(filename), "%s%s",
00954 argv[2], config);
00955 else
00956
00957 snprintf(filename, sizeof(filename), "%s/%s",
00958 argv[2], config);
00959 } else
00960
00961 snprintf(filename, sizeof(filename), argv[2]);
00962 } else
00963
00964 snprintf(filename, sizeof(filename), "%s/%s",
00965 (char *)ast_config_AST_CONFIG_DIR, config);
00966
00967 cfg = ast_config_load("extensions.conf");
00968
00969
00970 if (ast_lock_contexts()) {
00971 ast_cli(fd, "Failed to lock contexts list\n");
00972 ast_mutex_unlock(&save_dialplan_lock);
00973 ast_config_destroy(cfg);
00974 return RESULT_FAILURE;
00975 }
00976
00977
00978 if (!(output = fopen(filename, "wt"))) {
00979 ast_cli(fd, "Failed to create file '%s'\n",
00980 filename);
00981 ast_unlock_contexts();
00982 ast_mutex_unlock(&save_dialplan_lock);
00983 ast_config_destroy(cfg);
00984 return RESULT_FAILURE;
00985 }
00986
00987
00988 fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\n\n",
00989 static_config ? "yes" : "no",
00990 write_protect_config ? "yes" : "no");
00991
00992 if ((v = ast_variable_browse(cfg, "globals"))) {
00993 fprintf(output, "[globals]\n");
00994 while(v) {
00995 fprintf(output, "%s => %s\n", v->name, v->value);
00996 v = v->next;
00997 }
00998 fprintf(output, "\n");
00999 }
01000
01001 ast_config_destroy(cfg);
01002
01003
01004 c = ast_walk_contexts(NULL);
01005 while (c) {
01006 context_header_written = 0;
01007
01008
01009 if (!ast_lock_context(c)) {
01010 struct ast_exten *e, *last_written_e = NULL;
01011 struct ast_include *i;
01012 struct ast_ignorepat *ip;
01013 struct ast_sw *sw;
01014
01015
01016 if (!strcmp(ast_get_context_registrar(c), registrar)) {
01017 fprintf(output, "[%s]\n", ast_get_context_name(c));
01018 context_header_written = 1;
01019 }
01020
01021
01022 e = ast_walk_context_extensions(c, NULL);
01023 while (e) {
01024 struct ast_exten *p;
01025
01026
01027 p = ast_walk_extension_priorities(e, NULL);
01028 while (p) {
01029 if (!strcmp(ast_get_extension_registrar(p),
01030 registrar)) {
01031
01032
01033 if (last_written_e != NULL &&
01034 strcmp(ast_get_extension_name(last_written_e),
01035 ast_get_extension_name(p)))
01036 fprintf(output, "\n");
01037 last_written_e = p;
01038
01039 if (!context_header_written) {
01040 fprintf(output, "[%s]\n", ast_get_context_name(c));
01041 context_header_written = 1;
01042 }
01043
01044 if (ast_get_extension_priority(p)!=PRIORITY_HINT) {
01045 char *tempdata = NULL, *startdata;
01046 tempdata = strdup((char *)ast_get_extension_app_data(p));
01047 if (tempdata) {
01048 startdata = tempdata;
01049 while (*tempdata) {
01050 if (*tempdata == '|')
01051 *tempdata = ',';
01052 tempdata++;
01053 }
01054 tempdata = startdata;
01055 }
01056 if (ast_get_extension_matchcid(p))
01057 fprintf(output, "exten => %s/%s,%d,%s(%s)\n",
01058 ast_get_extension_name(p),
01059 ast_get_extension_cidmatch(p),
01060 ast_get_extension_priority(p),
01061 ast_get_extension_app(p),
01062 tempdata);
01063 else
01064 fprintf(output, "exten => %s,%d,%s(%s)\n",
01065 ast_get_extension_name(p),
01066 ast_get_extension_priority(p),
01067 ast_get_extension_app(p),
01068 tempdata);
01069 if (tempdata)
01070 free(tempdata);
01071 } else
01072 fprintf(output, "exten => %s,hint,%s\n",
01073 ast_get_extension_name(p),
01074 ast_get_extension_app(p));
01075
01076 }
01077 p = ast_walk_extension_priorities(e, p);
01078 }
01079
01080 e = ast_walk_context_extensions(c, e);
01081 }
01082
01083
01084 if (last_written_e) fprintf(output, "\n");
01085
01086
01087 i = ast_walk_context_includes(c, NULL);
01088 while (i) {
01089 if (!strcmp(ast_get_include_registrar(i), registrar)) {
01090 if (!context_header_written) {
01091 fprintf(output, "[%s]\n", ast_get_context_name(c));
01092 context_header_written = 1;
01093 }
01094 fprintf(output, "include => %s\n",
01095 ast_get_include_name(i));
01096 }
01097 i = ast_walk_context_includes(c, i);
01098 }
01099
01100 if (ast_walk_context_includes(c, NULL))
01101 fprintf(output, "\n");
01102
01103
01104 sw = ast_walk_context_switches(c, NULL);
01105 while (sw) {
01106 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
01107 if (!context_header_written) {
01108 fprintf(output, "[%s]\n", ast_get_context_name(c));
01109 context_header_written = 1;
01110 }
01111 fprintf(output, "switch => %s/%s\n",
01112 ast_get_switch_name(sw),
01113 ast_get_switch_data(sw));
01114 }
01115 sw = ast_walk_context_switches(c, sw);
01116 }
01117
01118 if (ast_walk_context_switches(c, NULL))
01119 fprintf(output, "\n");
01120
01121
01122 ip = ast_walk_context_ignorepats(c, NULL);
01123 while (ip) {
01124 if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
01125 if (!context_header_written) {
01126 fprintf(output, "[%s]\n", ast_get_context_name(c));
01127 context_header_written = 1;
01128 }
01129
01130 fprintf(output, "ignorepat => %s\n",
01131 ast_get_ignorepat_name(ip));
01132 }
01133 ip = ast_walk_context_ignorepats(c, ip);
01134 }
01135
01136 ast_unlock_context(c);
01137 } else
01138 incomplete = 1;
01139
01140 c = ast_walk_contexts(c);
01141 }
01142
01143 ast_unlock_contexts();
01144 ast_mutex_unlock(&save_dialplan_lock);
01145 fclose(output);
01146
01147 if (incomplete) {
01148 ast_cli(fd, "Saved dialplan is incomplete\n");
01149 return RESULT_FAILURE;
01150 }
01151
01152 ast_cli(fd, "Dialplan successfully saved into '%s'\n",
01153 filename);
01154 return RESULT_SUCCESS;
01155 }
01156
01157
01158
01159
01160 static int handle_context_add_extension(int fd, int argc, char *argv[])
01161 {
01162 char *whole_exten;
01163 char *exten, *prior;
01164 int iprior = -2;
01165 char *cidmatch, *app, *app_data;
01166 char *start, *end;
01167
01168
01169 if (argc != 5 && argc != 6) return RESULT_SHOWUSAGE;
01170 if (strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
01171 if (argc == 6) if (strcmp(argv[5], "replace")) return RESULT_SHOWUSAGE;
01172
01173 whole_exten = argv[2];
01174 exten = strsep(&whole_exten,",");
01175 if (strchr(exten, '/')) {
01176 cidmatch = exten;
01177 strsep(&cidmatch,"/");
01178 } else {
01179 cidmatch = NULL;
01180 }
01181 prior = strsep(&whole_exten,",");
01182 if (prior) {
01183 if (!strcmp(prior, "hint")) {
01184 iprior = PRIORITY_HINT;
01185 } else {
01186 if (sscanf(prior, "%d", &iprior) != 1) {
01187 ast_cli(fd, "'%s' is not a valid priority\n", prior);
01188 prior = NULL;
01189 }
01190 }
01191 }
01192 app = whole_exten;
01193 if (app && (start = strchr(app, '(')) && (end = strrchr(app, ')'))) {
01194 *start = *end = '\0';
01195 app_data = start + 1;
01196 ast_process_quotes_and_slashes(app_data, ',', '|');
01197 } else {
01198 if (app) {
01199 app_data = strchr(app, ',');
01200 if (app_data) {
01201 *app_data = '\0';
01202 app_data++;
01203 }
01204 } else
01205 app_data = NULL;
01206 }
01207
01208 if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT)) return RESULT_SHOWUSAGE;
01209
01210 if (!app_data)
01211 app_data="";
01212 if (ast_add_extension(argv[4], argc == 6 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
01213 (void *)strdup(app_data), free, registrar)) {
01214 switch (errno) {
01215 case ENOMEM:
01216 ast_cli(fd, "Out of free memory\n"); break;
01217
01218 case EBUSY:
01219 ast_cli(fd, "Failed to lock context(s) list, please try again later\n"); break;
01220
01221 case ENOENT:
01222 ast_cli(fd, "No existence of '%s' context\n", argv[4]); break;
01223
01224 case EEXIST:
01225 ast_cli(fd, "Extension %s@%s with priority %s already exists\n",
01226 exten, argv[4], prior); break;
01227
01228 default:
01229 ast_cli(fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
01230 exten, prior, app, app_data, argv[4]); break;
01231 }
01232 return RESULT_FAILURE;
01233 }
01234
01235 if (argc == 6)
01236 ast_cli(fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
01237 exten, argv[4], prior, exten, prior, app, app_data);
01238 else
01239 ast_cli(fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
01240 exten, prior, app, app_data, argv[4]);
01241
01242 return RESULT_SUCCESS;
01243 }
01244
01245
01246 static char *complete_context_add_extension(char *line, char *word,
01247 int pos, int state)
01248 {
01249 int which = 0;
01250
01251
01252 if (pos == 3) {
01253 if (state == 0) return strdup("into");
01254 return NULL;
01255 }
01256
01257
01258 if (pos == 4) {
01259 struct ast_context *c;
01260
01261
01262 if (ast_lock_contexts()) {
01263 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01264 return NULL;
01265 }
01266
01267
01268 c = ast_walk_contexts(NULL);
01269 while (c) {
01270
01271 if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
01272 if (++which > state) {
01273 char *res = strdup(ast_get_context_name(c));
01274 ast_unlock_contexts();
01275 return res;
01276 }
01277 }
01278 c = ast_walk_contexts(c);
01279 }
01280
01281 ast_unlock_contexts();
01282 return NULL;
01283 }
01284
01285 if (pos == 5) return state == 0 ? strdup("replace") : NULL;
01286
01287 return NULL;
01288 }
01289
01290
01291
01292
01293 static int handle_context_add_ignorepat(int fd, int argc, char *argv[])
01294 {
01295 if (argc != 5) return RESULT_SHOWUSAGE;
01296 if (strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
01297
01298 if (ast_context_add_ignorepat(argv[4], argv[2], registrar)) {
01299 switch (errno) {
01300 case ENOMEM:
01301 ast_cli(fd, "Out of free memory\n"); break;
01302
01303 case ENOENT:
01304 ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
01305 break;
01306
01307 case EEXIST:
01308 ast_cli(fd, "Ignore pattern '%s' already included in '%s' context\n",
01309 argv[2], argv[4]);
01310 break;
01311
01312 case EBUSY:
01313 ast_cli(fd, "Failed to lock context(s) list, please, try again later\n");
01314 break;
01315
01316 default:
01317 ast_cli(fd, "Failed to add ingore pattern '%s' into '%s' context\n",
01318 argv[2], argv[4]);
01319 break;
01320 }
01321 return RESULT_FAILURE;
01322 }
01323
01324 ast_cli(fd, "Ignore pattern '%s' added into '%s' context\n",
01325 argv[2], argv[4]);
01326 return RESULT_SUCCESS;
01327 }
01328
01329 static char *complete_context_add_ignorepat(char *line, char *word,
01330 int pos, int state)
01331 {
01332 if (pos == 3) return state == 0 ? strdup("into") : NULL;
01333
01334 if (pos == 4) {
01335 struct ast_context *c;
01336 int which = 0;
01337 char *dupline, *duplinet, *ignorepat = NULL;
01338
01339 dupline = strdup(line);
01340 duplinet = dupline;
01341
01342 if (duplinet) {
01343 strsep(&duplinet, " ");
01344 strsep(&duplinet, " ");
01345 ignorepat = strsep(&duplinet, " ");
01346 }
01347
01348 if (ast_lock_contexts()) {
01349 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
01350 return NULL;
01351 }
01352
01353 c = ast_walk_contexts(NULL);
01354 while (c) {
01355 if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
01356 int serve_context = 1;
01357 if (ignorepat) {
01358 if (!ast_lock_context(c)) {
01359 struct ast_ignorepat *ip;
01360 ip = ast_walk_context_ignorepats(c, NULL);
01361 while (ip && serve_context) {
01362 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat))
01363 serve_context = 0;
01364 ip = ast_walk_context_ignorepats(c, ip);
01365 }
01366 ast_unlock_context(c);
01367 }
01368 }
01369 if (serve_context) {
01370 if (++which > state) {
01371 char *context = strdup(ast_get_context_name(c));
01372 if (dupline) free(dupline);
01373 ast_unlock_contexts();
01374 return context;
01375 }
01376 }
01377 }
01378 c = ast_walk_contexts(c);
01379 }
01380
01381 if (dupline) free(dupline);
01382 ast_unlock_contexts();
01383 return NULL;
01384 }
01385
01386 return NULL;
01387 }
01388
01389 static int handle_context_remove_ignorepat(int fd, int argc, char *argv[])
01390 {
01391 if (argc != 5) return RESULT_SHOWUSAGE;
01392 if (strcmp(argv[3], "from")) return RESULT_SHOWUSAGE;
01393
01394 if (ast_context_remove_ignorepat(argv[4], argv[2], registrar)) {
01395 switch (errno) {
01396 case EBUSY:
01397 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
01398 break;
01399
01400 case ENOENT:
01401 ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
01402 break;
01403
01404 case EINVAL:
01405 ast_cli(fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
01406 argv[2], argv[4]);
01407 break;
01408
01409 default:
01410 ast_cli(fd, "Failed to remove ignore pattern '%s' from '%s' context\n", argv[2], argv[4]);
01411 break;
01412 }
01413 return RESULT_FAILURE;
01414 }
01415
01416 ast_cli(fd, "Ignore pattern '%s' removed from '%s' context\n",
01417 argv[2], argv[4]);
01418 return RESULT_SUCCESS;
01419 }
01420
01421 static int pbx_load_module(void);
01422
01423 static int handle_reload_extensions(int fd, int argc, char *argv[])
01424 {
01425 if (argc!=2) return RESULT_SHOWUSAGE;
01426 pbx_load_module();
01427 return RESULT_SUCCESS;
01428 }
01429
01430 static char *complete_context_remove_ignorepat(char *line, char *word,
01431 int pos, int state)
01432 {
01433 struct ast_context *c;
01434 int which = 0;
01435
01436 if (pos == 2) {
01437 if (ast_lock_contexts()) {
01438 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01439 return NULL;
01440 }
01441
01442 c = ast_walk_contexts(NULL);
01443 while (c) {
01444 if (!ast_lock_context(c)) {
01445 struct ast_ignorepat *ip;
01446
01447 ip = ast_walk_context_ignorepats(c, NULL);
01448 while (ip) {
01449 if (!strncmp(ast_get_ignorepat_name(ip), word, strlen(word))) {
01450 if (which + 1 > state) {
01451 struct ast_context *cw;
01452 int already_served = 0;
01453 cw = ast_walk_contexts(NULL);
01454 while (cw && cw != c && !already_served) {
01455 if (!ast_lock_context(cw)) {
01456 struct ast_ignorepat *ipw;
01457 ipw = ast_walk_context_ignorepats(cw, NULL);
01458 while (ipw) {
01459 if (!strcmp(ast_get_ignorepat_name(ipw),
01460 ast_get_ignorepat_name(ip))) already_served = 1;
01461 ipw = ast_walk_context_ignorepats(cw, ipw);
01462 }
01463 ast_unlock_context(cw);
01464 }
01465 cw = ast_walk_contexts(cw);
01466 }
01467 if (!already_served) {
01468 char *ret = strdup(ast_get_ignorepat_name(ip));
01469 ast_unlock_context(c);
01470 ast_unlock_contexts();
01471 return ret;
01472 }
01473 } else
01474 which++;
01475 }
01476 ip = ast_walk_context_ignorepats(c, ip);
01477 }
01478
01479 ast_unlock_context(c);
01480 }
01481 c = ast_walk_contexts(c);
01482 }
01483
01484 ast_unlock_contexts();
01485 return NULL;
01486 }
01487
01488 if (pos == 3) return state == 0 ? strdup("from") : NULL;
01489
01490 if (pos == 4) {
01491 char *dupline, *duplinet, *ignorepat;
01492
01493 dupline = strdup(line);
01494 if (!dupline) {
01495 ast_log(LOG_WARNING, "Out of free memory\n");
01496 return NULL;
01497 }
01498
01499 duplinet = dupline;
01500 strsep(&duplinet, " ");
01501 strsep(&duplinet, " ");
01502 ignorepat = strsep(&duplinet, " ");
01503
01504 if (!ignorepat) {
01505 free(dupline);
01506 return NULL;
01507 }
01508
01509 if (ast_lock_contexts()) {
01510 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01511 free(dupline);
01512 return NULL;
01513 }
01514
01515 c = ast_walk_contexts(NULL);
01516 while (c) {
01517 if (!ast_lock_context(c)) {
01518 struct ast_ignorepat *ip;
01519 ip = ast_walk_context_ignorepats(c, NULL);
01520 while (ip) {
01521 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat)) {
01522 if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
01523 if (++which > state) {
01524 char *ret = strdup(ast_get_context_name(c));
01525 free(dupline);
01526 ast_unlock_context(c);
01527 ast_unlock_contexts();
01528 return ret;
01529 }
01530 }
01531 }
01532 ip = ast_walk_context_ignorepats(c, ip);
01533 }
01534
01535 ast_unlock_context(c);
01536 }
01537 c = ast_walk_contexts(c);
01538 }
01539
01540 free(dupline);
01541 ast_unlock_contexts();
01542 return NULL;
01543 }
01544
01545 return NULL;
01546 }
01547
01548
01549
01550
01551 static struct ast_cli_entry context_dont_include_cli =
01552 { { "dont", "include", NULL }, handle_context_dont_include,
01553 "Remove a specified include from context", context_dont_include_help,
01554 complete_context_dont_include };
01555
01556 static struct ast_cli_entry context_remove_extension_cli =
01557 { { "remove", "extension", NULL }, handle_context_remove_extension,
01558 "Remove a specified extension", context_remove_extension_help,
01559 complete_context_remove_extension };
01560
01561 static struct ast_cli_entry context_add_include_cli =
01562 { { "include", "context", NULL }, handle_context_add_include,
01563 "Include context in other context", context_add_include_help,
01564 complete_context_add_include };
01565
01566 static struct ast_cli_entry save_dialplan_cli =
01567 { { "save", "dialplan", NULL }, handle_save_dialplan,
01568 "Save dialplan", save_dialplan_help };
01569
01570 static struct ast_cli_entry context_add_extension_cli =
01571 { { "add", "extension", NULL }, handle_context_add_extension,
01572 "Add new extension into context", context_add_extension_help,
01573 complete_context_add_extension };
01574
01575 static struct ast_cli_entry context_add_ignorepat_cli =
01576 { { "add", "ignorepat", NULL }, handle_context_add_ignorepat,
01577 "Add new ignore pattern", context_add_ignorepat_help,
01578 complete_context_add_ignorepat };
01579
01580 static struct ast_cli_entry context_remove_ignorepat_cli =
01581 { { "remove", "ignorepat", NULL }, handle_context_remove_ignorepat,
01582 "Remove ignore pattern from context", context_remove_ignorepat_help,
01583 complete_context_remove_ignorepat };
01584
01585 static struct ast_cli_entry reload_extensions_cli =
01586 { { "extensions", "reload", NULL}, handle_reload_extensions,
01587 "Reload extensions and *only* extensions", reload_extensions_help };
01588
01589
01590
01591
01592 int unload_module(void)
01593 {
01594 ast_cli_unregister(&context_add_extension_cli);
01595 if (static_config && !write_protect_config)
01596 ast_cli_unregister(&save_dialplan_cli);
01597 ast_cli_unregister(&context_add_include_cli);
01598 ast_cli_unregister(&context_dont_include_cli);
01599 ast_cli_unregister(&context_remove_extension_cli);
01600 ast_cli_unregister(&context_remove_ignorepat_cli);
01601 ast_cli_unregister(&context_add_ignorepat_cli);
01602 ast_cli_unregister(&reload_extensions_cli);
01603 ast_context_destroy(NULL, registrar);
01604 return 0;
01605 }
01606
01607 static int pbx_load_module(void)
01608 {
01609 struct ast_config *cfg;
01610 struct ast_variable *v;
01611 char *cxt, *ext, *pri, *appl, *data, *tc, *cidmatch;
01612 struct ast_context *con;
01613 char *end;
01614 char *label;
01615 char realvalue[256];
01616 int lastpri = -2;
01617
01618 cfg = ast_config_load(config);
01619 if (cfg) {
01620
01621 static_config = ast_true(ast_variable_retrieve(cfg, "general",
01622 "static"));
01623 write_protect_config = ast_true(ast_variable_retrieve(cfg, "general",
01624 "writeprotect"));
01625 autofallthrough_config = ast_true(ast_variable_retrieve(cfg, "general",
01626 "autofallthrough"));
01627 clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general",
01628 "clearglobalvars"));
01629 option_priority_jumping = !ast_false(ast_variable_retrieve(cfg, "general",
01630 "priorityjumping"));
01631
01632 v = ast_variable_browse(cfg, "globals");
01633 while(v) {
01634 memset(realvalue, 0, sizeof(realvalue));
01635 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01636 pbx_builtin_setvar_helper(NULL, v->name, realvalue);
01637 v = v->next;
01638 }
01639 cxt = ast_category_browse(cfg, NULL);
01640 while(cxt) {
01641
01642 if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) {
01643 cxt = ast_category_browse(cfg, cxt);
01644 continue;
01645 }
01646 if ((con=ast_context_create(&local_contexts,cxt, registrar))) {
01647 v = ast_variable_browse(cfg, cxt);
01648 while(v) {
01649 if (!strcasecmp(v->name, "exten")) {
01650 char *stringp=NULL;
01651 int ipri = -2;
01652 char realext[256]="";
01653 char *plus, *firstp, *firstc;
01654 tc = strdup(v->value);
01655 if(tc!=NULL){
01656 stringp=tc;
01657 ext = strsep(&stringp, ",");
01658 if (!ext)
01659 ext="";
01660 pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
01661 cidmatch = strchr(realext, '/');
01662 if (cidmatch) {
01663 *cidmatch = '\0';
01664 cidmatch++;
01665 ast_shrink_phone_number(cidmatch);
01666 }
01667 pri = strsep(&stringp, ",");
01668 if (!pri)
01669 pri="";
01670 label = strchr(pri, '(');
01671 if (label) {
01672 *label = '\0';
01673 label++;
01674 end = strchr(label, ')');
01675 if (end)
01676 *end = '\0';
01677 else
01678 ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno);
01679 }
01680 plus = strchr(pri, '+');
01681 if (plus) {
01682 *plus = '\0';
01683 plus++;
01684 }
01685 if (!strcmp(pri,"hint"))
01686 ipri=PRIORITY_HINT;
01687 else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
01688 if (lastpri > -2)
01689 ipri = lastpri + 1;
01690 else
01691 ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
01692 } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
01693 if (lastpri > -2)
01694 ipri = lastpri;
01695 else
01696 ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
01697 } else {
01698 if (sscanf(pri, "%d", &ipri) != 1) {
01699 if ((ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
01700 ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
01701 ipri = 0;
01702 }
01703 }
01704 }
01705 appl = stringp;
01706 if (!appl)
01707 appl="";
01708
01709 firstc = strchr(appl, ',');
01710 firstp = strchr(appl, '(');
01711 if (firstc && ((!firstp) || (firstc < firstp))) {
01712
01713
01714 appl = strsep(&stringp, ",");
01715 data = stringp;
01716 } else if ((!firstc) && (!firstp)) {
01717
01718 data = "";
01719 } else {
01720
01721 appl = strsep(&stringp, "(");
01722 data = stringp;
01723 end = strrchr(data, ')');
01724 if ((end = strrchr(data, ')'))) {
01725 *end = '\0';
01726 } else {
01727 ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
01728 }
01729 ast_process_quotes_and_slashes(data, ',', '|');
01730 }
01731
01732 if (!data)
01733 data="";
01734 while(*appl && (*appl < 33)) appl++;
01735 if (ipri) {
01736 if (plus)
01737 ipri += atoi(plus);
01738 lastpri = ipri;
01739 if(!option_dontwarn) {
01740 if (!strcmp(realext, "_."))
01741 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);
01742 }
01743 if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), FREE, registrar)) {
01744 ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
01745 }
01746 }
01747 free(tc);
01748 } else {
01749 ast_log(LOG_ERROR, "Memory allocation failure\n");
01750 }
01751 } else if(!strcasecmp(v->name, "include")) {
01752 memset(realvalue, 0, sizeof(realvalue));
01753 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01754 if (ast_context_add_include2(con, realvalue, registrar))
01755 ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
01756 } else if(!strcasecmp(v->name, "ignorepat")) {
01757 memset(realvalue, 0, sizeof(realvalue));
01758 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01759 if (ast_context_add_ignorepat2(con, realvalue, registrar))
01760 ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
01761 } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
01762 char *stringp=NULL;
01763 memset(realvalue, 0, sizeof(realvalue));
01764 if (!strcasecmp(v->name, "switch"))
01765 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01766 else
01767 strncpy(realvalue, v->value, sizeof(realvalue) - 1);
01768 tc = realvalue;
01769 stringp=tc;
01770 appl = strsep(&stringp, "/");
01771 data = strsep(&stringp, "");
01772 if (!data)
01773 data = "";
01774 if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar))
01775 ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
01776 }
01777 v = v->next;
01778 }
01779 }
01780 cxt = ast_category_browse(cfg, cxt);
01781 }
01782 ast_config_destroy(cfg);
01783 }
01784 ast_merge_contexts_and_delete(&local_contexts,registrar);
01785
01786 for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
01787 ast_context_verify_includes(con);
01788
01789 pbx_set_autofallthrough(autofallthrough_config);
01790
01791 return 0;
01792 }
01793
01794 int load_module(void)
01795 {
01796 if (pbx_load_module()) return -1;
01797
01798 ast_cli_register(&context_remove_extension_cli);
01799 ast_cli_register(&context_dont_include_cli);
01800 ast_cli_register(&context_add_include_cli);
01801 if (static_config && !write_protect_config)
01802 ast_cli_register(&save_dialplan_cli);
01803 ast_cli_register(&context_add_extension_cli);
01804 ast_cli_register(&context_add_ignorepat_cli);
01805 ast_cli_register(&context_remove_ignorepat_cli);
01806 ast_cli_register(&reload_extensions_cli);
01807
01808 return 0;
01809 }
01810
01811 int reload(void)
01812 {
01813 if (clearglobalvars_config)
01814 pbx_builtin_clear_globals();
01815 pbx_load_module();
01816 return 0;
01817 }
01818
01819 int usecount(void)
01820 {
01821 return 0;
01822 }
01823
01824 char *description(void)
01825 {
01826 return dtext;
01827 }
01828
01829 char *key(void)
01830 {
01831 return ASTERISK_GPL_KEY;
01832 }