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