Mon Oct 8 12:39:26 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 = "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

Referenced by handle_cli_dialplan_save().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1828 of file pbx_config.c.

static void __unreg_module ( void   )  [static]

Definition at line 1828 of file pbx_config.c.

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

Definition at line 1657 of file pbx_config.c.

References len().

Referenced by pbx_load_users().

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

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

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

static char * complete_dialplan_add_ignorepat ( struct ast_cli_args  )  [static]

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

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

static char * complete_dialplan_add_include ( struct ast_cli_args  )  [static]

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

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

static char * complete_dialplan_remove_extension ( struct ast_cli_args  )  [static]

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

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 (asprintf(&ret, "%s/%s@%s", ast_get_extension_name(e), ast_get_extension_cidmatch(e), ast_get_context_name(c)) < 0) {
00439                            ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00440                            ret = NULL;
00441                         }
00442                         break;
00443                      } else if (!ast_get_extension_matchcid(e) && !strchr(a->word, '/')) {
00444                         if (asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c)) < 0) {
00445                            ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00446                            ret = NULL;
00447                         }
00448                         break;
00449                      }
00450                   }
00451                }
00452             }
00453          }
00454          if (e)   /* got a match */
00455             break;
00456       }
00457 
00458       ast_unlock_contexts();
00459    error2:
00460       free(exten);
00461    } else if (a->pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */
00462       char *exten = NULL, *context, *cid, *p;
00463       struct ast_context *c;
00464       int le, lc, len;
00465       const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'extension' */
00466       int i = split_ec(s, &exten, &context, &cid); /* parse ext@context */
00467 
00468       if (i)   /* error */
00469          goto error3;
00470       if ( (p = strchr(exten, ' ')) ) /* remove space after extension */
00471          *p = '\0';
00472       if ( (p = strchr(context, ' ')) ) /* remove space after context */
00473          *p = '\0';
00474       le = strlen(exten);
00475       lc = strlen(context);
00476       len = strlen(a->word);
00477       if (le == 0 || lc == 0)
00478          goto error3;
00479 
00480       if (ast_rdlock_contexts()) {
00481          ast_log(LOG_ERROR, "Failed to lock context list\n");
00482          goto error3;
00483       }
00484 
00485       /* walk contexts */
00486       c = NULL;
00487       while ( (c = ast_walk_contexts(c)) ) {
00488          /* XXX locking on c ? */
00489          struct ast_exten *e;
00490          if (strcmp(ast_get_context_name(c), context) != 0)
00491             continue;
00492          /* got it, we must match here */
00493          e = NULL;
00494          while ( (e = ast_walk_context_extensions(c, e)) ) {
00495             struct ast_exten *priority;
00496             char buffer[10];
00497 
00498             if (cid && strcmp(ast_get_extension_cidmatch(e), cid) != 0) {
00499                continue;
00500             }
00501             if (strcmp(ast_get_extension_name(e), exten) != 0)
00502                continue;
00503             /* XXX lock e ? */
00504             priority = NULL;
00505             while ( !ret && (priority = ast_walk_extension_priorities(e, priority)) ) {
00506                snprintf(buffer, sizeof(buffer), "%u", ast_get_extension_priority(priority));
00507                if (partial_match(buffer, a->word, len) && ++which > a->n) /* n-th match */
00508                   ret = strdup(buffer);
00509             }
00510             break;
00511          }
00512          break;
00513       }
00514       ast_unlock_contexts();
00515    error3:
00516       free(exten);
00517    }
00518    return ret; 
00519 }

static char * complete_dialplan_remove_ignorepat ( struct ast_cli_args  )  [static]

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

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

static char * complete_dialplan_remove_include ( struct ast_cli_args  )  [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, strsep(), 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 909 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, 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, strsep(), and ast_cli_entry::usage.

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

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

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

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

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

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

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

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

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

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

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 677 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_variable::name, ast_variable::next, overrideswitch, PRIORITY_HINT, PUT_CTX_HDR, save_dialplan_lock, ast_cli_entry::usage, and ast_variable::value.

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

static int load_module ( void   )  [static]

Definition at line 1805 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 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 1386 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_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().

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

static int pbx_load_module ( void   )  [static]

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

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

static void pbx_load_users ( void   )  [static]

Definition at line 1669 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, local_contexts, local_table, LOG_ERROR, and strsep().

Referenced by pbx_load_module().

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

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

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

static int reload ( void   )  [static]

Definition at line 1817 of file pbx_config.c.

References pbx_builtin_clear_globals(), and pbx_load_module().

01818 {
01819    if (clearglobalvars_config)
01820       pbx_builtin_clear_globals();
01821    return pbx_load_module();
01822 }

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]

Standard module functions ...

Definition at line 1339 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1828 of file pbx_config.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1828 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 1333 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 1322 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 60 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 61 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 reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 58 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 Mon Oct 8 12:39:26 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7