Sat Mar 10 01:55:35 2012

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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 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

Referenced by handle_cli_dialplan_save().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1803 of file pbx_config.c.

static void __unreg_module ( void   )  [static]

Definition at line 1803 of file pbx_config.c.

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

Definition at line 1638 of file pbx_config.c.

References len().

Referenced by pbx_load_users().

01639 {
01640    int len = strlen(iface);
01641    if (strlen(add) + len < maxlen - 2) {
01642       if (strlen(iface)) {
01643          iface[len] = '&';
01644          strcpy(iface + len + 1, add);
01645       } else
01646          strcpy(iface, add);
01647    }
01648 }

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 1014 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().

01015 {
01016    int which = 0;
01017 
01018    if (a->pos == 4) {      /* complete 'into' word ... */
01019       return (a->n == 0) ? strdup("into") : NULL;
01020    } else if (a->pos == 5) { /* complete context */
01021       struct ast_context *c = NULL;
01022       int len = strlen(a->word);
01023       char *res = NULL;
01024 
01025       /* try to lock contexts list ... */
01026       if (ast_rdlock_contexts()) {
01027          ast_log(LOG_WARNING, "Failed to lock contexts list\n");
01028          return NULL;
01029       }
01030 
01031       /* walk through all contexts */
01032       while ( !res && (c = ast_walk_contexts(c)) )
01033          if (partial_match(ast_get_context_name(c), a->word, len) && ++which > a->n)
01034             res = strdup(ast_get_context_name(c));
01035       ast_unlock_contexts();
01036       return res;
01037    } else if (a->pos == 6) {
01038       return a->n == 0 ? strdup("replace") : NULL;
01039    }
01040    return NULL;
01041 }

static char * complete_dialplan_add_ignorepat ( struct ast_cli_args  )  [static]

Definition at line 1100 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, strsep(), and ast_cli_args::word.

Referenced by handle_cli_dialplan_add_ignorepat().

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

static char * complete_dialplan_add_include ( struct ast_cli_args  )  [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, strsep(), 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  )  [static]

Definition at line 396 of file pbx_config.c.

References 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, errno, exten, free, len(), ast_cli_args::line, LOG_ERROR, LOG_WARNING, 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().

00397 {
00398    char *ret = NULL;
00399    int which = 0;
00400 
00401    if (a->pos == 3) { /* 'dialplan remove extension _X_' (exten@context ... */
00402       struct ast_context *c = NULL;
00403       char *context = NULL, *exten = NULL, *cid = NULL;
00404       int le = 0; /* length of extension */
00405       int lc = 0; /* length of context */
00406       int lcid = 0; /* length of cid */
00407 
00408       lc = split_ec(a->word, &exten, &context, &cid);
00409       if (lc)  { /* error */
00410          return NULL;
00411       }
00412       le = strlen(exten);
00413       lc = strlen(context);
00414       lcid = cid ? strlen(cid) : -1;
00415 
00416       if (ast_rdlock_contexts()) {
00417          ast_log(LOG_ERROR, "Failed to lock context list\n");
00418          goto error2;
00419       }
00420 
00421       /* find our context ... */
00422       while ( (c = ast_walk_contexts(c)) ) { /* match our context if any */
00423          struct ast_exten *e = NULL;
00424          /* XXX locking ? */
00425          if (!partial_match(ast_get_context_name(c), context, lc))
00426             continue;   /* context not matched */
00427          while ( (e = ast_walk_context_extensions(c, e)) ) { /* try to complete extensions ... */
00428             if ( !strchr(a->word, '/') ||
00429                   (!strchr(a->word, '@') && partial_match(ast_get_extension_cidmatch(e), cid, lcid)) ||
00430                   (strchr(a->word, '@') && !strcmp(ast_get_extension_cidmatch(e), cid))) {
00431                if ( ((strchr(a->word, '/') || strchr(a->word, '@')) && !strcmp(ast_get_extension_name(e), exten)) ||
00432                    (!strchr(a->word, '/') && !strchr(a->word, '@') && partial_match(ast_get_extension_name(e), exten, le))) { /* n-th match */
00433                   if (++which > a->n) {
00434                      /* If there is an extension then return exten@context. */
00435                      if (ast_get_extension_matchcid(e) && (!strchr(a->word, '@') || strchr(a->word, '/'))) {
00436                         if (asprintf(&ret, "%s/%s@%s", ast_get_extension_name(e), ast_get_extension_cidmatch(e), ast_get_context_name(c)) < 0) {
00437                            ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00438                            ret = NULL;
00439                         }
00440                         break;
00441                      } else if (!ast_get_extension_matchcid(e) && !strchr(a->word, '/')) {
00442                         if (asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c)) < 0) {
00443                            ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
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  )  [static]

Definition at line 1196 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, strsep(), and ast_cli_args::word.

Referenced by handle_cli_dialplan_remove_ignorepat().

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

static char * complete_dialplan_remove_include ( struct ast_cli_args  )  [static]

Definition at line 186 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, strsep(), and ast_cli_args::word.

Referenced by handle_cli_dialplan_remove_include().

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

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 902 of file pbx_config.c.

References app, ast_cli_args::argc, ast_cli_args::argv, ast_add_extension(), ast_cli(), ast_free_ptr, ast_strdupa, 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, strdup, strsep(), and ast_cli_entry::usage.

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

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 1046 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.

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

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 1279 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.

01280 {
01281    switch (cmd) {
01282    case CLI_INIT:
01283       e->command = "dialplan reload";
01284       e->usage =
01285          "Usage: dialplan reload\n"
01286          "       Reload extensions.conf without reloading any other\n"
01287          "       modules.  This command does not delete global variables\n"
01288          "       unless clearglobalvars is set to yes in extensions.conf\n";
01289       return NULL;
01290    case CLI_GENERATE:
01291       return NULL;
01292    }
01293 
01294    if (a->argc != 2)
01295       return CLI_SHOWUSAGE;
01296 
01297    if (clearglobalvars_config)
01298       pbx_builtin_clear_globals();
01299 
01300    pbx_load_module();
01301    ast_cli(a->fd, "Dialplan reloaded.\n");
01302    return CLI_SUCCESS;
01303 }

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 309 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.

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

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

Definition at line 1147 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.

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

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 77 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.

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

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, config_flags, el, ext, ast_cli_args::fd, 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 
00735    /* try to lock contexts list */
00736    if (ast_rdlock_contexts()) {
00737       ast_cli(a->fd, "Failed to lock contexts list\n");
00738       ast_mutex_unlock(&save_dialplan_lock);
00739       ast_config_destroy(cfg);
00740       return CLI_FAILURE;
00741    }
00742 
00743    /* create new file ... */
00744    if (!(output = fopen(filename, "wt"))) {
00745       ast_cli(a->fd, "Failed to create file '%s'\n",
00746          filename);
00747       ast_unlock_contexts();
00748       ast_mutex_unlock(&save_dialplan_lock);
00749       ast_config_destroy(cfg);
00750       return CLI_FAILURE;
00751    }
00752 
00753    /* fireout general info */
00754    if (overrideswitch_config) {
00755       snprintf(overrideswitch, sizeof(overrideswitch), "overrideswitch=%s\n", overrideswitch_config);
00756    }
00757    fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\n%sextenpatternmatchnew=%s\n\n",
00758       static_config ? "yes" : "no",
00759       write_protect_config ? "yes" : "no",
00760                 autofallthrough_config ? "yes" : "no",
00761             clearglobalvars_config ? "yes" : "no",
00762             overrideswitch_config ? overrideswitch : "",
00763             extenpatternmatchnew_config ? "yes" : "no");
00764 
00765    if ((v = ast_variable_browse(cfg, "globals"))) {
00766       fprintf(output, "[globals]\n");
00767       while(v) {
00768          fprintf(output, "%s => %s\n", v->name, v->value);
00769          v = v->next;
00770       }
00771       fprintf(output, "\n");
00772    }
00773 
00774    ast_config_destroy(cfg);
00775    
00776 #define PUT_CTX_HDR  do { \
00777    if (!context_header_written) {   \
00778       fprintf(output, "[%s]\n", ast_get_context_name(c));   \
00779       context_header_written = 1;   \
00780    }  \
00781    } while (0)
00782 
00783    /* walk all contexts */
00784    for (c = NULL; (c = ast_walk_contexts(c)); ) {
00785       int context_header_written = 0;
00786       struct ast_exten *ext, *last_written_e = NULL;
00787       struct ast_include *i;
00788       struct ast_ignorepat *ip;
00789       struct ast_sw *sw;
00790 
00791       /* try to lock context and fireout all info */  
00792       if (ast_rdlock_context(c)) { /* lock failure */
00793          incomplete = 1;
00794          continue;
00795       }
00796       /* registered by this module? */
00797       /* XXX do we need this ? */
00798       if (!strcmp(ast_get_context_registrar(c), registrar)) {
00799          fprintf(output, "[%s]\n", ast_get_context_name(c));
00800          context_header_written = 1;
00801       }
00802 
00803       /* walk extensions ... */
00804       for (ext = NULL; (ext = ast_walk_context_extensions(c, ext)); ) {
00805          struct ast_exten *p = NULL;
00806 
00807          /* fireout priorities */
00808          while ( (p = ast_walk_extension_priorities(ext, p)) ) {
00809             if (strcmp(ast_get_extension_registrar(p), registrar) != 0) /* not this source */
00810                continue;
00811       
00812             /* make empty line between different extensions */ 
00813             if (last_written_e != NULL &&
00814                    strcmp(ast_get_extension_name(last_written_e),
00815                       ast_get_extension_name(p)))
00816                fprintf(output, "\n");
00817             last_written_e = p;
00818          
00819             PUT_CTX_HDR;
00820 
00821             if (ast_get_extension_priority(p) == PRIORITY_HINT) { /* easy */
00822                fprintf(output, "exten => %s,hint,%s\n",
00823                       ast_get_extension_name(p),
00824                       ast_get_extension_app(p));
00825             } else {
00826                const char *sep, *cid;
00827                const char *el = ast_get_extension_label(p);
00828                char label[128] = "";
00829  
00830                if (ast_get_extension_matchcid(p)) {
00831                   sep = "/";
00832                   cid = ast_get_extension_cidmatch(p);
00833                } else
00834                   sep = cid = "";
00835             
00836                if (el && (snprintf(label, sizeof(label), "(%s)", el) != (strlen(el) + 2)))
00837                   incomplete = 1;   /* error encountered or label > 125 chars */
00838                
00839                fprintf(output, "exten => %s%s%s,%d%s,%s(%s)\n",
00840                    ast_get_extension_name(p), (ast_strlen_zero(sep) ? "" : sep), (ast_strlen_zero(cid) ? "" : cid),
00841                    ast_get_extension_priority(p), label,
00842                    ast_get_extension_app(p), (ast_strlen_zero(ast_get_extension_app_data(p)) ? "" : (const char *)ast_get_extension_app_data(p)));
00843             }
00844          }
00845       }
00846 
00847       /* written any extensions? ok, write space between exten & inc */
00848       if (last_written_e)
00849          fprintf(output, "\n");
00850 
00851       /* walk through includes */
00852       for (i = NULL; (i = ast_walk_context_includes(c, i)) ; ) {
00853          if (strcmp(ast_get_include_registrar(i), registrar) != 0)
00854             continue; /* not mine */
00855          PUT_CTX_HDR;
00856          fprintf(output, "include => %s\n", ast_get_include_name(i));
00857       }
00858       if (ast_walk_context_includes(c, NULL))
00859          fprintf(output, "\n");
00860 
00861       /* walk through switches */
00862       for (sw = NULL; (sw = ast_walk_context_switches(c, sw)) ; ) {
00863          if (strcmp(ast_get_switch_registrar(sw), registrar) != 0)
00864             continue; /* not mine */
00865          PUT_CTX_HDR;
00866          fprintf(output, "switch => %s/%s\n",
00867                 ast_get_switch_name(sw), ast_get_switch_data(sw));
00868       }
00869 
00870       if (ast_walk_context_switches(c, NULL))
00871          fprintf(output, "\n");
00872 
00873       /* fireout ignorepats ... */
00874       for (ip = NULL; (ip = ast_walk_context_ignorepats(c, ip)); ) {
00875          if (strcmp(ast_get_ignorepat_registrar(ip), registrar) != 0)
00876             continue; /* not mine */
00877          PUT_CTX_HDR;
00878          fprintf(output, "ignorepat => %s\n",
00879                   ast_get_ignorepat_name(ip));
00880       }
00881 
00882       ast_unlock_context(c);
00883    }  
00884 
00885    ast_unlock_contexts();
00886    ast_mutex_unlock(&save_dialplan_lock);
00887    fclose(output);
00888 
00889    if (incomplete) {
00890       ast_cli(a->fd, "Saved dialplan is incomplete\n");
00891       return CLI_FAILURE;
00892    }
00893 
00894    ast_cli(a->fd, "Dialplan successfully saved into '%s'\n",
00895       filename);
00896    return CLI_SUCCESS;
00897 }

static int load_module ( void   )  [static]

Definition at line 1780 of file pbx_config.c.

References ARRAY_LEN, ast_cli_register(), ast_cli_register_multiple(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, cli_dialplan_save, cli_pbx_config, and pbx_load_module().

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 119 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().

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

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

return true if 'name' is included by context c

Definition at line 105 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().

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

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 148 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().

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

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

Definition at line 1367 of file pbx_config.c.

References ast_category_browse(), ast_config_load, ast_context_find_or_create(), ast_copy_string(), ast_free, ast_log(), ast_strdup, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), config_flags, CONFIG_STATUS_FILEINVALID, ext, ast_variable::file, ast_variable::lineno, local_contexts, local_table, LOG_ERROR, ast_variable::name, ast_variable::next, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), and ast_variable::value.

Referenced by pbx_load_module().

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

static int pbx_load_module ( void   )  [static]

Definition at line 1754 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_walk_contexts(), local_contexts, local_table, pbx_load_config(), pbx_load_users(), pbx_set_autofallthrough(), pbx_set_extenpatternmatchnew(), and pbx_set_overrideswitch().

01755 {
01756    struct ast_context *con;
01757 
01758    if (!local_table)
01759       local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
01760 
01761    if (!pbx_load_config(config))
01762       return AST_MODULE_LOAD_DECLINE;
01763    
01764    pbx_load_users();
01765 
01766    ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
01767    local_table = NULL; /* the local table has been moved into the global one. */
01768    local_contexts = NULL;
01769 
01770    for (con = NULL; (con = ast_walk_contexts(con));)
01771       ast_context_verify_includes(con);
01772 
01773    pbx_set_overrideswitch(overrideswitch_config);
01774    pbx_set_autofallthrough(autofallthrough_config);
01775    pbx_set_extenpatternmatchnew(extenpatternmatchnew_config);
01776 
01777    return AST_MODULE_LOAD_SUCCESS;
01778 }

static void pbx_load_users ( void   )  [static]

Definition at line 1650 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_strlen_zero(), ast_true(), ast_variable_retrieve(), config_flags, ext, local_contexts, local_table, LOG_ERROR, strdup, and strsep().

Referenced by pbx_load_module().

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

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 1342 of file pbx_config.c.

01343 {
01344    int square = 0;
01345    char *res = *destructible;
01346    for (; destructible && *destructible && **destructible; (*destructible)++) {
01347       if (**destructible == '[' && !strchr(delim, '[')) {
01348          square++;
01349       } else if (**destructible == ']' && !strchr(delim, ']')) {
01350          if (square) {
01351             square--;
01352          }
01353       } else if (**destructible == '\\' && !strchr(delim, '\\')) {
01354          (*destructible)++;
01355       } else if (strchr(delim, **destructible) && !square) {
01356          **destructible = '\0';
01357          (*destructible)++;
01358          break;
01359       }
01360    }
01361    if (destructible && *destructible && **destructible == '\0') {
01362       *destructible = NULL;
01363    }
01364    return res;
01365 }

static int reload ( void   )  [static]

Definition at line 1792 of file pbx_config.c.

References pbx_builtin_clear_globals(), and pbx_load_module().

01793 {
01794    if (clearglobalvars_config)
01795       pbx_builtin_clear_globals();
01796    return pbx_load_module();
01797 }

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 133 of file pbx_config.c.

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

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

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 156 of file pbx_config.c.

References ast_strdup, and free.

Referenced by complete_dialplan_remove_extension(), and handle_cli_dialplan_remove_extension().

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

static int unload_module ( void   )  [static]

Standard module functions ...

Definition at line 1325 of file pbx_config.c.

References ARRAY_LEN, ast_cli_unregister(), ast_cli_unregister_multiple(), ast_context_destroy(), ast_free, cli_dialplan_save, and cli_pbx_config.


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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1803 of file pbx_config.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1803 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.

struct ast_cli_entry cli_dialplan_save [static]

Initial value:

   { .handler =  handle_cli_dialplan_save , .summary =  "Save dialplan" ,__VA_ARGS__ }

Definition at line 1319 of file pbx_config.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_pbx_config[] [static]

CLI entries for commands provided by this module

Definition at line 1308 of file pbx_config.c.

Referenced by load_module(), and unload_module().

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 58 of file pbx_config.c.

Referenced by ast_context_find_or_create(), lua_register_switches(), lua_reload_extensions(), pbx_load_config(), pbx_load_module(), and pbx_load_users().

struct ast_hashtab* local_table = NULL [static]

Definition at line 59 of file pbx_config.c.

Referenced by lua_register_switches(), lua_reload_extensions(), pbx_load_config(), pbx_load_module(), and pbx_load_users().

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 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 Sat Mar 10 01:55:36 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7