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