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: 41269 $")
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\nautofallthrough=%s\nclearglobalvars=%s\npriorityjumping=%s\n\n",
00989 static_config ? "yes" : "no",
00990 write_protect_config ? "yes" : "no",
00991 autofallthrough_config ? "yes" : "no",
00992 clearglobalvars_config ? "yes" : "no",
00993 option_priority_jumping ? "yes" : "no");
00994
00995 if ((v = ast_variable_browse(cfg, "globals"))) {
00996 fprintf(output, "[globals]\n");
00997 while(v) {
00998 fprintf(output, "%s => %s\n", v->name, v->value);
00999 v = v->next;
01000 }
01001 fprintf(output, "\n");
01002 }
01003
01004 ast_config_destroy(cfg);
01005
01006
01007 c = ast_walk_contexts(NULL);
01008 while (c) {
01009 context_header_written = 0;
01010
01011
01012 if (!ast_lock_context(c)) {
01013 struct ast_exten *e, *last_written_e = NULL;
01014 struct ast_include *i;
01015 struct ast_ignorepat *ip;
01016 struct ast_sw *sw;
01017
01018
01019 if (!strcmp(ast_get_context_registrar(c), registrar)) {
01020 fprintf(output, "[%s]\n", ast_get_context_name(c));
01021 context_header_written = 1;
01022 }
01023
01024
01025 e = ast_walk_context_extensions(c, NULL);
01026 while (e) {
01027 struct ast_exten *p;
01028
01029
01030 p = ast_walk_extension_priorities(e, NULL);
01031 while (p) {
01032 if (!strcmp(ast_get_extension_registrar(p),
01033 registrar)) {
01034
01035
01036 if (last_written_e != NULL &&
01037 strcmp(ast_get_extension_name(last_written_e),
01038 ast_get_extension_name(p)))
01039 fprintf(output, "\n");
01040 last_written_e = p;
01041
01042 if (!context_header_written) {
01043 fprintf(output, "[%s]\n", ast_get_context_name(c));
01044 context_header_written = 1;
01045 }
01046
01047 if (ast_get_extension_priority(p)!=PRIORITY_HINT) {
01048 char *tempdata, *startdata;
01049 const char *el = ast_get_extension_label(p);
01050 char label[128] = "";
01051
01052 tempdata = ast_strdupa(ast_get_extension_app_data(p));
01053
01054 startdata = tempdata;
01055 while (*tempdata) {
01056 if (*tempdata == '|')
01057 *tempdata = ',';
01058 tempdata++;
01059 }
01060 tempdata = startdata;
01061
01062 if (el && (snprintf(label, sizeof(label), "(%s)", el) != (strlen(el) + 2)))
01063 incomplete = 1;
01064
01065 if (ast_get_extension_matchcid(p)) {
01066 fprintf(output, "exten => %s/%s,%d%s,%s(%s)\n",
01067 ast_get_extension_name(p),
01068 ast_get_extension_cidmatch(p),
01069 ast_get_extension_priority(p), label,
01070 ast_get_extension_app(p),
01071 tempdata);
01072 } else {
01073 fprintf(output, "exten => %s,%d%s,%s(%s)\n",
01074 ast_get_extension_name(p),
01075 ast_get_extension_priority(p), label,
01076 ast_get_extension_app(p),
01077 tempdata);
01078 }
01079 } else {
01080 fprintf(output, "exten => %s,hint,%s\n",
01081 ast_get_extension_name(p),
01082 ast_get_extension_app(p));
01083 }
01084
01085 }
01086 p = ast_walk_extension_priorities(e, p);
01087 }
01088
01089 e = ast_walk_context_extensions(c, e);
01090 }
01091
01092
01093 if (last_written_e) fprintf(output, "\n");
01094
01095
01096 i = ast_walk_context_includes(c, NULL);
01097 while (i) {
01098 if (!strcmp(ast_get_include_registrar(i), registrar)) {
01099 if (!context_header_written) {
01100 fprintf(output, "[%s]\n", ast_get_context_name(c));
01101 context_header_written = 1;
01102 }
01103 fprintf(output, "include => %s\n",
01104 ast_get_include_name(i));
01105 }
01106 i = ast_walk_context_includes(c, i);
01107 }
01108
01109 if (ast_walk_context_includes(c, NULL))
01110 fprintf(output, "\n");
01111
01112
01113 sw = ast_walk_context_switches(c, NULL);
01114 while (sw) {
01115 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
01116 if (!context_header_written) {
01117 fprintf(output, "[%s]\n", ast_get_context_name(c));
01118 context_header_written = 1;
01119 }
01120 fprintf(output, "switch => %s/%s\n",
01121 ast_get_switch_name(sw),
01122 ast_get_switch_data(sw));
01123 }
01124 sw = ast_walk_context_switches(c, sw);
01125 }
01126
01127 if (ast_walk_context_switches(c, NULL))
01128 fprintf(output, "\n");
01129
01130
01131 ip = ast_walk_context_ignorepats(c, NULL);
01132 while (ip) {
01133 if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
01134 if (!context_header_written) {
01135 fprintf(output, "[%s]\n", ast_get_context_name(c));
01136 context_header_written = 1;
01137 }
01138
01139 fprintf(output, "ignorepat => %s\n",
01140 ast_get_ignorepat_name(ip));
01141 }
01142 ip = ast_walk_context_ignorepats(c, ip);
01143 }
01144
01145 ast_unlock_context(c);
01146 } else
01147 incomplete = 1;
01148
01149 c = ast_walk_contexts(c);
01150 }
01151
01152 ast_unlock_contexts();
01153 ast_mutex_unlock(&save_dialplan_lock);
01154 fclose(output);
01155
01156 if (incomplete) {
01157 ast_cli(fd, "Saved dialplan is incomplete\n");
01158 return RESULT_FAILURE;
01159 }
01160
01161 ast_cli(fd, "Dialplan successfully saved into '%s'\n",
01162 filename);
01163 return RESULT_SUCCESS;
01164 }
01165
01166
01167
01168
01169 static int handle_context_add_extension(int fd, int argc, char *argv[])
01170 {
01171 char *whole_exten;
01172 char *exten, *prior;
01173 int iprior = -2;
01174 char *cidmatch, *app, *app_data;
01175 char *start, *end;
01176
01177
01178 if (argc != 5 && argc != 6) return RESULT_SHOWUSAGE;
01179 if (strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
01180 if (argc == 6) if (strcmp(argv[5], "replace")) return RESULT_SHOWUSAGE;
01181
01182 whole_exten = argv[2];
01183 exten = strsep(&whole_exten,",");
01184 if (strchr(exten, '/')) {
01185 cidmatch = exten;
01186 strsep(&cidmatch,"/");
01187 } else {
01188 cidmatch = NULL;
01189 }
01190 prior = strsep(&whole_exten,",");
01191 if (prior) {
01192 if (!strcmp(prior, "hint")) {
01193 iprior = PRIORITY_HINT;
01194 } else {
01195 if (sscanf(prior, "%d", &iprior) != 1) {
01196 ast_cli(fd, "'%s' is not a valid priority\n", prior);
01197 prior = NULL;
01198 }
01199 }
01200 }
01201 app = whole_exten;
01202 if (app && (start = strchr(app, '(')) && (end = strrchr(app, ')'))) {
01203 *start = *end = '\0';
01204 app_data = start + 1;
01205 ast_process_quotes_and_slashes(app_data, ',', '|');
01206 } else {
01207 if (app) {
01208 app_data = strchr(app, ',');
01209 if (app_data) {
01210 *app_data = '\0';
01211 app_data++;
01212 }
01213 } else
01214 app_data = NULL;
01215 }
01216
01217 if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT)) return RESULT_SHOWUSAGE;
01218
01219 if (!app_data)
01220 app_data="";
01221 if (ast_add_extension(argv[4], argc == 6 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
01222 (void *)strdup(app_data), free, registrar)) {
01223 switch (errno) {
01224 case ENOMEM:
01225 ast_cli(fd, "Out of free memory\n"); break;
01226
01227 case EBUSY:
01228 ast_cli(fd, "Failed to lock context(s) list, please try again later\n"); break;
01229
01230 case ENOENT:
01231 ast_cli(fd, "No existence of '%s' context\n", argv[4]); break;
01232
01233 case EEXIST:
01234 ast_cli(fd, "Extension %s@%s with priority %s already exists\n",
01235 exten, argv[4], prior); break;
01236
01237 default:
01238 ast_cli(fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
01239 exten, prior, app, app_data, argv[4]); break;
01240 }
01241 return RESULT_FAILURE;
01242 }
01243
01244 if (argc == 6)
01245 ast_cli(fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
01246 exten, argv[4], prior, exten, prior, app, app_data);
01247 else
01248 ast_cli(fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
01249 exten, prior, app, app_data, argv[4]);
01250
01251 return RESULT_SUCCESS;
01252 }
01253
01254
01255 static char *complete_context_add_extension(char *line, char *word,
01256 int pos, int state)
01257 {
01258 int which = 0;
01259
01260
01261 if (pos == 3) {
01262 if (state == 0) return strdup("into");
01263 return NULL;
01264 }
01265
01266
01267 if (pos == 4) {
01268 struct ast_context *c;
01269
01270
01271 if (ast_lock_contexts()) {
01272 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01273 return NULL;
01274 }
01275
01276
01277 c = ast_walk_contexts(NULL);
01278 while (c) {
01279
01280 if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
01281 if (++which > state) {
01282 char *res = strdup(ast_get_context_name(c));
01283 ast_unlock_contexts();
01284 return res;
01285 }
01286 }
01287 c = ast_walk_contexts(c);
01288 }
01289
01290 ast_unlock_contexts();
01291 return NULL;
01292 }
01293
01294 if (pos == 5) return state == 0 ? strdup("replace") : NULL;
01295
01296 return NULL;
01297 }
01298
01299
01300
01301
01302 static int handle_context_add_ignorepat(int fd, int argc, char *argv[])
01303 {
01304 if (argc != 5) return RESULT_SHOWUSAGE;
01305 if (strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
01306
01307 if (ast_context_add_ignorepat(argv[4], argv[2], registrar)) {
01308 switch (errno) {
01309 case ENOMEM:
01310 ast_cli(fd, "Out of free memory\n"); break;
01311
01312 case ENOENT:
01313 ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
01314 break;
01315
01316 case EEXIST:
01317 ast_cli(fd, "Ignore pattern '%s' already included in '%s' context\n",
01318 argv[2], argv[4]);
01319 break;
01320
01321 case EBUSY:
01322 ast_cli(fd, "Failed to lock context(s) list, please, try again later\n");
01323 break;
01324
01325 default:
01326 ast_cli(fd, "Failed to add ingore pattern '%s' into '%s' context\n",
01327 argv[2], argv[4]);
01328 break;
01329 }
01330 return RESULT_FAILURE;
01331 }
01332
01333 ast_cli(fd, "Ignore pattern '%s' added into '%s' context\n",
01334 argv[2], argv[4]);
01335 return RESULT_SUCCESS;
01336 }
01337
01338 static char *complete_context_add_ignorepat(char *line, char *word,
01339 int pos, int state)
01340 {
01341 if (pos == 3) return state == 0 ? strdup("into") : NULL;
01342
01343 if (pos == 4) {
01344 struct ast_context *c;
01345 int which = 0;
01346 char *dupline, *duplinet, *ignorepat = NULL;
01347
01348 dupline = strdup(line);
01349 duplinet = dupline;
01350
01351 if (duplinet) {
01352 strsep(&duplinet, " ");
01353 strsep(&duplinet, " ");
01354 ignorepat = strsep(&duplinet, " ");
01355 }
01356
01357 if (ast_lock_contexts()) {
01358 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
01359 return NULL;
01360 }
01361
01362 c = ast_walk_contexts(NULL);
01363 while (c) {
01364 if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
01365 int serve_context = 1;
01366 if (ignorepat) {
01367 if (!ast_lock_context(c)) {
01368 struct ast_ignorepat *ip;
01369 ip = ast_walk_context_ignorepats(c, NULL);
01370 while (ip && serve_context) {
01371 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat))
01372 serve_context = 0;
01373 ip = ast_walk_context_ignorepats(c, ip);
01374 }
01375 ast_unlock_context(c);
01376 }
01377 }
01378 if (serve_context) {
01379 if (++which > state) {
01380 char *context = strdup(ast_get_context_name(c));
01381 if (dupline) free(dupline);
01382 ast_unlock_contexts();
01383 return context;
01384 }
01385 }
01386 }
01387 c = ast_walk_contexts(c);
01388 }
01389
01390 if (dupline) free(dupline);
01391 ast_unlock_contexts();
01392 return NULL;
01393 }
01394
01395 return NULL;
01396 }
01397
01398 static int handle_context_remove_ignorepat(int fd, int argc, char *argv[])
01399 {
01400 if (argc != 5) return RESULT_SHOWUSAGE;
01401 if (strcmp(argv[3], "from")) return RESULT_SHOWUSAGE;
01402
01403 if (ast_context_remove_ignorepat(argv[4], argv[2], registrar)) {
01404 switch (errno) {
01405 case EBUSY:
01406 ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
01407 break;
01408
01409 case ENOENT:
01410 ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
01411 break;
01412
01413 case EINVAL:
01414 ast_cli(fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
01415 argv[2], argv[4]);
01416 break;
01417
01418 default:
01419 ast_cli(fd, "Failed to remove ignore pattern '%s' from '%s' context\n", argv[2], argv[4]);
01420 break;
01421 }
01422 return RESULT_FAILURE;
01423 }
01424
01425 ast_cli(fd, "Ignore pattern '%s' removed from '%s' context\n",
01426 argv[2], argv[4]);
01427 return RESULT_SUCCESS;
01428 }
01429
01430 static int pbx_load_module(void);
01431
01432 static int handle_reload_extensions(int fd, int argc, char *argv[])
01433 {
01434 if (argc!=2) return RESULT_SHOWUSAGE;
01435 pbx_load_module();
01436 return RESULT_SUCCESS;
01437 }
01438
01439 static char *complete_context_remove_ignorepat(char *line, char *word,
01440 int pos, int state)
01441 {
01442 struct ast_context *c;
01443 int which = 0;
01444
01445 if (pos == 2) {
01446 if (ast_lock_contexts()) {
01447 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01448 return NULL;
01449 }
01450
01451 c = ast_walk_contexts(NULL);
01452 while (c) {
01453 if (!ast_lock_context(c)) {
01454 struct ast_ignorepat *ip;
01455
01456 ip = ast_walk_context_ignorepats(c, NULL);
01457 while (ip) {
01458 if (!strncmp(ast_get_ignorepat_name(ip), word, strlen(word))) {
01459 if (which + 1 > state) {
01460 struct ast_context *cw;
01461 int already_served = 0;
01462 cw = ast_walk_contexts(NULL);
01463 while (cw && cw != c && !already_served) {
01464 if (!ast_lock_context(cw)) {
01465 struct ast_ignorepat *ipw;
01466 ipw = ast_walk_context_ignorepats(cw, NULL);
01467 while (ipw) {
01468 if (!strcmp(ast_get_ignorepat_name(ipw),
01469 ast_get_ignorepat_name(ip))) already_served = 1;
01470 ipw = ast_walk_context_ignorepats(cw, ipw);
01471 }
01472 ast_unlock_context(cw);
01473 }
01474 cw = ast_walk_contexts(cw);
01475 }
01476 if (!already_served) {
01477 char *ret = strdup(ast_get_ignorepat_name(ip));
01478 ast_unlock_context(c);
01479 ast_unlock_contexts();
01480 return ret;
01481 }
01482 } else
01483 which++;
01484 }
01485 ip = ast_walk_context_ignorepats(c, ip);
01486 }
01487
01488 ast_unlock_context(c);
01489 }
01490 c = ast_walk_contexts(c);
01491 }
01492
01493 ast_unlock_contexts();
01494 return NULL;
01495 }
01496
01497 if (pos == 3) return state == 0 ? strdup("from") : NULL;
01498
01499 if (pos == 4) {
01500 char *dupline, *duplinet, *ignorepat;
01501
01502 dupline = strdup(line);
01503 if (!dupline) {
01504 ast_log(LOG_WARNING, "Out of free memory\n");
01505 return NULL;
01506 }
01507
01508 duplinet = dupline;
01509 strsep(&duplinet, " ");
01510 strsep(&duplinet, " ");
01511 ignorepat = strsep(&duplinet, " ");
01512
01513 if (!ignorepat) {
01514 free(dupline);
01515 return NULL;
01516 }
01517
01518 if (ast_lock_contexts()) {
01519 ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01520 free(dupline);
01521 return NULL;
01522 }
01523
01524 c = ast_walk_contexts(NULL);
01525 while (c) {
01526 if (!ast_lock_context(c)) {
01527 struct ast_ignorepat *ip;
01528 ip = ast_walk_context_ignorepats(c, NULL);
01529 while (ip) {
01530 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat)) {
01531 if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
01532 if (++which > state) {
01533 char *ret = strdup(ast_get_context_name(c));
01534 free(dupline);
01535 ast_unlock_context(c);
01536 ast_unlock_contexts();
01537 return ret;
01538 }
01539 }
01540 }
01541 ip = ast_walk_context_ignorepats(c, ip);
01542 }
01543
01544 ast_unlock_context(c);
01545 }
01546 c = ast_walk_contexts(c);
01547 }
01548
01549 free(dupline);
01550 ast_unlock_contexts();
01551 return NULL;
01552 }
01553
01554 return NULL;
01555 }
01556
01557
01558
01559
01560 static struct ast_cli_entry context_dont_include_cli =
01561 { { "dont", "include", NULL }, handle_context_dont_include,
01562 "Remove a specified include from context", context_dont_include_help,
01563 complete_context_dont_include };
01564
01565 static struct ast_cli_entry context_remove_extension_cli =
01566 { { "remove", "extension", NULL }, handle_context_remove_extension,
01567 "Remove a specified extension", context_remove_extension_help,
01568 complete_context_remove_extension };
01569
01570 static struct ast_cli_entry context_add_include_cli =
01571 { { "include", "context", NULL }, handle_context_add_include,
01572 "Include context in other context", context_add_include_help,
01573 complete_context_add_include };
01574
01575 static struct ast_cli_entry save_dialplan_cli =
01576 { { "save", "dialplan", NULL }, handle_save_dialplan,
01577 "Save dialplan", save_dialplan_help };
01578
01579 static struct ast_cli_entry context_add_extension_cli =
01580 { { "add", "extension", NULL }, handle_context_add_extension,
01581 "Add new extension into context", context_add_extension_help,
01582 complete_context_add_extension };
01583
01584 static struct ast_cli_entry context_add_ignorepat_cli =
01585 { { "add", "ignorepat", NULL }, handle_context_add_ignorepat,
01586 "Add new ignore pattern", context_add_ignorepat_help,
01587 complete_context_add_ignorepat };
01588
01589 static struct ast_cli_entry context_remove_ignorepat_cli =
01590 { { "remove", "ignorepat", NULL }, handle_context_remove_ignorepat,
01591 "Remove ignore pattern from context", context_remove_ignorepat_help,
01592 complete_context_remove_ignorepat };
01593
01594 static struct ast_cli_entry reload_extensions_cli =
01595 { { "extensions", "reload", NULL}, handle_reload_extensions,
01596 "Reload extensions and *only* extensions", reload_extensions_help };
01597
01598
01599
01600
01601 int unload_module(void)
01602 {
01603 ast_cli_unregister(&context_add_extension_cli);
01604 if (static_config && !write_protect_config)
01605 ast_cli_unregister(&save_dialplan_cli);
01606 ast_cli_unregister(&context_add_include_cli);
01607 ast_cli_unregister(&context_dont_include_cli);
01608 ast_cli_unregister(&context_remove_extension_cli);
01609 ast_cli_unregister(&context_remove_ignorepat_cli);
01610 ast_cli_unregister(&context_add_ignorepat_cli);
01611 ast_cli_unregister(&reload_extensions_cli);
01612 ast_context_destroy(NULL, registrar);
01613 return 0;
01614 }
01615
01616 static int pbx_load_module(void)
01617 {
01618 struct ast_config *cfg;
01619 struct ast_variable *v;
01620 char *cxt, *ext, *pri, *appl, *data, *tc, *cidmatch;
01621 struct ast_context *con;
01622 char *end;
01623 char *label;
01624 char realvalue[256];
01625 int lastpri = -2;
01626
01627 cfg = ast_config_load(config);
01628 if (cfg) {
01629
01630 static_config = ast_true(ast_variable_retrieve(cfg, "general",
01631 "static"));
01632 write_protect_config = ast_true(ast_variable_retrieve(cfg, "general",
01633 "writeprotect"));
01634 autofallthrough_config = ast_true(ast_variable_retrieve(cfg, "general",
01635 "autofallthrough"));
01636 clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general",
01637 "clearglobalvars"));
01638 option_priority_jumping = !ast_false(ast_variable_retrieve(cfg, "general",
01639 "priorityjumping"));
01640
01641 v = ast_variable_browse(cfg, "globals");
01642 while(v) {
01643 memset(realvalue, 0, sizeof(realvalue));
01644 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01645 pbx_builtin_setvar_helper(NULL, v->name, realvalue);
01646 v = v->next;
01647 }
01648 cxt = ast_category_browse(cfg, NULL);
01649 while(cxt) {
01650
01651 if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) {
01652 cxt = ast_category_browse(cfg, cxt);
01653 continue;
01654 }
01655 if ((con=ast_context_create(&local_contexts,cxt, registrar))) {
01656 v = ast_variable_browse(cfg, cxt);
01657 while(v) {
01658 if (!strcasecmp(v->name, "exten")) {
01659 char *stringp=NULL;
01660 int ipri = -2;
01661 char realext[256]="";
01662 char *plus, *firstp, *firstc;
01663 tc = strdup(v->value);
01664 if(tc!=NULL){
01665 stringp=tc;
01666 ext = strsep(&stringp, ",");
01667 if (!ext)
01668 ext="";
01669 pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
01670 cidmatch = strchr(realext, '/');
01671 if (cidmatch) {
01672 *cidmatch = '\0';
01673 cidmatch++;
01674 ast_shrink_phone_number(cidmatch);
01675 }
01676 pri = strsep(&stringp, ",");
01677 if (!pri)
01678 pri="";
01679 label = strchr(pri, '(');
01680 if (label) {
01681 *label = '\0';
01682 label++;
01683 end = strchr(label, ')');
01684 if (end)
01685 *end = '\0';
01686 else
01687 ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno);
01688 }
01689 plus = strchr(pri, '+');
01690 if (plus) {
01691 *plus = '\0';
01692 plus++;
01693 }
01694 if (!strcmp(pri,"hint"))
01695 ipri=PRIORITY_HINT;
01696 else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
01697 if (lastpri > -2)
01698 ipri = lastpri + 1;
01699 else
01700 ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
01701 } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
01702 if (lastpri > -2)
01703 ipri = lastpri;
01704 else
01705 ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
01706 } else {
01707 if (sscanf(pri, "%d", &ipri) != 1) {
01708 if ((ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
01709 ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
01710 ipri = 0;
01711 }
01712 }
01713 }
01714 appl = stringp;
01715 if (!appl)
01716 appl="";
01717
01718 firstc = strchr(appl, ',');
01719 firstp = strchr(appl, '(');
01720 if (firstc && ((!firstp) || (firstc < firstp))) {
01721
01722
01723 appl = strsep(&stringp, ",");
01724 data = stringp;
01725 } else if ((!firstc) && (!firstp)) {
01726
01727 data = "";
01728 } else {
01729
01730 appl = strsep(&stringp, "(");
01731 data = stringp;
01732 end = strrchr(data, ')');
01733 if ((end = strrchr(data, ')'))) {
01734 *end = '\0';
01735 } else {
01736 ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
01737 }
01738 ast_process_quotes_and_slashes(data, ',', '|');
01739 }
01740
01741 if (!data)
01742 data="";
01743 while(*appl && (*appl < 33)) appl++;
01744 if (ipri) {
01745 if (plus)
01746 ipri += atoi(plus);
01747 lastpri = ipri;
01748 if(!option_dontwarn) {
01749 if (!strcmp(realext, "_."))
01750 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);
01751 }
01752 if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), FREE, registrar)) {
01753 ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
01754 }
01755 }
01756 free(tc);
01757 } else {
01758 ast_log(LOG_ERROR, "Memory allocation failure\n");
01759 }
01760 } else if(!strcasecmp(v->name, "include")) {
01761 memset(realvalue, 0, sizeof(realvalue));
01762 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01763 if (ast_context_add_include2(con, realvalue, registrar))
01764 ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
01765 } else if(!strcasecmp(v->name, "ignorepat")) {
01766 memset(realvalue, 0, sizeof(realvalue));
01767 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01768 if (ast_context_add_ignorepat2(con, realvalue, registrar))
01769 ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
01770 } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
01771 char *stringp=NULL;
01772 memset(realvalue, 0, sizeof(realvalue));
01773 if (!strcasecmp(v->name, "switch"))
01774 pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01775 else
01776 strncpy(realvalue, v->value, sizeof(realvalue) - 1);
01777 tc = realvalue;
01778 stringp=tc;
01779 appl = strsep(&stringp, "/");
01780 data = strsep(&stringp, "");
01781 if (!data)
01782 data = "";
01783 if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar))
01784 ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
01785 }
01786 v = v->next;
01787 }
01788 }
01789 cxt = ast_category_browse(cfg, cxt);
01790 }
01791 ast_config_destroy(cfg);
01792 }
01793 ast_merge_contexts_and_delete(&local_contexts,registrar);
01794
01795 for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
01796 ast_context_verify_includes(con);
01797
01798 pbx_set_autofallthrough(autofallthrough_config);
01799
01800 return 0;
01801 }
01802
01803 int load_module(void)
01804 {
01805 if (pbx_load_module()) return -1;
01806
01807 ast_cli_register(&context_remove_extension_cli);
01808 ast_cli_register(&context_dont_include_cli);
01809 ast_cli_register(&context_add_include_cli);
01810 if (static_config && !write_protect_config)
01811 ast_cli_register(&save_dialplan_cli);
01812 ast_cli_register(&context_add_extension_cli);
01813 ast_cli_register(&context_add_ignorepat_cli);
01814 ast_cli_register(&context_remove_ignorepat_cli);
01815 ast_cli_register(&reload_extensions_cli);
01816
01817 return 0;
01818 }
01819
01820 int reload(void)
01821 {
01822 if (clearglobalvars_config)
01823 pbx_builtin_clear_globals();
01824 pbx_load_module();
01825 return 0;
01826 }
01827
01828 int usecount(void)
01829 {
01830 return 0;
01831 }
01832
01833 char *description(void)
01834 {
01835 return dtext;
01836 }
01837
01838 char *key(void)
01839 {
01840 return ASTERISK_GPL_KEY;
01841 }