Tue Aug 20 16:35:08 2013

Asterisk developer's documentation


pbx_config.c File Reference

Populate and remember extensions from static config file. More...

#include "asterisk.h"
#include <ctype.h>
#include "asterisk/paths.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"

Go to the source code of this file.

Defines

#define PUT_CTX_HDR

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void append_interface (char *iface, int maxlen, char *add)
static char * complete_dialplan_add_extension (struct ast_cli_args *)
static char * complete_dialplan_add_ignorepat (struct ast_cli_args *)
static char * complete_dialplan_add_include (struct ast_cli_args *)
static char * complete_dialplan_remove_extension (struct ast_cli_args *)
static char * complete_dialplan_remove_ignorepat (struct ast_cli_args *)
static char * complete_dialplan_remove_include (struct ast_cli_args *)
static char * handle_cli_dialplan_add_extension (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 ADD EXTENSION command stuff.
static char * handle_cli_dialplan_add_ignorepat (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_dialplan_add_include (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_dialplan_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_dialplan_remove_extension (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_dialplan_remove_ignorepat (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_dialplan_remove_include (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_dialplan_save (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 'save dialplan' CLI command implementation functions ...
static int load_module (void)
static int lookup_c_ip (struct ast_context *c, const char *name)
 return true if 'name' is in the ignorepats for context c
static int lookup_ci (struct ast_context *c, const char *name)
 return true if 'name' is included by context c
static int partial_match (const char *s, const char *word, int len)
 match the first 'len' chars of word. len==0 always succeeds
static int pbx_load_config (const char *config_file)
static int pbx_load_module (void)
static void pbx_load_users (void)
static char * pbx_strsep (char **destructible, const char *delim)
static int reload (void)
static const char * skip_words (const char *p, int n)
 moves to the n-th word in the string, or empty string if none
static int split_ec (const char *src, char **ext, char **const ctx, char **const cid)
 split extension@context in two parts, return -1 on error. The return string is malloc'ed and pointed by *ext
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Text Extension Configuration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct ast_module_infoast_module_info = &__mod_info
static int autofallthrough_config = 1
static int clearglobalvars_config = 0
static struct ast_cli_entry cli_dialplan_save
static struct ast_cli_entry cli_pbx_config []
static const char config [] = "extensions.conf"
static int extenpatternmatchnew_config = 0
static struct ast_contextlocal_contexts = NULL
static struct ast_hashtablocal_table = NULL
static char * overrideswitch_config = NULL
static const char registrar [] = "pbx_config"
static ast_mutex_t reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static ast_mutex_t save_dialplan_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static int static_config = 0
static char userscontext [AST_MAX_EXTENSION] = "default"
static int write_protect_config = 1

Detailed Description

Populate and remember extensions from static config file.

Definition in file pbx_config.c.


Define Documentation

#define PUT_CTX_HDR

Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1826 of file pbx_config.c.

static void __unreg_module ( void   )  [static]

Definition at line 1826 of file pbx_config.c.

static void append_interface ( char *  iface,
int  maxlen,
char *  add 
) [static]

Definition at line 1655 of file pbx_config.c.

References len().

Referenced by pbx_load_users().

01656 {
01657    int len = strlen(iface);
01658    if (strlen(add) + len < maxlen - 2) {
01659       if (strlen(iface)) {
01660          iface[len] = '&';
01661          strcpy(iface + len + 1, add);
01662       } else
01663          strcpy(iface, add);
01664    }
01665 }

static char * complete_dialplan_add_extension ( struct ast_cli_args a  )  [static]

dialplan add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local

Definition at line 1026 of file pbx_config.c.

References ast_get_context_name(), ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), len(), LOG_WARNING, ast_cli_args::n, partial_match(), ast_cli_args::pos, strdup, and ast_cli_args::word.

Referenced by handle_cli_dialplan_add_extension().

01027 {
01028    int which = 0;
01029 
01030    if (a->pos == 4) {      /* complete 'into' word ... */
01031       return (a->n == 0) ? strdup("into") : NULL;
01032    } else if (a->pos == 5) { /* complete context */
01033       struct ast_context *c = NULL;
01034       int len = strlen(a->word);
01035       char *res = NULL;
01036 
01037       /* try to lock contexts list ... */
01038       if (ast_rdlock_contexts()) {
01039          ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01040          return NULL;
01041       }
01042 
01043       /* walk through all contexts */
01044       while ( !res && (c = ast_walk_contexts(c)) )
01045          if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n)
01046             res = strdup(ast_get_context_name(c));
01047       ast_unlock_contexts();
01048       return res;
01049    } else if (a->pos == 6) {
01050       return a->n == 0 ? strdup("replace") : NULL;
01051    }
01052    return NULL;
01053 }

static char * complete_dialplan_add_ignorepat ( struct ast_cli_args a  )  [static]

Definition at line 1112 of file pbx_config.c.

References ast_get_context_name(), ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), free, len(), ast_cli_args::line, LOG_ERROR, lookup_c_ip(), ast_cli_args::n, partial_match(), ast_cli_args::pos, skip_words(), strdup, and ast_cli_args::word.

Referenced by handle_cli_dialplan_add_ignorepat().

01113 {
01114    if (a->pos == 4)
01115       return a->n == 0 ? strdup("into") : NULL;
01116    else if (a->pos == 5) {
01117       struct ast_context *c;
01118       int which = 0;
01119       char *dupline, *ignorepat = NULL;
01120       const char *s;
01121       char *ret = NULL;
01122       int len = strlen(a->word);
01123 
01124       /* XXX skip first three words 'dialplan' 'add' 'ignorepat' */
01125       s = skip_words(a->line, 3);
01126       if (s == NULL)
01127          return NULL;
01128       dupline = strdup(s);
01129       if (!dupline) {
01130          ast_log(LOG_ERROR, "Malloc failure\n");
01131          return NULL;
01132       }
01133       ignorepat = strsep(&dupline, " ");
01134 
01135       if (ast_rdlock_contexts()) {
01136          ast_log(LOG_ERROR, "Failed to lock contexts list\n");
01137          return NULL;
01138       }
01139 
01140       for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
01141          int found = 0;
01142 
01143          if (!partial_match(ast_get_context_name(c), a->word, len))
01144             continue; /* not mine */
01145          if (ignorepat) /* there must be one, right ? */
01146             found = lookup_c_ip(c, ignorepat);
01147          if (!found && ++which > a->n)
01148             ret = strdup(ast_get_context_name(c));
01149       }
01150 
01151       free(ignorepat);
01152       ast_unlock_contexts();
01153       return ret;
01154    }
01155 
01156    return NULL;
01157 }

static char * complete_dialplan_add_include ( struct ast_cli_args a  )  [static]

Definition at line 578 of file pbx_config.c.

References ast_get_context_name(), ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), context, free, len(), ast_cli_args::line, LOG_ERROR, lookup_ci(), ast_cli_args::n, partial_match(), ast_cli_args::pos, skip_words(), strdup, and ast_cli_args::word.

Referenced by handle_cli_dialplan_add_include().

00579 {
00580    struct ast_context *c;
00581    int which = 0;
00582    char *ret = NULL;
00583    int len = strlen(a->word);
00584 
00585    if (a->pos == 3) {      /* 'dialplan add include _X_' (context) ... */
00586       if (ast_rdlock_contexts()) {
00587          ast_log(LOG_ERROR, "Failed to lock context list\n");
00588          return NULL;
00589       }
00590       for (c = NULL; !ret && (c = ast_walk_contexts(c)); )
00591          if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n)
00592             ret = strdup(ast_get_context_name(c));
00593       ast_unlock_contexts();
00594       return ret;
00595    } else if (a->pos == 4) { /* dialplan add include CTX _X_ */
00596       /* complete  as 'into' if context exists or we are unable to check */
00597       char *context, *dupline;
00598       const char *s = skip_words(a->line, 3); /* should not fail */
00599 
00600       if (a->n != 0) /* only once */
00601          return NULL;
00602 
00603       /* parse context from line ... */
00604       context = dupline = strdup(s);
00605       if (!context) {
00606          ast_log(LOG_ERROR, "Out of free memory\n");
00607          return strdup("into");
00608       }
00609       strsep(&dupline, " ");
00610 
00611       /* check for context existence ... */
00612       if (ast_rdlock_contexts()) {
00613          ast_log(LOG_ERROR, "Failed to lock context list\n");
00614          /* our fault, we can't check, so complete 'into' ... */
00615          ret = strdup("into");
00616       } else {
00617          struct ast_context *ctx;
00618          for (ctx = NULL; !ret && (ctx = ast_walk_contexts(ctx)); )
00619             if (!strcmp(context, ast_get_context_name(ctx)))
00620                ret = strdup("into"); /* found */
00621          ast_unlock_contexts();
00622       }
00623       free(context);
00624       return ret;
00625    } else if (a->pos == 5) { /* 'dialplan add include CTX into _X_' (dst context) */
00626       char *context, *dupline, *into;
00627       const char *s = skip_words(a->line, 3); /* should not fail */
00628       context = dupline = strdup(s);
00629       if (!dupline) {
00630          ast_log(LOG_ERROR, "Out of free memory\n");
00631          return NULL;
00632       }
00633       strsep(&dupline, " "); /* skip context */
00634       into = strsep(&dupline, " ");
00635       /* error if missing context or fifth word is not 'into' */
00636       if (!strlen(context) || strcmp(into, "into")) {
00637          ast_log(LOG_ERROR, "bad context %s or missing into %s\n",
00638             context, into);
00639          goto error3;
00640       }
00641 
00642       if (ast_rdlock_contexts()) {
00643          ast_log(LOG_ERROR, "Failed to lock context list\n");
00644          goto error3;
00645       }
00646 
00647       for (c = NULL; (c = ast_walk_contexts(c)); )
00648          if (!strcmp(context, ast_get_context_name(c)))
00649             break;
00650       if (c) { /* first context exists, go on... */
00651          /* go through all contexts ... */
00652          for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
00653             if (!strcmp(context, ast_get_context_name(c)))
00654                continue; /* skip ourselves */
00655             if (partial_match(ast_get_context_name(c), a->word, len) &&
00656                   !lookup_ci(c, context) /* not included yet */ &&
00657                   ++which > a->n)
00658                ret = strdup(ast_get_context_name(c));
00659          }
00660       } else {
00661          ast_log(LOG_ERROR, "context %s not found\n", context);
00662       }
00663       ast_unlock_contexts();
00664    error3:
00665       free(context);
00666       return ret;
00667    }
00668 
00669    return NULL;
00670 }

static char * complete_dialplan_remove_extension ( struct ast_cli_args a  )  [static]

Definition at line 398 of file pbx_config.c.

References ast_asprintf, ast_get_context_name(), ast_get_extension_cidmatch(), ast_get_extension_matchcid(), ast_get_extension_name(), ast_get_extension_priority(), ast_log(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), context, exten, free, len(), ast_cli_args::line, LOG_ERROR, ast_cli_args::n, partial_match(), ast_cli_args::pos, ast_exten::priority, skip_words(), split_ec(), strdup, and ast_cli_args::word.

Referenced by handle_cli_dialplan_remove_extension().

00399 {
00400    char *ret = NULL;
00401    int which = 0;
00402 
00403    if (a->pos == 3) { /* 'dialplan remove extension _X_' (exten@context ... */
00404       struct ast_context *c = NULL;
00405       char *context = NULL, *exten = NULL, *cid = NULL;
00406       int le = 0; /* length of extension */
00407       int lc = 0; /* length of context */
00408       int lcid = 0; /* length of cid */
00409 
00410       lc = split_ec(a->word, &exten, &context, &cid);
00411       if (lc)  { /* error */
00412          return NULL;
00413       }
00414       le = strlen(exten);
00415       lc = strlen(context);
00416       lcid = cid ? strlen(cid) : -1;
00417 
00418       if (ast_rdlock_contexts()) {
00419          ast_log(LOG_ERROR, "Failed to lock context list\n");
00420          goto error2;
00421       }
00422 
00423       /* find our context ... */
00424       while ( (c = ast_walk_contexts(c)) ) { /* match our context if any */
00425          struct ast_exten *e = NULL;
00426          /* XXX locking ? */
00427          if (!partial_match(ast_get_context_name(c), context, lc))
00428             continue;   /* context not matched */
00429          while ( (e = ast_walk_context_extensions(c, e)) ) { /* try to complete extensions ... */
00430             if ( !strchr(a->word, '/') ||
00431                   (!strchr(a->word, '@') && partial_match(ast_get_extension_cidmatch(e), cid, lcid)) ||
00432                   (strchr(a->word, '@') && !strcmp(ast_get_extension_cidmatch(e), cid))) {
00433                if ( ((strchr(a->word, '/') || strchr(a->word, '@')) && !strcmp(ast_get_extension_name(e), exten)) ||
00434                    (!strchr(a->word, '/') && !strchr(a->word, '@') && partial_match(ast_get_extension_name(e), exten, le))) { /* n-th match */
00435                   if (++which > a->n) {
00436                      /* If there is an extension then return exten@context. */
00437                      if (ast_get_extension_matchcid(e) && (!strchr(a->word, '@') || strchr(a->word, '/'))) {
00438                         if (ast_asprintf(&ret, "%s/%s@%s", ast_get_extension_name(e), ast_get_extension_cidmatch(e), ast_get_context_name(c)) < 0) {
00439                            ret = NULL;
00440                         }
00441                         break;
00442                      } else if (!ast_get_extension_matchcid(e) && !strchr(a->word, '/')) {
00443                         if (ast_asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c)) < 0) {
00444                            ret = NULL;
00445                         }
00446                         break;
00447                      }
00448                   }
00449                }
00450             }
00451          }
00452          if (e)   /* got a match */
00453             break;
00454       }
00455 
00456       ast_unlock_contexts();
00457    error2:
00458       free(exten);
00459    } else if (a->pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */
00460       char *exten = NULL, *context, *cid, *p;
00461       struct ast_context *c;
00462       int le, lc, len;
00463       const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'extension' */
00464       int i = split_ec(s, &exten, &context, &cid); /* parse ext@context */
00465 
00466       if (i)   /* error */
00467          goto error3;
00468       if ( (p = strchr(exten, ' ')) ) /* remove space after extension */
00469          *p = '\0';
00470       if ( (p = strchr(context, ' ')) ) /* remove space after context */
00471          *p = '\0';
00472       le = strlen(exten);
00473       lc = strlen(context);
00474       len = strlen(a->word);
00475       if (le == 0 || lc == 0)
00476          goto error3;
00477 
00478       if (ast_rdlock_contexts()) {
00479          ast_log(LOG_ERROR, "Failed to lock context list\n");
00480          goto error3;
00481       }
00482 
00483       /* walk contexts */
00484       c = NULL;
00485       while ( (c = ast_walk_contexts(c)) ) {
00486          /* XXX locking on c ? */
00487          struct ast_exten *e;
00488          if (strcmp(ast_get_context_name(c), context) != 0)
00489             continue;
00490          /* got it, we must match here */
00491          e = NULL;
00492          while ( (e = ast_walk_context_extensions(c, e)) ) {
00493             struct ast_exten *priority;
00494             char buffer[10];
00495 
00496             if (cid && strcmp(ast_get_extension_cidmatch(e), cid) != 0) {
00497                continue;
00498             }
00499             if (strcmp(ast_get_extension_name(e), exten) != 0)
00500                continue;
00501             /* XXX lock e ? */
00502             priority = NULL;
00503             while ( !ret && (priority = ast_walk_extension_priorities(e, priority)) ) {
00504                snprintf(buffer, sizeof(buffer), "%u", ast_get_extension_priority(priority));
00505                if (partial_match(buffer, a->word, len) && ++which > a->n) /* n-th match */
00506                   ret = strdup(buffer);
00507             }
00508             break;
00509          }
00510          break;
00511       }
00512       ast_unlock_contexts();
00513    error3:
00514       free(exten);
00515    }
00516    return ret; 
00517 }

static char * complete_dialplan_remove_ignorepat ( struct ast_cli_args a  )  [static]

Definition at line 1208 of file pbx_config.c.

References ast_get_context_name(), ast_get_ignorepat_name(), ast_log(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_ignorepats(), ast_walk_contexts(), free, len(), ast_cli_args::line, LOG_WARNING, lookup_c_ip(), ast_cli_args::n, partial_match(), ast_cli_args::pos, strdup, and ast_cli_args::word.

Referenced by handle_cli_dialplan_remove_ignorepat().

01209 {
01210    struct ast_context *c;
01211    int which = 0;
01212    char *ret = NULL;
01213 
01214    if (a->pos == 3) {
01215       int len = strlen(a->word);
01216       if (ast_rdlock_contexts()) {
01217          ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01218          return NULL;
01219       }
01220 
01221       for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
01222          struct ast_ignorepat *ip;
01223 
01224          if (ast_rdlock_context(c)) /* error, skip it */
01225             continue;
01226          
01227          for (ip = NULL; !ret && (ip = ast_walk_context_ignorepats(c, ip));) {
01228             if (partial_match(ast_get_ignorepat_name(ip), a->word, len) && ++which > a->n) {
01229                /* n-th match */
01230                struct ast_context *cw = NULL;
01231                int found = 0;
01232                while ( (cw = ast_walk_contexts(cw)) && cw != c && !found) {
01233                   /* XXX do i stop on c, or skip it ? */
01234                   found = lookup_c_ip(cw, ast_get_ignorepat_name(ip));
01235                }
01236                if (!found)
01237                   ret = strdup(ast_get_ignorepat_name(ip));
01238             }
01239          }
01240          ast_unlock_context(c);
01241       }
01242       ast_unlock_contexts();
01243       return ret;
01244    } else if (a->pos == 4) {
01245        return a->n == 0 ? strdup("from") : NULL;
01246    } else if (a->pos == 5) { /* XXX check this */
01247       char *dupline, *duplinet, *ignorepat;
01248       int len = strlen(a->word);
01249 
01250       dupline = strdup(a->line);
01251       if (!dupline) {
01252          ast_log(LOG_WARNING, "Out of free memory\n");
01253          return NULL;
01254       }
01255 
01256       duplinet = dupline;
01257       strsep(&duplinet, " ");
01258       strsep(&duplinet, " ");
01259       ignorepat = strsep(&duplinet, " ");
01260 
01261       if (!ignorepat) {
01262          free(dupline);
01263          return NULL;
01264       }
01265 
01266       if (ast_rdlock_contexts()) {
01267          ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01268          free(dupline);
01269          return NULL;
01270       }
01271 
01272       for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
01273          if (ast_rdlock_context(c)) /* fail, skip it */
01274             continue;
01275          if (!partial_match(ast_get_context_name(c), a->word, len))
01276             continue;
01277          if (lookup_c_ip(c, ignorepat) && ++which > a->n)
01278             ret = strdup(ast_get_context_name(c));
01279          ast_unlock_context(c);
01280       }
01281       ast_unlock_contexts();
01282       free(dupline);
01283       return NULL;
01284    }
01285 
01286    return NULL;
01287 }

static char * complete_dialplan_remove_include ( struct ast_cli_args a  )  [static]

Definition at line 188 of file pbx_config.c.

References ast_get_context_name(), ast_get_include_name(), ast_log(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_includes(), ast_walk_contexts(), ast_wrlock_contexts(), context, free, len(), ast_cli_args::line, LOG_ERROR, LOG_WARNING, lookup_ci(), ast_cli_args::n, partial_match(), ast_cli_args::pos, skip_words(), strdup, and ast_cli_args::word.

Referenced by handle_cli_dialplan_remove_include().

00189 {
00190    int which = 0;
00191    char *res = NULL;
00192    int len = strlen(a->word); /* how many bytes to match */
00193    struct ast_context *c = NULL;
00194 
00195    if (a->pos == 3) {      /* "dialplan remove include _X_" */
00196       if (ast_wrlock_contexts()) {
00197          ast_log(LOG_ERROR, "Failed to lock context list\n");
00198          return NULL;
00199       }
00200       /* walk contexts and their includes, return the n-th match */
00201       while (!res && (c = ast_walk_contexts(c))) {
00202          struct ast_include *i = NULL;
00203 
00204          if (ast_rdlock_context(c)) /* error ? skip this one */
00205             continue;
00206 
00207          while ( !res && (i = ast_walk_context_includes(c, i)) ) {
00208             const char *i_name = ast_get_include_name(i);
00209             struct ast_context *nc = NULL;
00210             int already_served = 0;
00211 
00212             if (!partial_match(i_name, a->word, len))
00213                continue;   /* not matched */
00214 
00215             /* check if this include is already served or not */
00216 
00217             /* go through all contexts again till we reach actual
00218              * context or already_served = 1
00219              */
00220             while ( (nc = ast_walk_contexts(nc)) && nc != c && !already_served)
00221                already_served = lookup_ci(nc, i_name);
00222 
00223             if (!already_served && ++which > a->n)
00224                res = strdup(i_name);
00225          }
00226          ast_unlock_context(c);
00227       }
00228 
00229       ast_unlock_contexts();
00230       return res;
00231    } else if (a->pos == 4) { /* "dialplan remove include CTX _X_" */
00232       /*
00233        * complete as 'from', but only if previous context is really
00234        * included somewhere
00235        */
00236       char *context, *dupline;
00237       const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'include' */
00238 
00239       if (a->n > 0)
00240          return NULL;
00241       context = dupline = strdup(s);
00242       if (!dupline) {
00243          ast_log(LOG_ERROR, "Out of free memory\n");
00244          return NULL;
00245       }
00246       strsep(&dupline, " ");
00247 
00248       if (ast_rdlock_contexts()) {
00249          ast_log(LOG_ERROR, "Failed to lock contexts list\n");
00250          free(context);
00251          return NULL;
00252       }
00253 
00254       /* go through all contexts and check if is included ... */
00255       while (!res && (c = ast_walk_contexts(c)))
00256          if (lookup_ci(c, context)) /* context is really included, complete "from" command */
00257             res = strdup("from");
00258       ast_unlock_contexts();
00259       if (!res)
00260          ast_log(LOG_WARNING, "%s not included anywhere\n", context);
00261       free(context);
00262       return res;
00263    } else if (a->pos == 5) { /* "dialplan remove include CTX from _X_" */
00264       /*
00265        * Context from which we removing include ... 
00266        */
00267       char *context, *dupline, *from;
00268       const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'include' */
00269       context = dupline = strdup(s);
00270       if (!dupline) {
00271          ast_log(LOG_ERROR, "Out of free memory\n");
00272          return NULL;
00273       }
00274 
00275       strsep(&dupline, " "); /* skip context */
00276 
00277       /* fourth word must be 'from' */
00278       from = strsep(&dupline, " ");
00279       if (!from || strcmp(from, "from")) {
00280          free(context);
00281          return NULL;
00282       }
00283 
00284       if (ast_rdlock_contexts()) {
00285          ast_log(LOG_ERROR, "Failed to lock context list\n");
00286          free(context);
00287          return NULL;
00288       }
00289 
00290       /* walk through all contexts ... */
00291       c = NULL;
00292       while ( !res && (c = ast_walk_contexts(c))) {
00293          const char *c_name = ast_get_context_name(c);
00294          if (!partial_match(c_name, a->word, len)) /* not a good target */
00295             continue;
00296          /* walk through all includes and check if it is our context */ 
00297          if (lookup_ci(c, context) && ++which > a->n)
00298             res = strdup(c_name);
00299       }
00300       ast_unlock_contexts();
00301       free(context);
00302       return res;
00303    }
00304 
00305    return NULL;
00306 }

static char* handle_cli_dialplan_add_extension ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

ADD EXTENSION command stuff.

Definition at line 907 of file pbx_config.c.

References app, ast_cli_args::argc, ast_cli_args::argv, ast_add_extension(), ast_cli(), ast_free_ptr(), ast_strdup, ast_strdupa, ast_exten::cidmatch, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_dialplan_add_extension(), errno, exten, ast_cli_args::fd, PRIORITY_HINT, and ast_cli_entry::usage.

00908 {
00909    char *whole_exten;
00910    char *exten, *prior;
00911    int iprior = -2;
00912    char *cidmatch, *app, *app_data;
00913    char *start, *end;
00914 
00915    switch (cmd) {
00916    case CLI_INIT:
00917       e->command = "dialplan add extension";
00918       e->usage =
00919          "Usage: dialplan add extension <exten>,<priority>,<app> into <context> [replace]\n"
00920          "\n"
00921          "       app can be either:\n"
00922          "         app-name\n"
00923          "         app-name(app-data)\n"
00924          "         app-name,<app-data>\n"
00925          "\n"
00926          "       This command will add the new extension into <context>.  If\n"
00927          "       an extension with the same priority already exists and the\n"
00928          "       'replace' option is given we will replace the extension.\n"
00929          "\n"
00930          "Example: dialplan add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n"
00931          "         Now, you can dial 6123 and talk to Markster :)\n";
00932       return NULL;
00933    case CLI_GENERATE:
00934       return complete_dialplan_add_extension(a);
00935    }
00936 
00937    /* check for arguments at first */
00938    if (a->argc != 6 && a->argc != 7)
00939       return CLI_SHOWUSAGE;
00940    if (strcmp(a->argv[4], "into"))
00941       return CLI_SHOWUSAGE;
00942    if (a->argc == 7)
00943       if (strcmp(a->argv[6], "replace"))
00944          return CLI_SHOWUSAGE;
00945 
00946    whole_exten = ast_strdupa(a->argv[3]);
00947    exten = strsep(&whole_exten,",");
00948    if (strchr(exten, '/')) {
00949       cidmatch = exten;
00950       strsep(&cidmatch,"/");
00951    } else {
00952       cidmatch = NULL;
00953    }
00954    prior = strsep(&whole_exten,",");
00955    if (prior) {
00956       if (!strcmp(prior, "hint")) {
00957          iprior = PRIORITY_HINT;
00958       } else {
00959          if (sscanf(prior, "%30d", &iprior) != 1) {
00960             ast_cli(a->fd, "'%s' is not a valid priority\n", prior);
00961             prior = NULL;
00962          }
00963       }
00964    }
00965    app = whole_exten;
00966    if (app) {
00967       if ((start = strchr(app, '(')) && (end = strrchr(app, ')'))) {
00968          *start = *end = '\0';
00969          app_data = start + 1;
00970       } else {
00971          app_data = strchr(app, ',');
00972          if (app_data) {
00973             *app_data++ = '\0';
00974          }
00975       }
00976    } else {
00977       app_data = NULL;
00978    }
00979 
00980    if (!exten || !prior || !app) {
00981       return CLI_SHOWUSAGE;
00982    }
00983 
00984    if (!app_data)
00985       app_data="";
00986    if (ast_add_extension(a->argv[5], a->argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
00987       ast_strdup(app_data), ast_free_ptr, registrar)) {
00988       switch (errno) {
00989       case ENOMEM:
00990          ast_cli(a->fd, "Out of free memory\n");
00991          break;
00992 
00993       case EBUSY:
00994          ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n");
00995          break;
00996 
00997       case ENOENT:
00998          ast_cli(a->fd, "No existence of '%s' context\n", a->argv[5]);
00999          break;
01000 
01001       case EEXIST:
01002          ast_cli(a->fd, "Extension %s@%s with priority %s already exists\n",
01003             exten, a->argv[5], prior);
01004          break;
01005 
01006       default:
01007          ast_cli(a->fd, "Failed to add '%s,%s,%s(%s)' extension into '%s' context\n",
01008                exten, prior, app, app_data, a->argv[5]);
01009          break;
01010       }
01011       return CLI_FAILURE;
01012    }
01013 
01014    if (a->argc == 7) {
01015       ast_cli(a->fd, "Extension %s@%s (%s) replace by '%s,%s,%s(%s)'\n",
01016          exten, a->argv[5], prior, exten, prior, app, app_data);
01017    } else {
01018       ast_cli(a->fd, "Extension '%s,%s,%s(%s)' added into '%s' context\n",
01019          exten, prior, app, app_data, a->argv[5]);
01020    }
01021 
01022    return CLI_SUCCESS;
01023 }

static char* handle_cli_dialplan_add_ignorepat ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

IGNOREPAT CLI stuff

Definition at line 1058 of file pbx_config.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_context_add_ignorepat(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_dialplan_add_ignorepat(), errno, ast_cli_args::fd, and ast_cli_entry::usage.

01059 {
01060    switch (cmd) {
01061    case CLI_INIT:
01062       e->command = "dialplan add ignorepat";
01063       e->usage =
01064          "Usage: dialplan add ignorepat <pattern> into <context>\n"
01065          "       This command adds a new ignore pattern into context <context>\n"
01066          "\n"
01067          "Example: dialplan add ignorepat _3XX into local\n";
01068       return NULL;
01069    case CLI_GENERATE:
01070       return complete_dialplan_add_ignorepat(a);
01071    }
01072 
01073    if (a->argc != 6)
01074       return CLI_SHOWUSAGE;
01075 
01076    if (strcmp(a->argv[4], "into"))
01077       return CLI_SHOWUSAGE;
01078 
01079    if (ast_context_add_ignorepat(a->argv[5], a->argv[3], registrar)) {
01080       switch (errno) {
01081       case ENOMEM:
01082          ast_cli(a->fd, "Out of free memory\n");
01083          break;
01084 
01085       case ENOENT:
01086          ast_cli(a->fd, "There is no existence of '%s' context\n", a->argv[5]);
01087          break;
01088 
01089       case EEXIST:
01090          ast_cli(a->fd, "Ignore pattern '%s' already included in '%s' context\n",
01091             a->argv[3], a->argv[5]);
01092          break;
01093 
01094       case EBUSY:
01095          ast_cli(a->fd, "Failed to lock context(s) list, please, try again later\n");
01096          break;
01097 
01098       default:
01099          ast_cli(a->fd, "Failed to add ingore pattern '%s' into '%s' context\n",
01100             a->argv[3], a->argv[5]);
01101          break;
01102       }
01103       return CLI_FAILURE;
01104    }
01105 
01106    ast_cli(a->fd, "Ignore pattern '%s' added into '%s' context\n",
01107       a->argv[3], a->argv[5]);
01108 
01109    return CLI_SUCCESS;
01110 }

static char* handle_cli_dialplan_add_include ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Include context ...

Definition at line 522 of file pbx_config.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_context_add_include(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_dialplan_add_include(), errno, ast_cli_args::fd, and ast_cli_entry::usage.

00523 {
00524    switch (cmd) {
00525    case CLI_INIT:
00526       e->command = "dialplan add include";
00527       e->usage =
00528          "Usage: dialplan add include <context> into <context>\n"
00529          "       Include a context in another context.\n";
00530       return NULL;
00531    case CLI_GENERATE:
00532       return complete_dialplan_add_include(a);
00533    }
00534 
00535    if (a->argc != 6) /* dialplan add include CTX in CTX */
00536       return CLI_SHOWUSAGE;
00537 
00538    /* fifth arg must be 'into' ... */
00539    if (strcmp(a->argv[4], "into"))
00540       return CLI_SHOWUSAGE;
00541 
00542    if (ast_context_add_include(a->argv[5], a->argv[3], registrar)) {
00543       switch (errno) {
00544       case ENOMEM:
00545          ast_cli(a->fd, "Out of memory for context addition\n");
00546          break;
00547 
00548       case EBUSY:
00549          ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n");
00550          break;
00551 
00552       case EEXIST:
00553          ast_cli(a->fd, "Context '%s' already included in '%s' context\n",
00554             a->argv[3], a->argv[5]);
00555          break;
00556 
00557       case ENOENT:
00558       case EINVAL:
00559          ast_cli(a->fd, "There is no existence of context '%s'\n",
00560             errno == ENOENT ? a->argv[5] : a->argv[3]);
00561          break;
00562 
00563       default:
00564          ast_cli(a->fd, "Failed to include '%s' in '%s' context\n",
00565             a->argv[3], a->argv[5]);
00566          break;
00567       }
00568       return CLI_FAILURE;
00569    }
00570 
00571    /* show some info ... */
00572    ast_cli(a->fd, "Context '%s' included in '%s' context\n",
00573       a->argv[3], a->argv[5]);
00574 
00575    return CLI_SUCCESS;
00576 }

static char* handle_cli_dialplan_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1291 of file pbx_config.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pbx_builtin_clear_globals(), pbx_load_module(), and ast_cli_entry::usage.

01292 {
01293    switch (cmd) {
01294    case CLI_INIT:
01295       e->command = "dialplan reload";
01296       e->usage =
01297          "Usage: dialplan reload\n"
01298          "       Reload extensions.conf without reloading any other\n"
01299          "       modules.  This command does not delete global variables\n"
01300          "       unless clearglobalvars is set to yes in extensions.conf\n";
01301       return NULL;
01302    case CLI_GENERATE:
01303       return NULL;
01304    }
01305 
01306    if (a->argc != 2)
01307       return CLI_SHOWUSAGE;
01308 
01309    if (clearglobalvars_config)
01310       pbx_builtin_clear_globals();
01311 
01312    pbx_load_module();
01313    ast_cli(a->fd, "Dialplan reloaded.\n");
01314    return CLI_SUCCESS;
01315 }

static char* handle_cli_dialplan_remove_extension ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

REMOVE EXTENSION command stuff

Definition at line 311 of file pbx_config.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_context_remove_extension_callerid(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_dialplan_remove_extension(), context, exten, ast_cli_args::fd, free, PRIORITY_HINT, split_ec(), and ast_cli_entry::usage.

00312 {
00313    int removing_priority = 0;
00314    char *exten, *context, *cid;
00315    char *ret = CLI_FAILURE;
00316 
00317    switch (cmd) {
00318    case CLI_INIT:
00319       e->command = "dialplan remove extension";
00320       e->usage =
00321          "Usage: dialplan remove extension exten[/cid]@context [priority]\n"
00322          "       Remove an extension from a given context. If a priority\n"
00323          "       is given, only that specific priority from the given extension\n"
00324          "       will be removed.\n";
00325       return NULL;
00326    case CLI_GENERATE:
00327       return complete_dialplan_remove_extension(a);
00328    }
00329 
00330    if (a->argc != 5 && a->argc != 4)
00331       return CLI_SHOWUSAGE;
00332 
00333    /*
00334     * Priority input checking ...
00335     */
00336    if (a->argc == 5) {
00337       const char *c = a->argv[4];
00338 
00339       /* check for digits in whole parameter for right priority ...
00340        * why? because atoi (strtol) returns 0 if any characters in
00341        * string and whole extension will be removed, it's not good
00342        */
00343       if (!strcmp("hint", c))
00344          removing_priority = PRIORITY_HINT;
00345       else {
00346          while (*c && isdigit(*c))
00347             c++;
00348          if (*c) { /* non-digit in string */
00349             ast_cli(a->fd, "Invalid priority '%s'\n", a->argv[4]);
00350             return CLI_FAILURE;
00351          }
00352          removing_priority = atoi(a->argv[4]);
00353       }
00354 
00355       if (removing_priority == 0) {
00356          ast_cli(a->fd, "If you want to remove whole extension, please " \
00357             "omit priority argument\n");
00358          return CLI_FAILURE;
00359       }
00360    }
00361 
00362    /* XXX original overwrote argv[3] */
00363    /*
00364     * Format exten@context checking ...
00365     */
00366    if (split_ec(a->argv[3], &exten, &context, &cid))
00367       return CLI_FAILURE; /* XXX malloc failure */
00368    if ((!strlen(exten)) || (!(strlen(context)))) {
00369       ast_cli(a->fd, "Missing extension or context name in third argument '%s'\n",
00370          a->argv[3]);
00371       free(exten);
00372       return CLI_FAILURE;
00373    }
00374 
00375    if (!ast_context_remove_extension_callerid(context, exten, removing_priority,
00376          /* Do NOT substitute S_OR; it is NOT the same thing */
00377          cid ? cid : (removing_priority ? "" : NULL), cid ? 1 : 0, registrar)) {
00378       if (!removing_priority)
00379          ast_cli(a->fd, "Whole extension %s@%s removed\n",
00380             exten, context);
00381       else
00382          ast_cli(a->fd, "Extension %s@%s with priority %d removed\n",
00383             exten, context, removing_priority);
00384          
00385       ret = CLI_SUCCESS;
00386    } else {
00387       if (cid) {
00388          ast_cli(a->fd, "Failed to remove extension %s/%s@%s\n", exten, cid, context);
00389       } else {
00390          ast_cli(a->fd, "Failed to remove extension %s@%s\n", exten, context);
00391       }
00392       ret = CLI_FAILURE;
00393    }
00394    free(exten);
00395    return ret;
00396 }

static char* handle_cli_dialplan_remove_ignorepat ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1159 of file pbx_config.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_context_remove_ignorepat(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_dialplan_remove_ignorepat(), errno, ast_cli_args::fd, and ast_cli_entry::usage.

01160 {
01161    switch (cmd) {
01162    case CLI_INIT:
01163       e->command = "dialplan remove ignorepat";
01164       e->usage =
01165          "Usage: dialplan remove ignorepat <pattern> from <context>\n"
01166          "       This command removes an ignore pattern from context <context>\n"
01167          "\n"
01168          "Example: dialplan remove ignorepat _3XX from local\n";
01169       return NULL;
01170    case CLI_GENERATE:
01171       return complete_dialplan_remove_ignorepat(a);
01172    }
01173 
01174    if (a->argc != 6)
01175       return CLI_SHOWUSAGE;
01176 
01177    if (strcmp(a->argv[4], "from"))
01178       return CLI_SHOWUSAGE;
01179 
01180    if (ast_context_remove_ignorepat(a->argv[5], a->argv[3], registrar)) {
01181       switch (errno) {
01182       case EBUSY:
01183          ast_cli(a->fd, "Failed to lock context(s) list, please try again later\n");
01184          break;
01185 
01186       case ENOENT:
01187          ast_cli(a->fd, "There is no existence of '%s' context\n", a->argv[5]);
01188          break;
01189 
01190       case EINVAL:
01191          ast_cli(a->fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
01192                a->argv[3], a->argv[5]);
01193          break;
01194 
01195       default:
01196          ast_cli(a->fd, "Failed to remove ignore pattern '%s' from '%s' context\n",
01197                a->argv[3], a->argv[5]);
01198          break;
01199       }
01200       return CLI_FAILURE;
01201    }
01202 
01203    ast_cli(a->fd, "Ignore pattern '%s' removed from '%s' context\n",
01204       a->argv[3], a->argv[5]);
01205    return CLI_SUCCESS;
01206 }

static char* handle_cli_dialplan_remove_include ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

REMOVE INCLUDE command stuff

Definition at line 79 of file pbx_config.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_context_remove_include(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_dialplan_remove_include(), ast_cli_args::fd, and ast_cli_entry::usage.

00080 {
00081    switch (cmd) {
00082    case CLI_INIT:
00083       e->command = "dialplan remove include";
00084       e->usage =
00085          "Usage: dialplan remove include <context> from <context>\n"
00086          "       Remove an included context from another context.\n";
00087       return NULL;
00088    case CLI_GENERATE:
00089       return complete_dialplan_remove_include(a);
00090    }
00091 
00092    if (a->argc != 6 || strcmp(a->argv[4], "from"))
00093       return CLI_SHOWUSAGE;
00094 
00095    if (!ast_context_remove_include(a->argv[5], a->argv[3], registrar)) {
00096       ast_cli(a->fd, "We are not including '%s' into '%s' now\n",
00097          a->argv[3], a->argv[5]);
00098       return CLI_SUCCESS;
00099    }
00100 
00101    ast_cli(a->fd, "Failed to remove '%s' include from '%s' context\n",
00102       a->argv[3], a->argv[5]);
00103    return CLI_FAILURE;
00104 }

static char* handle_cli_dialplan_save ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

'save dialplan' CLI command implementation functions ...

Definition at line 675 of file pbx_config.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_config_AST_CONFIG_DIR, ast_config_destroy(), ast_config_load, ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_cidmatch(), ast_get_extension_label(), ast_get_extension_matchcid(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_mutex_lock, ast_mutex_unlock, ast_rdlock_context(), ast_rdlock_contexts(), ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_variable_browse(), ast_walk_context_extensions(), ast_walk_context_ignorepats(), ast_walk_context_includes(), ast_walk_context_switches(), ast_walk_contexts(), ast_walk_extension_priorities(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, el, ext, ast_cli_args::fd, ast_exten::label, ast_variable::name, ast_variable::next, overrideswitch, PRIORITY_HINT, PUT_CTX_HDR, save_dialplan_lock, ast_cli_entry::usage, and ast_variable::value.

00676 {
00677    char filename[256], overrideswitch[256] = "";
00678    struct ast_context *c;
00679    struct ast_config *cfg;
00680    struct ast_variable *v;
00681    int incomplete = 0; /* incomplete config write? */
00682    FILE *output;
00683    struct ast_flags config_flags = { 0 };
00684    const char *base, *slash;
00685 
00686    switch (cmd) {
00687    case CLI_INIT:
00688       e->command = "dialplan save";
00689       e->usage =
00690          "Usage: dialplan save [/path/to/extension/file]\n"
00691          "       Save dialplan created by pbx_config module.\n"
00692          "\n"
00693          "Example: dialplan save                 (/etc/asterisk/extensions.conf)\n"
00694          "         dialplan save /home/markster  (/home/markster/extensions.conf)\n";
00695       return NULL;
00696    case CLI_GENERATE:
00697       return NULL;
00698    }
00699 
00700    if (! (static_config && !write_protect_config)) {
00701       ast_cli(a->fd,
00702          "I can't save dialplan now, see '%s' example file.\n",
00703          config);
00704       return CLI_FAILURE;
00705    }
00706 
00707    if (a->argc != 2 && a->argc != 3)
00708       return CLI_SHOWUSAGE;
00709 
00710    if (ast_mutex_lock(&save_dialplan_lock)) {
00711       ast_cli(a->fd,
00712          "Failed to lock dialplan saving (another proccess saving?)\n");
00713       return CLI_FAILURE;
00714    }
00715    /* XXX the code here is quite loose, a pathname with .conf in it
00716     * is assumed to be a complete pathname
00717     */
00718    if (a->argc == 3) {  /* have config path. Look for *.conf */
00719       base = a->argv[2];
00720       if (!strstr(a->argv[2], ".conf")) { /*no, this is assumed to be a pathname */
00721          /* if filename ends with '/', do not add one */
00722          slash = (*(a->argv[2] + strlen(a->argv[2]) -1) == '/') ? "/" : "";
00723       } else { /* yes, complete file name */
00724          slash = "";
00725       }
00726    } else {
00727       /* no config file, default one */
00728       base = ast_config_AST_CONFIG_DIR;
00729       slash = "/";
00730    }
00731    snprintf(filename, sizeof(filename), "%s%s%s", base, slash, config);
00732 
00733    cfg = ast_config_load("extensions.conf", config_flags);
00734    if (!cfg) {
00735       ast_cli(a->fd, "Failed to load extensions.conf\n");
00736       ast_mutex_unlock(&save_dialplan_lock);
00737       return CLI_FAILURE;
00738    }
00739 
00740    /* try to lock contexts list */
00741    if (ast_rdlock_contexts()) {
00742       ast_cli(a->fd, "Failed to lock contexts list\n");
00743       ast_mutex_unlock(&save_dialplan_lock);
00744       ast_config_destroy(cfg);
00745       return CLI_FAILURE;
00746    }
00747 
00748    /* create new file ... */
00749    if (!(output = fopen(filename, "wt"))) {
00750       ast_cli(a->fd, "Failed to create file '%s'\n",
00751          filename);
00752       ast_unlock_contexts();
00753       ast_mutex_unlock(&save_dialplan_lock);
00754       ast_config_destroy(cfg);
00755       return CLI_FAILURE;
00756    }
00757 
00758    /* fireout general info */
00759    if (overrideswitch_config) {
00760       snprintf(overrideswitch, sizeof(overrideswitch), "overrideswitch=%s\n", overrideswitch_config);
00761    }
00762    fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\n%sextenpatternmatchnew=%s\n\n",
00763       static_config ? "yes" : "no",
00764       write_protect_config ? "yes" : "no",
00765                 autofallthrough_config ? "yes" : "no",
00766             clearglobalvars_config ? "yes" : "no",
00767             overrideswitch_config ? overrideswitch : "",
00768             extenpatternmatchnew_config ? "yes" : "no");
00769 
00770    if ((v = ast_variable_browse(cfg, "globals"))) {
00771       fprintf(output, "[globals]\n");
00772       while(v) {
00773          fprintf(output, "%s => %s\n", v->name, v->value);
00774          v = v->next;
00775       }
00776       fprintf(output, "\n");
00777    }
00778 
00779    ast_config_destroy(cfg);
00780    
00781 #define PUT_CTX_HDR  do { \
00782    if (!context_header_written) {   \
00783       fprintf(output, "[%s]\n", ast_get_context_name(c));   \
00784       context_header_written = 1;   \
00785    }  \
00786    } while (0)
00787 
00788    /* walk all contexts */
00789    for (c = NULL; (c = ast_walk_contexts(c)); ) {
00790       int context_header_written = 0;
00791       struct ast_exten *ext, *last_written_e = NULL;
00792       struct ast_include *i;
00793       struct ast_ignorepat *ip;
00794       struct ast_sw *sw;
00795 
00796       /* try to lock context and fireout all info */  
00797       if (ast_rdlock_context(c)) { /* lock failure */
00798          incomplete = 1;
00799          continue;
00800       }
00801       /* registered by this module? */
00802       /* XXX do we need this ? */
00803       if (!strcmp(ast_get_context_registrar(c), registrar)) {
00804          fprintf(output, "[%s]\n", ast_get_context_name(c));
00805          context_header_written = 1;
00806       }
00807 
00808       /* walk extensions ... */
00809       for (ext = NULL; (ext = ast_walk_context_extensions(c, ext)); ) {
00810          struct ast_exten *p = NULL;
00811 
00812          /* fireout priorities */
00813          while ( (p = ast_walk_extension_priorities(ext, p)) ) {
00814             if (strcmp(ast_get_extension_registrar(p), registrar) != 0) /* not this source */
00815                continue;
00816       
00817             /* make empty line between different extensions */ 
00818             if (last_written_e != NULL &&
00819                    strcmp(ast_get_extension_name(last_written_e),
00820                       ast_get_extension_name(p)))
00821                fprintf(output, "\n");
00822             last_written_e = p;
00823          
00824             PUT_CTX_HDR;
00825 
00826             if (ast_get_extension_priority(p) == PRIORITY_HINT) { /* easy */
00827                fprintf(output, "exten => %s,hint,%s\n",
00828                       ast_get_extension_name(p),
00829                       ast_get_extension_app(p));
00830             } else {
00831                const char *sep, *cid;
00832                const char *el = ast_get_extension_label(p);
00833                char label[128] = "";
00834  
00835                if (ast_get_extension_matchcid(p)) {
00836                   sep = "/";
00837                   cid = ast_get_extension_cidmatch(p);
00838                } else
00839                   sep = cid = "";
00840             
00841                if (el && (snprintf(label, sizeof(label), "(%s)", el) != (strlen(el) + 2)))
00842                   incomplete = 1;   /* error encountered or label > 125 chars */
00843                
00844                fprintf(output, "exten => %s%s%s,%d%s,%s(%s)\n",
00845                    ast_get_extension_name(p), (ast_strlen_zero(sep) ? "" : sep), (ast_strlen_zero(cid) ? "" : cid),
00846                    ast_get_extension_priority(p), label,
00847                    ast_get_extension_app(p), (ast_strlen_zero(ast_get_extension_app_data(p)) ? "" : (const char *)ast_get_extension_app_data(p)));
00848             }
00849          }
00850       }
00851 
00852       /* written any extensions? ok, write space between exten & inc */
00853       if (last_written_e)
00854          fprintf(output, "\n");
00855 
00856       /* walk through includes */
00857       for (i = NULL; (i = ast_walk_context_includes(c, i)) ; ) {
00858          if (strcmp(ast_get_include_registrar(i), registrar) != 0)
00859             continue; /* not mine */
00860          PUT_CTX_HDR;
00861          fprintf(output, "include => %s\n", ast_get_include_name(i));
00862       }
00863       if (ast_walk_context_includes(c, NULL))
00864          fprintf(output, "\n");
00865 
00866       /* walk through switches */
00867       for (sw = NULL; (sw = ast_walk_context_switches(c, sw)) ; ) {
00868          if (strcmp(ast_get_switch_registrar(sw), registrar) != 0)
00869             continue; /* not mine */
00870          PUT_CTX_HDR;
00871          fprintf(output, "switch => %s/%s\n",
00872                 ast_get_switch_name(sw), ast_get_switch_data(sw));
00873       }
00874 
00875       if (ast_walk_context_switches(c, NULL))
00876          fprintf(output, "\n");
00877 
00878       /* fireout ignorepats ... */
00879       for (ip = NULL; (ip = ast_walk_context_ignorepats(c, ip)); ) {
00880          if (strcmp(ast_get_ignorepat_registrar(ip), registrar) != 0)
00881             continue; /* not mine */
00882          PUT_CTX_HDR;
00883          fprintf(output, "ignorepat => %s\n",
00884                   ast_get_ignorepat_name(ip));
00885       }
00886 
00887       ast_unlock_context(c);
00888    }  
00889 
00890    ast_unlock_contexts();
00891    ast_mutex_unlock(&save_dialplan_lock);
00892    fclose(output);
00893 
00894    if (incomplete) {
00895       ast_cli(a->fd, "Saved dialplan is incomplete\n");
00896       return CLI_FAILURE;
00897    }
00898 
00899    ast_cli(a->fd, "Dialplan successfully saved into '%s'\n",
00900       filename);
00901    return CLI_SUCCESS;
00902 }

static int load_module ( void   )  [static]
static int lookup_c_ip ( struct ast_context c,
const char *  name 
) [static]

return true if 'name' is in the ignorepats for context c

Definition at line 121 of file pbx_config.c.

References ast_get_ignorepat_name(), ast_rdlock_context(), ast_unlock_context(), and ast_walk_context_ignorepats().

Referenced by complete_dialplan_add_ignorepat(), and complete_dialplan_remove_ignorepat().

00122 {
00123    struct ast_ignorepat *ip = NULL;
00124 
00125    if (ast_rdlock_context(c)) /* error, skip */
00126       return 0;
00127    while ( (ip = ast_walk_context_ignorepats(c, ip)) )
00128       if (!strcmp(name, ast_get_ignorepat_name(ip)))
00129          break;
00130    ast_unlock_context(c);
00131    return ip ? -1 /* success */ : 0;
00132 }

static int lookup_ci ( struct ast_context c,
const char *  name 
) [static]

return true if 'name' is included by context c

Definition at line 107 of file pbx_config.c.

References ast_get_include_name(), ast_rdlock_context(), ast_unlock_context(), and ast_walk_context_includes().

Referenced by complete_dialplan_add_include(), and complete_dialplan_remove_include().

00108 {
00109    struct ast_include *i = NULL;
00110 
00111    if (ast_rdlock_context(c)) /* error, skip */
00112       return 0;
00113    while ( (i = ast_walk_context_includes(c, i)) )
00114       if (!strcmp(name, ast_get_include_name(i)))
00115          break;
00116    ast_unlock_context(c);
00117    return i ? -1 /* success */ : 0;
00118 }

static int partial_match ( const char *  s,
const char *  word,
int  len 
) [static]

match the first 'len' chars of word. len==0 always succeeds

Definition at line 150 of file pbx_config.c.

Referenced by complete_dialplan_add_extension(), complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), complete_dialplan_remove_ignorepat(), and complete_dialplan_remove_include().

00151 {
00152    return (len == 0 || !strncmp(s, word, len));
00153 }

static int pbx_load_config ( const char *  config_file  )  [static]

Definition at line 1384 of file pbx_config.c.

References ast_add_extension2(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_find_or_create(), ast_copy_string(), ast_findlabel_extension2(), ast_free, ast_free_ptr(), ast_log(), ast_opt_dont_warn, ast_shrink_phone_number(), ast_skip_blanks(), ast_strdup, ast_strip(), ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, errno, ext, ast_variable::file, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, pbx_builtin_setvar_helper(), pbx_strsep(), pbx_substitute_variables_helper(), PRIORITY_HINT, S_OR, and ast_variable::value.

Referenced by pbx_load_module().

01385 {
01386    struct ast_config *cfg;
01387    char *end;
01388    char *label;
01389 #ifdef LOW_MEMORY
01390    char realvalue[256];
01391 #else
01392    char realvalue[8192];
01393 #endif
01394    int lastpri = -2;
01395    struct ast_context *con;
01396    struct ast_variable *v;
01397    const char *cxt;
01398    const char *aft;
01399    const char *newpm, *ovsw;
01400    struct ast_flags config_flags = { 0 };
01401    char lastextension[256];
01402    cfg = ast_config_load(config_file, config_flags);
01403    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID)
01404       return 0;
01405 
01406    /* Use existing config to populate the PBX table */
01407    static_config = ast_true(ast_variable_retrieve(cfg, "general", "static"));
01408    write_protect_config = ast_true(ast_variable_retrieve(cfg, "general", "writeprotect"));
01409    if ((aft = ast_variable_retrieve(cfg, "general", "autofallthrough")))
01410       autofallthrough_config = ast_true(aft);
01411    if ((newpm = ast_variable_retrieve(cfg, "general", "extenpatternmatchnew")))
01412       extenpatternmatchnew_config = ast_true(newpm);
01413    clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
01414    if ((ovsw = ast_variable_retrieve(cfg, "general", "overrideswitch"))) {
01415       if (overrideswitch_config) {
01416          ast_free(overrideswitch_config);
01417       }
01418       if (!ast_strlen_zero(ovsw)) {
01419          overrideswitch_config = ast_strdup(ovsw);
01420       } else {
01421          overrideswitch_config = NULL;
01422       }
01423    }
01424 
01425    ast_copy_string(userscontext, ast_variable_retrieve(cfg, "general", "userscontext") ?: "default", sizeof(userscontext));
01426                             
01427    for (v = ast_variable_browse(cfg, "globals"); v; v = v->next) {
01428       pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01429       pbx_builtin_setvar_helper(NULL, v->name, realvalue);
01430    }
01431    for (cxt = ast_category_browse(cfg, NULL);
01432         cxt;
01433         cxt = ast_category_browse(cfg, cxt)) {
01434       /* All categories but "general" or "globals" are considered contexts */
01435       if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) {
01436          continue;
01437       }
01438       if (!(con = ast_context_find_or_create(&local_contexts, local_table, cxt, registrar))) {
01439          continue;
01440       }
01441 
01442       /* Reset continuation items at the beginning of each context */
01443       lastextension[0] = '\0';
01444       lastpri = -2;
01445 
01446       for (v = ast_variable_browse(cfg, cxt); v; v = v->next) {
01447          char *tc = NULL;
01448          char realext[256] = "";
01449          char *stringp, *ext;
01450          const char *vfile;
01451 
01452          /* get filename for error reporting from top level or an #include */
01453          vfile = !*v->file ? config_file : v->file;
01454 
01455          if (!strncasecmp(v->name, "same", 4)) {
01456             if (ast_strlen_zero(lastextension)) {
01457                ast_log(LOG_ERROR,
01458                   "No previous pattern in the first entry of context '%s' to match '%s' at line %d of %s!\n",
01459                   cxt, v->name, v->lineno, vfile);
01460                continue;
01461             }
01462             if ((stringp = tc = ast_strdup(v->value))) {
01463                ast_copy_string(realext, lastextension, sizeof(realext));
01464                goto process_extension;
01465             }
01466          } else if (!strcasecmp(v->name, "exten")) {
01467             int ipri;
01468             char *plus;
01469             char *pri, *appl, *data, *cidmatch;
01470 
01471             if (!(stringp = tc = ast_strdup(v->value))) {
01472                continue;
01473             }
01474 
01475             ext = S_OR(pbx_strsep(&stringp, ","), "");
01476             pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
01477             ast_copy_string(lastextension, realext, sizeof(lastextension));
01478 process_extension:
01479             ipri = -2;
01480             if ((cidmatch = strchr(realext, '/'))) {
01481                *cidmatch++ = '\0';
01482                ast_shrink_phone_number(cidmatch);
01483             }
01484             pri = ast_strip(S_OR(strsep(&stringp, ","), ""));
01485             if ((label = strchr(pri, '('))) {
01486                *label++ = '\0';
01487                if ((end = strchr(label, ')'))) {
01488                   *end = '\0';
01489                } else {
01490                   ast_log(LOG_WARNING,
01491                      "Label missing trailing ')' at line %d of %s\n",
01492                      v->lineno, vfile);
01493                   ast_free(tc);
01494                   continue;
01495                }
01496             }
01497             if ((plus = strchr(pri, '+'))) {
01498                *plus++ = '\0';
01499             }
01500             if (!strcmp(pri,"hint")) {
01501                ipri = PRIORITY_HINT;
01502             } else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
01503                if (lastpri > -2) {
01504                   ipri = lastpri + 1;
01505                } else {
01506                   ast_log(LOG_WARNING,
01507                      "Can't use 'next' priority on the first entry at line %d of %s!\n",
01508                      v->lineno, vfile);
01509                   ast_free(tc);
01510                   continue;
01511                }
01512             } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
01513                if (lastpri > -2) {
01514                   ipri = lastpri;
01515                } else {
01516                   ast_log(LOG_WARNING,
01517                      "Can't use 'same' priority on the first entry at line %d of %s!\n",
01518                      v->lineno, vfile);
01519                   ast_free(tc);
01520                   continue;
01521                }
01522             } else if (sscanf(pri, "%30d", &ipri) != 1 &&
01523                   (ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
01524                ast_log(LOG_WARNING,
01525                   "Invalid priority/label '%s' at line %d of %s\n",
01526                   pri, v->lineno, vfile);
01527                ipri = 0;
01528                ast_free(tc);
01529                continue;
01530             } else if (ipri < 1) {
01531                ast_log(LOG_WARNING, "Invalid priority '%s' at line %d of %s\n",
01532                   pri, v->lineno, vfile);
01533                ast_free(tc);
01534                continue;
01535             }
01536             appl = S_OR(stringp, "");
01537             /* Find the first occurrence of '(' */
01538             if (!strchr(appl, '(')) {
01539                /* No arguments */
01540                data = "";
01541             } else {
01542                char *orig_appl = ast_strdup(appl);
01543 
01544                if (!orig_appl) {
01545                   ast_free(tc);
01546                   continue;
01547                }
01548 
01549                appl = strsep(&stringp, "(");
01550 
01551                /* check if there are variables or expressions without an application, like: exten => 100,hint,DAHDI/g0/${GLOBAL(var)}  */
01552                if (strstr(appl, "${") || strstr(appl, "$[")){
01553                   /* set appl to original one */
01554                   strcpy(appl, orig_appl);
01555                   /* set no data */
01556                   data = "";
01557                /* no variable before application found -> go ahead */
01558                } else {
01559                   data = S_OR(stringp, "");
01560                   if ((end = strrchr(data, ')'))) {
01561                      *end = '\0';
01562                   } else {
01563                      ast_log(LOG_WARNING,
01564                         "No closing parenthesis found? '%s(%s' at line %d of %s\n",
01565                         appl, data, v->lineno, vfile);
01566                   }
01567                }
01568                ast_free(orig_appl);
01569             }
01570 
01571             appl = ast_skip_blanks(appl);
01572             if (ipri) {
01573                if (plus) {
01574                   ipri += atoi(plus);
01575                }
01576                lastpri = ipri;
01577                if (!ast_opt_dont_warn && (!strcmp(realext, "_.") || !strcmp(realext, "_!"))) {
01578                   ast_log(LOG_WARNING,
01579                      "The use of '%s' for an extension is strongly discouraged and can have unexpected behavior.  Please use '_X%c' instead at line %d of %s\n",
01580                      realext, realext[1], v->lineno, vfile);
01581                }
01582                if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, ast_strdup(data), ast_free_ptr, registrar)) {
01583                   ast_log(LOG_WARNING,
01584                      "Unable to register extension at line %d of %s\n",
01585                      v->lineno, vfile);
01586                }
01587             }
01588             ast_free(tc);
01589          } else if (!strcasecmp(v->name, "include")) {
01590             pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01591             if (ast_context_add_include2(con, realvalue, registrar)) {
01592                switch (errno) {
01593                case ENOMEM:
01594                   ast_log(LOG_WARNING, "Out of memory for context addition\n");
01595                   break;
01596 
01597                case EBUSY:
01598                   ast_log(LOG_WARNING, "Failed to lock context(s) list, please try again later\n");
01599                   break;
01600 
01601                case EEXIST:
01602                   ast_log(LOG_WARNING,
01603                      "Context '%s' already included in '%s' context on include at line %d of %s\n",
01604                      v->value, cxt, v->lineno, vfile);
01605                   break;
01606 
01607                case ENOENT:
01608                case EINVAL:
01609                   ast_log(LOG_WARNING,
01610                      "There is no existence of context '%s' included at line %d of %s\n",
01611                      errno == ENOENT ? v->value : cxt, v->lineno, vfile);
01612                   break;
01613 
01614                default:
01615                   ast_log(LOG_WARNING,
01616                      "Failed to include '%s' in '%s' context at line %d of %s\n",
01617                      v->value, cxt, v->lineno, vfile);
01618                   break;
01619                }
01620             }
01621          } else if (!strcasecmp(v->name, "ignorepat")) {
01622             pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01623             if (ast_context_add_ignorepat2(con, realvalue, registrar)) {
01624                ast_log(LOG_WARNING,
01625                   "Unable to include ignorepat '%s' in context '%s' at line %d of %s\n",
01626                   v->value, cxt, v->lineno, vfile);
01627             }
01628          } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
01629             char *stringp = realvalue;
01630             char *appl, *data;
01631             
01632             if (!strcasecmp(v->name, "switch")) {
01633                pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
01634             } else {
01635                ast_copy_string(realvalue, v->value, sizeof(realvalue));
01636             }
01637             appl = strsep(&stringp, "/");
01638             data = S_OR(stringp, "");
01639             if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar)) {
01640                ast_log(LOG_WARNING,
01641                   "Unable to include switch '%s' in context '%s' at line %d of %s\n",
01642                   v->value, cxt, v->lineno, vfile);
01643             }
01644          } else {
01645             ast_log(LOG_WARNING,
01646                "==!!== Unknown directive: %s at line %d of %s -- IGNORING!!!\n",
01647                v->name, v->lineno, vfile);
01648          }
01649       }
01650    }
01651    ast_config_destroy(cfg);
01652    return 1;
01653 }

static int pbx_load_module ( void   )  [static]

Definition at line 1771 of file pbx_config.c.

References ast_context_verify_includes(), ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_merge_contexts_and_delete(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_lock, ast_mutex_unlock, ast_walk_contexts(), pbx_load_config(), pbx_load_users(), pbx_set_autofallthrough(), pbx_set_extenpatternmatchnew(), pbx_set_overrideswitch(), and reload_lock.

Referenced by handle_cli_dialplan_reload(), load_module(), and reload().

01772 {
01773    struct ast_context *con;
01774 
01775    ast_mutex_lock(&reload_lock);
01776 
01777    if (!local_table)
01778       local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
01779 
01780    if (!pbx_load_config(config)) {
01781       ast_mutex_unlock(&reload_lock);
01782       return AST_MODULE_LOAD_DECLINE;
01783    }
01784    
01785    pbx_load_users();
01786 
01787    ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
01788    local_table = NULL; /* the local table has been moved into the global one. */
01789    local_contexts = NULL;
01790 
01791    ast_mutex_unlock(&reload_lock);
01792 
01793    for (con = NULL; (con = ast_walk_contexts(con));)
01794       ast_context_verify_includes(con);
01795 
01796    pbx_set_overrideswitch(overrideswitch_config);
01797    pbx_set_autofallthrough(autofallthrough_config);
01798    pbx_set_extenpatternmatchnew(extenpatternmatchnew_config);
01799 
01800    return AST_MODULE_LOAD_SUCCESS;
01801 }

static void pbx_load_users ( void   )  [static]

Definition at line 1667 of file pbx_config.c.

References append_interface(), ast_add_extension2(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_config_option(), ast_context_find_or_create(), ast_copy_string(), ast_free_ptr(), ast_log(), ast_strdup, ast_strlen_zero(), ast_true(), ast_variable_retrieve(), ext, and LOG_ERROR.

Referenced by pbx_load_module().

01668 {
01669    struct ast_config *cfg;
01670    char *cat, *chan;
01671    const char *dahdichan;
01672    const char *hasexten, *altexts;
01673    char tmp[256];
01674    char iface[256];
01675    char dahdicopy[256];
01676    char *ext, altcopy[256];
01677    char *c;
01678    int hasvoicemail;
01679    int start, finish, x;
01680    struct ast_context *con = NULL;
01681    struct ast_flags config_flags = { 0 };
01682    
01683    cfg = ast_config_load("users.conf", config_flags);
01684    if (!cfg)
01685       return;
01686 
01687    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
01688       if (!strcasecmp(cat, "general"))
01689          continue;
01690       iface[0] = '\0';
01691       if (ast_true(ast_config_option(cfg, cat, "hassip"))) {
01692          snprintf(tmp, sizeof(tmp), "SIP/%s", cat);
01693          append_interface(iface, sizeof(iface), tmp);
01694       }
01695       if (ast_true(ast_config_option(cfg, cat, "hasiax"))) {
01696          snprintf(tmp, sizeof(tmp), "IAX2/%s", cat);
01697          append_interface(iface, sizeof(iface), tmp);
01698       }
01699       if (ast_true(ast_config_option(cfg, cat, "hash323"))) {
01700          snprintf(tmp, sizeof(tmp), "H323/%s", cat);
01701          append_interface(iface, sizeof(iface), tmp);
01702       }
01703       hasexten = ast_config_option(cfg, cat, "hasexten");
01704       if (hasexten && !ast_true(hasexten))
01705          continue;
01706       hasvoicemail = ast_true(ast_config_option(cfg, cat, "hasvoicemail"));
01707       dahdichan = ast_variable_retrieve(cfg, cat, "dahdichan");
01708       if (!dahdichan)
01709          dahdichan = ast_variable_retrieve(cfg, "general", "dahdichan");
01710       if (!ast_strlen_zero(dahdichan)) {
01711          ast_copy_string(dahdicopy, dahdichan, sizeof(dahdicopy));
01712          c = dahdicopy;
01713          chan = strsep(&c, ",");
01714          while (chan) {
01715             if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
01716                /* Range */
01717             } else if (sscanf(chan, "%30d", &start)) {
01718                /* Just one */
01719                finish = start;
01720             } else {
01721                start = 0; finish = 0;
01722             }
01723             if (finish < start) {
01724                x = finish;
01725                finish = start;
01726                start = x;
01727             }
01728             for (x = start; x <= finish; x++) {
01729                snprintf(tmp, sizeof(tmp), "DAHDI/%d", x);
01730                append_interface(iface, sizeof(iface), tmp);
01731             }
01732             chan = strsep(&c, ",");
01733          }
01734       }
01735       if (!ast_strlen_zero(iface)) {
01736          /* Only create a context here when it is really needed. Otherwise default empty context
01737          created by pbx_config may conflict with the one explicitly created by pbx_ael */
01738          if (!con)
01739             con = ast_context_find_or_create(&local_contexts, local_table, userscontext, registrar);
01740 
01741          if (!con) {
01742             ast_log(LOG_ERROR, "Can't find/create user context '%s'\n", userscontext);
01743             return;
01744          }
01745 
01746          /* Add hint */
01747          ast_add_extension2(con, 0, cat, -1, NULL, NULL, iface, NULL, NULL, registrar);
01748          /* If voicemail, use "stdexten" else use plain old dial */
01749          if (hasvoicemail) {
01750             snprintf(tmp, sizeof(tmp), "stdexten,%s,${HINT}", cat);
01751             ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Macro", ast_strdup(tmp), ast_free_ptr, registrar);
01752          } else {
01753             ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Dial", ast_strdup("${HINT}"), ast_free_ptr, registrar);
01754          }
01755          altexts = ast_variable_retrieve(cfg, cat, "alternateexts");
01756          if (!ast_strlen_zero(altexts)) {
01757             snprintf(tmp, sizeof(tmp), "%s,1", cat);
01758             ast_copy_string(altcopy, altexts, sizeof(altcopy));
01759             c = altcopy;
01760             ext = strsep(&c, ",");
01761             while (ext) {
01762                ast_add_extension2(con, 0, ext, 1, NULL, NULL, "Goto", ast_strdup(tmp), ast_free_ptr, registrar);
01763                ext = strsep(&c, ",");
01764             }
01765          }
01766       }
01767    }
01768    ast_config_destroy(cfg);
01769 }

static char* pbx_strsep ( char **  destructible,
const char *  delim 
) [static]
Note:
Protect against misparsing based upon commas in the middle of fields like character classes. We've taken steps to permit pretty much every other printable character in a character class, so properly handling a comma at this level is a natural extension. This is almost like the standard application parser in app.c, except that it handles square brackets.

Definition at line 1354 of file pbx_config.c.

Referenced by pbx_load_config().

01355 {
01356    int square = 0;
01357    char *res;
01358 
01359    if (!destructible || !*destructible) {
01360       return NULL;
01361    }
01362    res = *destructible;
01363    for (; **destructible; (*destructible)++) {
01364       if (**destructible == '[' && !strchr(delim, '[')) {
01365          square++;
01366       } else if (**destructible == ']' && !strchr(delim, ']')) {
01367          if (square) {
01368             square--;
01369          }
01370       } else if (**destructible == '\\' && !strchr(delim, '\\')) {
01371          (*destructible)++;
01372       } else if (strchr(delim, **destructible) && !square) {
01373          **destructible = '\0';
01374          (*destructible)++;
01375          break;
01376       }
01377    }
01378    if (**destructible == '\0') {
01379       *destructible = NULL;
01380    }
01381    return res;
01382 }

static int reload ( void   )  [static]

Definition at line 1815 of file pbx_config.c.

References pbx_builtin_clear_globals(), and pbx_load_module().

01816 {
01817    if (clearglobalvars_config)
01818       pbx_builtin_clear_globals();
01819    return pbx_load_module();
01820 }

static const char* skip_words ( const char *  p,
int  n 
) [static]

moves to the n-th word in the string, or empty string if none

Definition at line 135 of file pbx_config.c.

Referenced by complete_dialplan_add_ignorepat(), complete_dialplan_add_include(), complete_dialplan_remove_extension(), and complete_dialplan_remove_include().

00136 {
00137    int in_blank = 0;
00138    for (;n && *p; p++) {
00139       if (isblank(*p) /* XXX order is important */ && !in_blank) {
00140          n--;  /* one word is gone */
00141          in_blank = 1;
00142       } else if (/* !is_blank(*p), we know already, && */ in_blank) {
00143          in_blank = 0;
00144       }
00145    }
00146    return p;
00147 }

static int split_ec ( const char *  src,
char **  ext,
char **const   ctx,
char **const   cid 
) [static]

split extension@context in two parts, return -1 on error. The return string is malloc'ed and pointed by *ext

Definition at line 158 of file pbx_config.c.

References ast_strdup, and free.

Referenced by complete_dialplan_remove_extension(), and handle_cli_dialplan_remove_extension().

00159 {
00160    char *i, *c, *e = ast_strdup(src); /* now src is not used anymore */
00161 
00162    if (e == NULL)
00163       return -1;  /* malloc error */
00164    /* now, parse values from 'exten@context' */
00165    *ext = e;
00166    c = strchr(e, '@');
00167    if (c == NULL) /* no context part */
00168       *ctx = "";  /* it is not overwritten, anyways */
00169    else {   /* found context, check for duplicity ... */
00170       *c++ = '\0';
00171       *ctx = c;
00172       if (strchr(c, '@')) { /* two @, not allowed */
00173          free(e);
00174          return -1;
00175       }
00176    }
00177    if (cid && (i = strchr(e, '/'))) {
00178       *i++ = '\0';
00179       *cid = i;
00180    } else if (cid) {
00181       /* Signal none detected */
00182       *cid = NULL;
00183    }
00184    return 0;
00185 }

static int unload_module ( void   )  [static]

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Text Extension Configuration" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1826 of file pbx_config.c.

Definition at line 1826 of file pbx_config.c.

int autofallthrough_config = 1 [static]

Definition at line 51 of file pbx_config.c.

int clearglobalvars_config = 0 [static]

Definition at line 52 of file pbx_config.c.

Initial value:

Definition at line 1331 of file pbx_config.c.

struct ast_cli_entry cli_pbx_config[] [static]

CLI entries for commands provided by this module

Definition at line 1320 of file pbx_config.c.

const char config[] = "extensions.conf" [static]

Definition at line 45 of file pbx_config.c.

int extenpatternmatchnew_config = 0 [static]

Definition at line 53 of file pbx_config.c.

struct ast_context* local_contexts = NULL [static]

Definition at line 60 of file pbx_config.c.

Referenced by ast_context_find_or_create(), and pbx_load_module().

struct ast_hashtab* local_table = NULL [static]

Definition at line 61 of file pbx_config.c.

Referenced by pbx_load_module().

char* overrideswitch_config = NULL [static]

Definition at line 54 of file pbx_config.c.

const char registrar[] = "pbx_config" [static]

Definition at line 46 of file pbx_config.c.

ast_mutex_t reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 58 of file pbx_config.c.

Referenced by pbx_load_module().

ast_mutex_t save_dialplan_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 56 of file pbx_config.c.

Referenced by handle_cli_dialplan_save().

int static_config = 0 [static]

Definition at line 49 of file pbx_config.c.

char userscontext[AST_MAX_EXTENSION] = "default" [static]

Definition at line 47 of file pbx_config.c.

int write_protect_config = 1 [static]

Definition at line 50 of file pbx_config.c.


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1