conf2ael.c File Reference

#include "asterisk.h"
#include "asterisk/paths.h"
#include <locale.h>
#include <ctype.h>
#include <err.h>
#include <regex.h>
#include "asterisk/pbx.h"
#include "asterisk/ast_expr.h"
#include "asterisk/channel.h"
#include "asterisk/chanvars.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/hashtab.h"
#include "asterisk/ael_structs.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/pval.h"
#include "asterisk/extconf.h"

Include dependency graph for conf2ael.c:

Go to the source code of this file.

Data Structures

struct  ast_app
 ast_app: A registered application More...
struct  ast_context
 ast_context: An extension context More...
struct  ast_exten
 ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More...
struct  ast_hint
 Structure for dial plan hints. More...
struct  ast_ignorepat
 ast_ignorepat: Ignore patterns in dial plan More...
struct  ast_include
 ast_include: include= support in extensions.conf More...
struct  ast_state_cb
 ast_state_cb: An extension state notify register item More...
struct  ast_sw
 ast_sw: Switch statement in extensions.conf More...
struct  profile_data
struct  profile_entry
struct  store_hint
struct  store_hints

Defines

#define BACKGROUND_MATCHEXTEN   (1 << 2)
#define BACKGROUND_NOANSWER   (1 << 1)
#define BACKGROUND_PLAYBACK   (1 << 3)
#define BACKGROUND_SKIP   (1 << 0)
#define EXT_DATA_SIZE   8192
#define STATUS_NO_CONTEXT   1
#define STATUS_NO_EXTENSION   2
#define STATUS_NO_LABEL   4
#define STATUS_NO_PRIORITY   3
#define STATUS_SUCCESS   5
#define SWITCH_DATA_LENGTH   256
#define VAR_BUF_SIZE   4096
#define VAR_HARDTRAN   3
#define VAR_NORMAL   1
#define VAR_SOFTTRAN   2

Functions

int all_bits_set (unsigned int *word, int bitsperword, int totalbits)
int ast_add_extension2 (struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add an extension to an extension context, this time with an ast_context *.
int ast_add_profile (const char *x, uint64_t scale)
 support for event profiling
void ast_cli_register_multiple (void)
void ast_cli_unregister_multiple (void)
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context).
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context (or ANY context if NULL).
struct ast_contextast_context_find_or_create (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
 Register a new context or find an existing one.
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure.
struct ast_custom_functionast_custom_function_find (const char *name)
const char * ast_get_context_name (struct ast_context *con)
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts
unsigned int ast_hashtab_hash_contexts (const void *obj)
void ast_log (int level, const char *file, int line, const char *function, const char *fmt,...)
 Used for sending a log message This is the standard logger function. Probably the only way you will invoke it would be something like this: ast_log(AST_LOG_WHATEVER, "Problem with the %s Captain. We should get some more. Will %d be enough?\n", "flux capacitor", 10); where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending on which log you wish to output to. These are implemented as macros, that will provide the function with the needed arguments.
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.
void ast_module_register (const struct ast_module_info *x)
void ast_module_unregister (const struct ast_module_info *x)
void ast_register_file_version (const char *file, const char *version)
 Register the version of a source code file with the core.
void ast_unregister_file_version (const char *file)
 Unregister a source code file from the core.
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
struct ast_ignorepatast_walk_context_ignorepats (struct ast_context *con, struct ast_ignorepat *ip)
struct ast_includeast_walk_context_includes (struct ast_context *con, struct ast_include *inc)
struct ast_swast_walk_context_switches (struct ast_context *con, struct ast_sw *sw)
struct ast_contextast_walk_contexts (struct ast_context *con)
static int bit_at (unsigned int *word, int bitsperword, int bitnum)
void get_start_stop (unsigned int *word, int bitsperword, int totalbits, int *start, int *end)
int main (int argc, char **argv)
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character.
struct ast_extenpbx_find_extension (struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)

Variables

const char * ast_config_AST_CONFIG_DIR = "/etc/asterisk"
char * config = "extensions.conf"
struct ast_contextcontexts
char * days []
struct ast_contextlocal_contexts
char * months []
int option_debug = 0
int option_verbose = 0


Define Documentation

#define BACKGROUND_MATCHEXTEN   (1 << 2)

Definition at line 128 of file conf2ael.c.

#define BACKGROUND_NOANSWER   (1 << 1)

Definition at line 127 of file conf2ael.c.

#define BACKGROUND_PLAYBACK   (1 << 3)

Definition at line 129 of file conf2ael.c.

#define BACKGROUND_SKIP   (1 << 0)

Definition at line 126 of file conf2ael.c.

#define EXT_DATA_SIZE   8192

Definition at line 115 of file conf2ael.c.

#define STATUS_NO_CONTEXT   1

Definition at line 240 of file conf2ael.c.

#define STATUS_NO_EXTENSION   2

Definition at line 241 of file conf2ael.c.

#define STATUS_NO_LABEL   4

Definition at line 243 of file conf2ael.c.

#define STATUS_NO_PRIORITY   3

Definition at line 242 of file conf2ael.c.

#define STATUS_SUCCESS   5

Definition at line 244 of file conf2ael.c.

#define SWITCH_DATA_LENGTH   256

Definition at line 118 of file conf2ael.c.

#define VAR_BUF_SIZE   4096

Definition at line 120 of file conf2ael.c.

#define VAR_HARDTRAN   3

Definition at line 124 of file conf2ael.c.

#define VAR_NORMAL   1

Definition at line 122 of file conf2ael.c.

#define VAR_SOFTTRAN   2

Definition at line 123 of file conf2ael.c.


Function Documentation

int all_bits_set ( unsigned int *  word,
int  bitsperword,
int  totalbits 
)

Definition at line 297 of file conf2ael.c.

References total.

Referenced by main().

00298 {
00299    
00300    int i, total=totalbits/bitsperword,bitmask = 0;
00301    
00302    for (i=0; i<bitsperword; i++)
00303    {
00304       bitmask |= (1 << i);
00305    }
00306    
00307    for (i=0; i<total; i++)
00308    {
00309       if (word[i] != bitmask)
00310          return 0;
00311    }
00312    return 1;
00313 }

int ast_add_extension2 ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)

Add an extension to an extension context, this time with an ast_context *.

Main interface to add extensions to the list for out context.

Note:
For details about the arguments, check ast_add_extension()
Add an extension to an extension context, this time with an ast_context *.

We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.

The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.

EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set

Definition at line 573 of file conf2ael.c.

References ast_add_extension2_lockopt(), ast_context::eswitches, extens, ast_context::extension_count, filter_leading_space_from_exprs(), filter_newlines(), free, ast_context::ignorepats, ast_context::includes, localized_add_extension2(), namelist::name, ast_context::name, namelist::name2, namelist::next, priors, and ast_context::switches.

Referenced by add_extensions(), ast_add_extension(), AST_TEST_DEFINE(), context_merge(), localized_add_extension2(), lua_register_hints(), manager_dialplan_extension_add(), pbx_load_config(), pbx_load_users(), sla_build_station(), and sla_build_trunk().

00577 {
00578    return localized_add_extension2(con, replace, extension, priority, label, callerid, application, data, datad, registrar);
00579 }

int ast_add_profile ( const char *  x,
uint64_t  scale 
)

support for event profiling

allocates a counter with a given name and scale.

(note, this must be documented a lot more) ast_add_profile allocates a generic 'counter' with a given name, which can be shown with the command 'core show profile <name>'

The counter accumulates positive or negative values supplied by

See also:
ast_add_profile(), dividing them by the 'scale' value passed in the create call, and also counts the number of 'events'. Values can also be taked by the TSC counter on ia32 architectures, in which case you can mark the start of an event calling ast_mark(id, 1) and then the end of the event with ast_mark(id, 0). For non-i386 architectures, these two calls return 0.
support for event profiling

Returns:
Returns the identifier of the counter.

Definition at line 92 of file conf2ael.c.

References ast_calloc, ast_realloc, ast_strdup, profile_data::e, profile_data::entries, profile_entry::events, profile_entry::mark, profile_data::max_size, profile_entry::name, NULL, prof_data, profile_entry::scale, and profile_entry::value.

Referenced by extension_match_core().

00092 { return 0;}

void ast_cli_register_multiple ( void   ) 

void ast_cli_unregister_multiple ( void   ) 

int ast_context_add_ignorepat2 ( struct ast_context con,
const char *  value,
const char *  registrar 
)

int ast_context_add_include2 ( struct ast_context con,
const char *  value,
const char *  registrar 
)

Add a context include.

Parameters:
con context to add the include to
value include value to add
registrar who registered the context
Adds an include taking a struct ast_context as the first parameter

Return values:
0 on success
-1 on failure

Definition at line 594 of file conf2ael.c.

References ADD_LAST, ast_build_timing(), ast_calloc, ast_destroy_timing(), ast_free, ast_get_context_name(), ast_unlock_context(), ast_verb, ast_wrlock_context(), c, create_name(), errno, ast_include::hastime, ast_context::includes, localized_context_add_include2(), ast_include::name, ast_include::next, NULL, ast_include::registrar, ast_include::rname, ast_include::stuff, and ast_include::timing.

Referenced by ast_compile_ael2(), ast_context_add_include(), context_merge_incls_swits_igps_other_registrars(), localized_context_add_include2(), and pbx_load_config().

00596 {
00597    
00598    return localized_context_add_include2(con, value,registrar);
00599 }

int ast_context_add_switch2 ( struct ast_context con,
const char *  value,
const char *  data,
int  eval,
const char *  registrar 
)

void ast_context_destroy ( struct ast_context con,
const char *  registrar 
)

Destroy a context (matches the specified context (or ANY context if NULL).

Parameters:
con context to destroy
registrar who registered it
You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.

Returns:
nothing

Definition at line 10814 of file pbx.c.

References __ast_context_destroy(), ast_unlock_contexts(), and ast_wrlock_contexts().

struct ast_context* ast_context_find_or_create ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  name,
const char *  registrar 
) [read]

Register a new context or find an existing one.

Parameters:
extcontexts pointer to the ast_context structure pointer
exttable pointer to the hashtable that contains all the elements in extcontexts
name name of the new context
registrar registrar of the context
This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.

This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns:
NULL on failure, and an ast_context structure on success

Definition at line 601 of file conf2ael.c.

References localized_context_find_or_create().

Referenced by add_hints(), ast_compile_ael2(), AST_TEST_DEFINE(), config_parse_variables(), context_merge(), create_test_dialplan(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_add_include(), load_module(), lua_register_hints(), lua_register_switches(), manager_dialplan_extension_add(), parking_duration_callback(), parking_lot_cfg_create_extensions(), pbx_load_config(), pbx_load_users(), reload_config(), set_config(), sla_build_station(), and sla_build_trunk().

00602 {
00603    printf("find/Creating context %s, registrar=%s\n", name, registrar);
00604    
00605    return localized_context_find_or_create(extcontexts, exttable, name, registrar);
00606 }

int ast_context_verify_includes ( struct ast_context con  ) 

Verifies includes in an ast_contect structure.

Parameters:
con context in which to verify the includes
Return values:
0 if no problems found
-1 if there were any missing context

Definition at line 12330 of file pbx.c.

References ast_context_find(), ast_get_context_name(), ast_log, ast_walk_context_includes(), LOG_WARNING, NULL, and ast_include::rname.

12331 {
12332    struct ast_include *inc = NULL;
12333    int res = 0;
12334 
12335    while ( (inc = ast_walk_context_includes(con, inc)) ) {
12336       if (ast_context_find(inc->rname))
12337          continue;
12338 
12339       res = -1;
12340       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
12341          ast_get_context_name(con), inc->rname);
12342       break;
12343    }
12344 
12345    return res;
12346 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  )  [read]

Definition at line 4019 of file pbx.c.

References ast_custom_function_find_nolock(), AST_RWLIST_RDLOCK, and AST_RWLIST_UNLOCK.

04020 {
04021    struct ast_custom_function *acf;
04022 
04023    AST_RWLIST_RDLOCK(&acf_root);
04024    acf = ast_custom_function_find_nolock(name);
04025    AST_RWLIST_UNLOCK(&acf_root);
04026 
04027    return acf;
04028 }

const char* ast_get_context_name ( struct ast_context con  ) 

Definition at line 12182 of file pbx.c.

12183 {
12184    return con ? con->name : NULL;
12185 }

int ast_hashtab_compare_contexts ( const void *  ah_a,
const void *  ah_b 
)

hashtable functions for contexts

Definition at line 1283 of file pbx.c.

References bc, and ast_context::name.

01284 {
01285    const struct ast_context *ac = ah_a;
01286    const struct ast_context *bc = ah_b;
01287    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01288       return 1;
01289    /* assume context names are registered in a string table! */
01290    return strcmp(ac->name, bc->name);
01291 }

unsigned int ast_hashtab_hash_contexts ( const void *  obj  ) 

Definition at line 1335 of file pbx.c.

References ast_hashtab_hash_string(), and ast_context::name.

01336 {
01337    const struct ast_context *ac = obj;
01338    return ast_hashtab_hash_string(ac->name);
01339 }

void ast_log ( int  level,
const char *  file,
int  line,
const char *  function,
const char *  fmt,
  ... 
)

Used for sending a log message This is the standard logger function. Probably the only way you will invoke it would be something like this: ast_log(AST_LOG_WHATEVER, "Problem with the %s Captain. We should get some more. Will %d be enough?\n", "flux capacitor", 10); where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending on which log you wish to output to. These are implemented as macros, that will provide the function with the needed arguments.

Parameters:
level Type of log event
file Will be provided by the AST_LOG_* macro
line Will be provided by the AST_LOG_* macro
function Will be provided by the AST_LOG_* macro
fmt This is what is important. The format is the same as your favorite breed of printf. You know how that works, right? :-)

Definition at line 1707 of file logger.c.

01708 {
01709    ast_callid callid;
01710    va_list ap;
01711 
01712    callid = ast_read_threadstorage_callid();
01713 
01714    va_start(ap, fmt);
01715    if (level == __LOG_VERBOSE) {
01716       __ast_verbose_ap(file, line, function, 0, callid, fmt, ap);
01717    } else {
01718       ast_log_full(level, file, line, function, callid, fmt, ap);
01719    }
01720    va_end(ap);
01721 }

void ast_merge_contexts_and_delete ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  registrar 
)

Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added.

Parameters:
extcontexts pointer to the ast_context structure
exttable pointer to the ast_hashtab structure that contains all the elements in extcontexts
registrar of the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts

Definition at line 8864 of file pbx.c.

References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, ast_free, ast_free_ptr, ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal(), ast_hint_extension_nolock(), AST_HINT_UPDATE_DEVICE, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), store_hint::callbacks, ast_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, ast_state_cb::data, ast_exten::data, store_hint::data, E_MATCH, execute_state_callback(), store_hint::exten, ast_exten::exten, ast_hint::exten, store_hint::last_presence_message, ast_hint::last_presence_message, ast_hint::last_presence_state, store_hint::last_presence_state, store_hint::last_presence_subtype, ast_hint::last_presence_subtype, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, ast_sw::next, NULL, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, pbx_find_info::stacklen, and tmp().

08865 {
08866    double ft;
08867    struct ast_context *tmp;
08868    struct ast_context *oldcontextslist;
08869    struct ast_hashtab *oldtable;
08870    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
08871    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
08872    struct store_hint *saved_hint;
08873    struct ast_hint *hint;
08874    struct ast_exten *exten;
08875    int length;
08876    struct ast_state_cb *thiscb;
08877    struct ast_hashtab_iter *iter;
08878    struct ao2_iterator i;
08879    struct timeval begintime;
08880    struct timeval writelocktime;
08881    struct timeval endlocktime;
08882    struct timeval enddeltime;
08883 
08884    /*
08885     * It is very important that this function hold the hints
08886     * container lock _and_ the conlock during its operation; not
08887     * only do we need to ensure that the list of contexts and
08888     * extensions does not change, but also that no hint callbacks
08889     * (watchers) are added or removed during the merge/delete
08890     * process
08891     *
08892     * In addition, the locks _must_ be taken in this order, because
08893     * there are already other code paths that use this order
08894     */
08895 
08896    begintime = ast_tvnow();
08897    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
08898    ast_wrlock_contexts();
08899 
08900    if (!contexts_table) {
08901       /* Well, that's odd. There are no contexts. */
08902       contexts_table = exttable;
08903       contexts = *extcontexts;
08904       ast_unlock_contexts();
08905       ast_mutex_unlock(&context_merge_lock);
08906       return;
08907    }
08908 
08909    iter = ast_hashtab_start_traversal(contexts_table);
08910    while ((tmp = ast_hashtab_next(iter))) {
08911       context_merge(extcontexts, exttable, tmp, registrar);
08912    }
08913    ast_hashtab_end_traversal(iter);
08914 
08915    ao2_lock(hints);
08916    writelocktime = ast_tvnow();
08917 
08918    /* preserve all watchers for hints */
08919    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
08920    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
08921       if (ao2_container_count(hint->callbacks)) {
08922          ao2_lock(hint);
08923          if (!hint->exten) {
08924             /* The extension has already been destroyed. (Should never happen here) */
08925             ao2_unlock(hint);
08926             continue;
08927          }
08928 
08929          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
08930             + sizeof(*saved_hint);
08931          if (!(saved_hint = ast_calloc(1, length))) {
08932             ao2_unlock(hint);
08933             continue;
08934          }
08935 
08936          /* This removes all the callbacks from the hint into saved_hint. */
08937          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
08938             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
08939             /*
08940              * We intentionally do not unref thiscb to account for the
08941              * non-ao2 reference in saved_hint->callbacks
08942              */
08943          }
08944 
08945          saved_hint->laststate = hint->laststate;
08946          saved_hint->context = saved_hint->data;
08947          strcpy(saved_hint->data, hint->exten->parent->name);
08948          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
08949          strcpy(saved_hint->exten, hint->exten->exten);
08950          if (hint->last_presence_subtype) {
08951             saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
08952          }
08953          if (hint->last_presence_message) {
08954             saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
08955          }
08956          saved_hint->last_presence_state = hint->last_presence_state;
08957          ao2_unlock(hint);
08958          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
08959       }
08960    }
08961    ao2_iterator_destroy(&i);
08962 
08963    /* save the old table and list */
08964    oldtable = contexts_table;
08965    oldcontextslist = contexts;
08966 
08967    /* move in the new table and list */
08968    contexts_table = exttable;
08969    contexts = *extcontexts;
08970 
08971    /*
08972     * Restore the watchers for hints that can be found; notify
08973     * those that cannot be restored.
08974     */
08975    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
08976       struct pbx_find_info q = { .stacklen = 0 };
08977 
08978       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
08979          PRIORITY_HINT, NULL, "", E_MATCH);
08980       /*
08981        * If this is a pattern, dynamically create a new extension for this
08982        * particular match.  Note that this will only happen once for each
08983        * individual extension, because the pattern will no longer match first.
08984        */
08985       if (exten && exten->exten[0] == '_') {
08986          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
08987             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
08988             exten->registrar);
08989          /* rwlocks are not recursive locks */
08990          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
08991             saved_hint->exten);
08992       }
08993 
08994       /* Find the hint in the hints container */
08995       hint = exten ? ao2_find(hints, exten, 0) : NULL;
08996       if (!hint) {
08997          /*
08998           * Notify watchers of this removed hint later when we aren't
08999           * encumberd by so many locks.
09000           */
09001          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
09002       } else {
09003          ao2_lock(hint);
09004          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
09005             ao2_link(hint->callbacks, thiscb);
09006             /* Ref that we added when putting into saved_hint->callbacks */
09007             ao2_ref(thiscb, -1);
09008          }
09009          hint->laststate = saved_hint->laststate;
09010          hint->last_presence_state = saved_hint->last_presence_state;
09011          hint->last_presence_subtype = saved_hint->last_presence_subtype;
09012          hint->last_presence_message = saved_hint->last_presence_message;
09013          ao2_unlock(hint);
09014          ao2_ref(hint, -1);
09015          /*
09016           * The free of saved_hint->last_presence_subtype and
09017           * saved_hint->last_presence_message is not necessary here.
09018           */
09019          ast_free(saved_hint);
09020       }
09021    }
09022 
09023    ao2_unlock(hints);
09024    ast_unlock_contexts();
09025 
09026    /*
09027     * Notify watchers of all removed hints with the same lock
09028     * environment as device_state_cb().
09029     */
09030    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
09031       /* this hint has been removed, notify the watchers */
09032       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
09033          execute_state_callback(thiscb->change_cb,
09034             saved_hint->context,
09035             saved_hint->exten,
09036             thiscb->data,
09037             AST_HINT_UPDATE_DEVICE,
09038             NULL,
09039             NULL);
09040          /* Ref that we added when putting into saved_hint->callbacks */
09041          ao2_ref(thiscb, -1);
09042       }
09043       ast_free(saved_hint->last_presence_subtype);
09044       ast_free(saved_hint->last_presence_message);
09045       ast_free(saved_hint);
09046    }
09047 
09048    ast_mutex_unlock(&context_merge_lock);
09049    endlocktime = ast_tvnow();
09050 
09051    /*
09052     * The old list and hashtab no longer are relevant, delete them
09053     * while the rest of asterisk is now freely using the new stuff
09054     * instead.
09055     */
09056 
09057    ast_hashtab_destroy(oldtable, NULL);
09058 
09059    for (tmp = oldcontextslist; tmp; ) {
09060       struct ast_context *next;  /* next starting point */
09061 
09062       next = tmp->next;
09063       __ast_internal_context_destroy(tmp);
09064       tmp = next;
09065    }
09066    enddeltime = ast_tvnow();
09067 
09068    ft = ast_tvdiff_us(writelocktime, begintime);
09069    ft /= 1000000.0;
09070    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
09071 
09072    ft = ast_tvdiff_us(endlocktime, writelocktime);
09073    ft /= 1000000.0;
09074    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
09075 
09076    ft = ast_tvdiff_us(enddeltime, endlocktime);
09077    ft /= 1000000.0;
09078    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
09079 
09080    ft = ast_tvdiff_us(enddeltime, begintime);
09081    ft /= 1000000.0;
09082    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
09083 }

void ast_module_register ( const struct ast_module_info x  ) 

Definition at line 614 of file conf2ael.c.

00615 {
00616 }

void ast_module_unregister ( const struct ast_module_info x  ) 

Definition at line 618 of file conf2ael.c.

00619 {
00620 }

void ast_register_file_version ( const char *  file,
const char *  version 
)

Register the version of a source code file with the core.

Parameters:
file the source file name
version the version string (typically a SVN revision keyword string)
Returns:
nothing
This function should not be called directly, but instead the ASTERISK_FILE_VERSION macro should be used to register a file with the core.

Definition at line 486 of file asterisk.c.

References ast_calloc, AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdupa, ast_strip(), and ast_strip_quoted().

00487 {
00488    struct file_version *new;
00489    char *work;
00490    size_t version_length;
00491 
00492    work = ast_strdupa(version);
00493    work = ast_strip(ast_strip_quoted(work, "$", "$"));
00494    version_length = strlen(work) + 1;
00495 
00496    if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
00497       return;
00498 
00499    new->file = file;
00500    new->version = (char *) new + sizeof(*new);
00501    memcpy(new->version, work, version_length);
00502    AST_RWLIST_WRLOCK(&file_versions);
00503    AST_RWLIST_INSERT_HEAD(&file_versions, new, list);
00504    AST_RWLIST_UNLOCK(&file_versions);
00505 }

void ast_unregister_file_version ( const char *  file  ) 

Unregister a source code file from the core.

Parameters:
file the source file name
Returns:
nothing
This function should not be called directly, but instead the ASTERISK_FILE_VERSION macro should be used to automatically unregister the file when the module is unloaded.

Definition at line 507 of file asterisk.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, file_version::file, and ast_atexit::list.

00508 {
00509    struct file_version *find;
00510 
00511    AST_RWLIST_WRLOCK(&file_versions);
00512    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
00513       if (!strcasecmp(find->file, file)) {
00514          AST_RWLIST_REMOVE_CURRENT(list);
00515          break;
00516       }
00517    }
00518    AST_RWLIST_TRAVERSE_SAFE_END;
00519    AST_RWLIST_UNLOCK(&file_versions);
00520 
00521    if (find)
00522       ast_free(find);
00523 }

struct ast_exten* ast_walk_context_extensions ( struct ast_context con,
struct ast_exten exten 
) [read]

Definition at line 12288 of file pbx.c.

12290 {
12291    if (!exten)
12292       return con ? con->root : NULL;
12293    else
12294       return exten->next;
12295 }

struct ast_ignorepat* ast_walk_context_ignorepats ( struct ast_context con,
struct ast_ignorepat ip 
) [read]

Definition at line 12321 of file pbx.c.

References ast_context::ignorepats, ast_ignorepat::next, and NULL.

12323 {
12324    if (!ip)
12325       return con ? con->ignorepats : NULL;
12326    else
12327       return ip->next;
12328 }

struct ast_include* ast_walk_context_includes ( struct ast_context con,
struct ast_include inc 
) [read]

Definition at line 12312 of file pbx.c.

12314 {
12315    if (!inc)
12316       return con ? con->includes : NULL;
12317    else
12318       return inc->next;
12319 }

struct ast_sw* ast_walk_context_switches ( struct ast_context con,
struct ast_sw sw 
) [read]

Definition at line 12297 of file pbx.c.

12299 {
12300    if (!sw)
12301       return con ? AST_LIST_FIRST(&con->alts) : NULL;
12302    else
12303       return AST_LIST_NEXT(sw, list);
12304 }

struct ast_context* ast_walk_contexts ( struct ast_context con  )  [read]

Definition at line 12283 of file pbx.c.

12284 {
12285    return con ? con->next : contexts;
12286 }

static int bit_at ( unsigned int *  word,
int  bitsperword,
int  bitnum 
) [static]

Definition at line 273 of file conf2ael.c.

Referenced by get_start_stop().

00274 {
00275    return word[bitnum/bitsperword] & (1 << (bitnum % bitsperword));
00276 }

void get_start_stop ( unsigned int *  word,
int  bitsperword,
int  totalbits,
int *  start,
int *  end 
)

Definition at line 278 of file conf2ael.c.

References bit_at().

Referenced by main().

00279 {
00280    int i;
00281    int thisbit, thatbit = bit_at(word, bitsperword, totalbits-1);
00282    
00283    for (i=0; i<totalbits; i++) {
00284       thisbit = bit_at(word, bitsperword, i);
00285       
00286       if (thisbit != thatbit ) {
00287          if (thisbit) {
00288             *start = i;
00289          } else {
00290             *end = i;
00291          }
00292       }
00293       thatbit = thisbit;
00294    }
00295 }

int main ( int  argc,
char **  argv 
)

Definition at line 316 of file conf2ael.c.

References ael2_print(), all_bits_set(), ast_context::alts, ast_exten::app, args, AST_LIST_FIRST, ast_log, ast_strdup, ast_exten::data, ast_timing::daymask, ast_timing::dowmask, e, ast_exten::exten, free, get_start_stop(), ast_include::hastime, ast_context::ignorepats, ast_context::includes, localized_pbx_load_module(), localized_use_conf_dir(), localized_walk_context_extensions(), localized_walk_context_switches(), localized_walk_contexts(), localized_walk_extension_priorities(), LOG_ERROR, min, ast_timing::minmask, ast_timing::monthmask, ast_sw::name, ast_include::name, ast_context::name, ast_ignorepat::next, ast_include::next, ast_ignorepat::pattern, ast_exten::peer, ast_exten::priority, PV_APPLICATION_CALL, PV_CONTEXT, PV_EXTENSION, PV_IGNOREPAT, PV_INCLUDES, PV_STATEMENTBLOCK, PV_SWITCHES, PV_WORD, pvalAppCallAddArg(), pvalAppCallSetAppName(), pvalContextAddStatement(), pvalContextSetName(), pvalCreateNode(), pvalExtenSetHints(), pvalExtenSetName(), pvalExtenSetStatement(), pvalIgnorePatSetPattern(), pvalIncludesAddInclude(), pvalIncludesAddIncludeWithTimeConstraints(), pvalStatementBlockAddStatement(), pvalSwitchesAddSwitch(), pvalTopLevAddObject(), pvalWordSetString(), strdup, ast_include::timing, and tmp().

00317 {
00318    struct ast_context *tmp;
00319    struct ast_exten *e, *eroot;
00320    pval *tree, *tmptree, *sws;
00321    struct ast_include *tmpi;
00322    struct ast_sw *sw = 0;
00323    struct ast_ignorepat *ipi;
00324    pval *incl=0;
00325    int localdir = 0, i;
00326 
00327    tree = 0;
00328    tmptree = 0;
00329 
00330    /* process the command line args */
00331    for (i=1; i<argc; i++)
00332    {
00333       if (strcmp(argv[i],"-d")==0)
00334          localdir =1;
00335    }
00336    
00337    /* 3 simple steps: */
00338    /*   1. read in the extensions.conf config file 
00339     *   2. traverse, and build an AEL tree
00340     *   3. Output the AEL tree into a file
00341     */
00342    printf("WARNING: This is an EXTREMELY preliminary version of a program\n");
00343    printf("         that will someday hopefully do a thoughful and intelligent\n");
00344    printf("         job of transforming your extensions.conf file into an\n");
00345    printf("         extensions.ael file.\n");
00346    printf("         This version has absolutely no intelligence, and pretty\n");
00347    printf("         much just does a direct conversion\n");
00348    printf("         The result will most likely need careful attention to\n");
00349    printf("         finish the job!!!!!\n");
00350 
00351    if (!localdir)
00352       printf(" (You could use -d the use the extensions.conf in the current directory!)\n");
00353 
00354    printf("Loading %s/%s...\n", ast_config_AST_CONFIG_DIR, config);
00355 
00356    if (!localdir)
00357       localized_use_conf_dir();
00358    localized_pbx_load_module();
00359    
00360    printf("... Done!\n");
00361    
00362    tmp = 0;
00363    while ((tmp = localized_walk_contexts(tmp)) ) {
00364       printf("Context: %s\n", tmp->name);
00365    }
00366    printf("=========\n");
00367    tmp = 0;
00368    while ((tmp = localized_walk_contexts(tmp)) ) {
00369       /* printf("Context: %s\n", tmp->name); */
00370       tmptree = pvalCreateNode(PV_CONTEXT);
00371       if (!tree)
00372          tree = tmptree;
00373       else
00374          pvalTopLevAddObject(tree, tmptree);
00375       
00376       pvalContextSetName(tmptree, ast_strdup(tmp->name));
00377       
00378       if (tmp->includes) {
00379          incl = pvalCreateNode(PV_INCLUDES);
00380          pvalContextAddStatement(tmptree, incl);
00381          for (tmpi = tmp->includes; tmpi; ) { /* includes */
00382             if (strchr(tmpi->name,'|')==0) {
00383                if (tmpi->hastime)
00384                {
00385                   char timerange[15];
00386                   char dowrange[10];
00387                   char domrange[10];
00388                   char monrange[10];
00389                   int startbit=0, endbit=0;
00390                   
00391                   if (all_bits_set(tmpi->timing.minmask, 30, 720))
00392                      strcpy(timerange, "*");
00393                   else {
00394                      int hr, min;
00395                      char tbuf[20];
00396                      get_start_stop(tmpi->timing.minmask, 30, 720, &startbit, &endbit);
00397                      hr = startbit/30;
00398                      min = (startbit % 30) * 2;
00399                      sprintf(tbuf,"%02d:%02d", hr, min);
00400                      strcpy(timerange, tbuf);
00401                      hr = endbit/30;
00402                      min = (endbit % 30) * 2;
00403                      sprintf(tbuf,"%02d:%02d", hr, min);
00404                      strcat(timerange,"-");
00405                      strcat(timerange,tbuf);
00406                   }
00407                   
00408                   if (all_bits_set(&tmpi->timing.dowmask, 7, 7))
00409                      strcpy(dowrange, "*");
00410                   else {
00411                      get_start_stop(&tmpi->timing.dowmask, 7, 7, &startbit, &endbit);
00412                      strcpy(dowrange, days[startbit]);
00413                      strcat(dowrange,"-");
00414                      strcat(dowrange, days[endbit]);
00415                   }
00416                   
00417                   if (all_bits_set(&tmpi->timing.monthmask, 12, 12))
00418                      strcpy(monrange, "*");
00419                   else {
00420                      get_start_stop(&tmpi->timing.monthmask, 12, 12, &startbit, &endbit);
00421                      strcpy(monrange, months[startbit]);
00422                      strcat(monrange,"-");
00423                      strcat(monrange, months[endbit]);
00424                   }
00425                   
00426                   if (all_bits_set(&tmpi->timing.daymask, 31, 31))
00427                      strcpy(domrange, "*");
00428                   else {
00429                      char tbuf[20];
00430                      get_start_stop(&tmpi->timing.daymask, 31, 31, &startbit, &endbit);
00431                      sprintf(tbuf,"%d", startbit);
00432                      strcpy(domrange, tbuf);
00433                      strcat(domrange,"-");
00434                      sprintf(tbuf,"%d", endbit);
00435                      strcat(domrange, tbuf);
00436                   }
00437                   /* now all 4 fields are set; what do we do? */
00438                   pvalIncludesAddIncludeWithTimeConstraints(incl, strdup(tmpi->name), strdup(timerange), strdup(domrange), strdup(dowrange), strdup(monrange));
00439                   
00440                } else {
00441                   pvalIncludesAddInclude(incl, strdup(tmpi->name));
00442                }
00443             } else { /* it appears the timing constraint info is tacked onto the name, carve it up and divvy it out */
00444                char *dow,*dom,*mon;
00445                char *all = strdup(tmpi->name);
00446                char *hr = strchr(all,'|');
00447                if (hr) {
00448                   *hr++ = 0;
00449                   dow = strchr(hr,'|');
00450                   if (dow) {
00451                      *dow++ = 0;
00452                      dom = strchr(dow,'|');
00453                      if (dom) {
00454                         *dom++ = 0;
00455                         mon = strchr(dom,'|');
00456                         if (mon) {
00457                            *mon++ = 0;
00458                            /* now all 4 fields are set; what do we do? */
00459                            pvalIncludesAddIncludeWithTimeConstraints(incl, strdup(all), strdup(hr), strdup(dow), strdup(dom), strdup(mon));
00460                            /* the original data is always best to keep (no 2-min rounding) */
00461                         } else {
00462                            ast_log(LOG_ERROR,"No month spec attached to include!\n");
00463                         }
00464                      } else {
00465                         ast_log(LOG_ERROR,"No day of month spec attached to include!\n");
00466                      }
00467                   } else {
00468                      ast_log(LOG_ERROR,"No day of week spec attached to include!\n");
00469                   }
00470                }
00471                free(all);
00472             }
00473             tmpi = tmpi->next;
00474          }
00475       }
00476       for (ipi = tmp->ignorepats; ipi; ) { /* ignorepats */
00477          incl = pvalCreateNode(PV_IGNOREPAT);
00478          pvalIgnorePatSetPattern(incl,(char *)ipi->pattern);
00479          pvalContextAddStatement(tmptree, incl);
00480          ipi = ipi->next;
00481       }
00482       eroot=0;
00483       while ( (eroot = localized_walk_context_extensions(tmp, eroot)) ) {
00484          pval *exten = pvalCreateNode(PV_EXTENSION);
00485          pvalContextAddStatement(tmptree, exten);
00486          pvalExtenSetName(exten, ast_strdup(eroot->exten));
00487       
00488          if (eroot->peer) {
00489             pval *block = pvalCreateNode(PV_STATEMENTBLOCK);
00490             pvalExtenSetStatement(exten, block);
00491             
00492             e = 0;
00493             while ( (e = localized_walk_extension_priorities(eroot, e)) ) {
00494                
00495                pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL);
00496                pval *args = pvalCreateNode(PV_WORD);
00497                
00498                /* printf("           %s(%s)\n", e->app, (char*)e->data); */
00499 
00500                pvalAppCallSetAppName(statemnt, ast_strdup(e->app));
00501                pvalWordSetString(args, ast_strdup(e->data));
00502                pvalAppCallAddArg(statemnt, args);
00503                
00504                pvalStatementBlockAddStatement(block, statemnt);
00505             }
00506          } else if (eroot->priority == -1) {
00507 
00508             pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL);
00509             pval *args = pvalCreateNode(PV_WORD);
00510 
00511             /* printf("Mike, we have a hint on exten %s with data %s\n", eroot->exten, eroot->app); */
00512 
00513             pvalAppCallSetAppName(statemnt, "NoOp");
00514             pvalWordSetString(args, ast_strdup(eroot->app));
00515 
00516 
00517             pvalExtenSetStatement(exten, statemnt);
00518             pvalExtenSetHints(exten, ast_strdup(eroot->app));
00519          } else {
00520 
00521             pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL);
00522             pval *args = pvalCreateNode(PV_WORD);
00523    
00524             /* printf("           %s (%s)\n", eroot->app, (char *)eroot->data); */
00525             
00526             pvalAppCallSetAppName(statemnt, ast_strdup(eroot->app));
00527             pvalWordSetString(args, ast_strdup(eroot->data));
00528 
00529             
00530             pvalAppCallAddArg(statemnt, args);
00531             pvalExtenSetStatement(exten, statemnt);
00532          }
00533 
00534          /* printf("   extension: %s\n", eroot->exten); */
00535       }
00536       if (AST_LIST_FIRST(&tmp->alts)) {
00537          sws = pvalCreateNode(PV_SWITCHES);
00538          pvalContextAddStatement(tmptree,sws);
00539          
00540          sw = 0;
00541          while ((sw = localized_walk_context_switches(tmp,sw)) ) {
00542             pvalSwitchesAddSwitch(sws, ast_strdup(sw->name));
00543          }
00544       }
00545    }
00546    printf("Generating aelout.ael file...\n");
00547    
00548    ael2_print("aelout.ael", tree);
00549    
00550    printf("...Done!\n");
00551    return 0;
00552 }

int pbx_builtin_setvar ( struct ast_channel chan,
const char *  data 
)

Parse and set a single channel variable, where the name and value are separated with an '=' character.

Note:
Will lock the channel.

Definition at line 557 of file conf2ael.c.

References localized_pbx_builtin_setvar().

Referenced by ast_compile_ael2(), and localized_pbx_builtin_setvar().

00558 {
00559    return localized_pbx_builtin_setvar(chan, data);
00560 }

struct ast_exten* pbx_find_extension ( struct ast_channel chan,
struct ast_context bypass,
struct pbx_find_info q,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action 
) [read]

Definition at line 3166 of file pbx.c.

03170 {
03171    int x, res;
03172    struct ast_context *tmp = NULL;
03173    struct ast_exten *e = NULL, *eroot = NULL;
03174    struct ast_include *i = NULL;
03175    struct ast_sw *sw = NULL;
03176    struct ast_exten pattern = {NULL, };
03177    struct scoreboard score = {0, };
03178    struct ast_str *tmpdata = NULL;
03179 
03180    pattern.label = label;
03181    pattern.priority = priority;
03182 #ifdef NEED_DEBUG_HERE
03183    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
03184 #endif
03185 
03186    /* Initialize status if appropriate */
03187    if (q->stacklen == 0) {
03188       q->status = STATUS_NO_CONTEXT;
03189       q->swo = NULL;
03190       q->data = NULL;
03191       q->foundcontext = NULL;
03192    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
03193       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
03194       return NULL;
03195    }
03196 
03197    /* Check first to see if we've already been checked */
03198    for (x = 0; x < q->stacklen; x++) {
03199       if (!strcasecmp(q->incstack[x], context))
03200          return NULL;
03201    }
03202 
03203    if (bypass) { /* bypass means we only look there */
03204       tmp = bypass;
03205    } else {      /* look in contexts */
03206       tmp = find_context(context);
03207       if (!tmp) {
03208          return NULL;
03209       }
03210    }
03211 
03212    if (q->status < STATUS_NO_EXTENSION)
03213       q->status = STATUS_NO_EXTENSION;
03214 
03215    /* Do a search for matching extension */
03216 
03217    eroot = NULL;
03218    score.total_specificity = 0;
03219    score.exten = 0;
03220    score.total_length = 0;
03221    if (!tmp->pattern_tree && tmp->root_table) {
03222       create_match_char_tree(tmp);
03223 #ifdef NEED_DEBUG
03224       ast_debug(1, "Tree Created in context %s:\n", context);
03225       log_match_char_tree(tmp->pattern_tree," ");
03226 #endif
03227    }
03228 #ifdef NEED_DEBUG
03229    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
03230    log_match_char_tree(tmp->pattern_tree, "::  ");
03231 #endif
03232 
03233    do {
03234       if (!ast_strlen_zero(overrideswitch)) {
03235          char *osw = ast_strdupa(overrideswitch), *name;
03236          struct ast_switch *asw;
03237          ast_switch_f *aswf = NULL;
03238          char *datap;
03239          int eval = 0;
03240 
03241          name = strsep(&osw, "/");
03242          asw = pbx_findswitch(name);
03243 
03244          if (!asw) {
03245             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
03246             break;
03247          }
03248 
03249          if (osw && strchr(osw, '$')) {
03250             eval = 1;
03251          }
03252 
03253          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03254             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
03255             break;
03256          } else if (eval) {
03257             /* Substitute variables now */
03258             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03259             datap = ast_str_buffer(tmpdata);
03260          } else {
03261             datap = osw;
03262          }
03263 
03264          /* equivalent of extension_match_core() at the switch level */
03265          if (action == E_CANMATCH)
03266             aswf = asw->canmatch;
03267          else if (action == E_MATCHMORE)
03268             aswf = asw->matchmore;
03269          else /* action == E_MATCH */
03270             aswf = asw->exists;
03271          if (!aswf) {
03272             res = 0;
03273          } else {
03274             if (chan) {
03275                ast_autoservice_start(chan);
03276             }
03277             res = aswf(chan, context, exten, priority, callerid, datap);
03278             if (chan) {
03279                ast_autoservice_stop(chan);
03280             }
03281          }
03282          if (res) {  /* Got a match */
03283             q->swo = asw;
03284             q->data = datap;
03285             q->foundcontext = context;
03286             /* XXX keep status = STATUS_NO_CONTEXT ? */
03287             return NULL;
03288          }
03289       }
03290    } while (0);
03291 
03292    if (extenpatternmatchnew) {
03293       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
03294       eroot = score.exten;
03295 
03296       if (score.last_char == '!' && action == E_MATCHMORE) {
03297          /* We match an extension ending in '!'.
03298           * The decision in this case is final and is NULL (no match).
03299           */
03300 #ifdef NEED_DEBUG_HERE
03301          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
03302 #endif
03303          return NULL;
03304       }
03305 
03306       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
03307          q->status = STATUS_SUCCESS;
03308 #ifdef NEED_DEBUG_HERE
03309          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
03310 #endif
03311          return score.canmatch_exten;
03312       }
03313 
03314       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
03315          if (score.node) {
03316             struct ast_exten *z = trie_find_next_match(score.node);
03317             if (z) {
03318 #ifdef NEED_DEBUG_HERE
03319                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
03320 #endif
03321             } else {
03322                if (score.canmatch_exten) {
03323 #ifdef NEED_DEBUG_HERE
03324                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
03325 #endif
03326                   return score.canmatch_exten;
03327                } else {
03328 #ifdef NEED_DEBUG_HERE
03329                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
03330 #endif
03331                }
03332             }
03333             return z;
03334          }
03335 #ifdef NEED_DEBUG_HERE
03336          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
03337 #endif
03338          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
03339       }
03340 
03341       if (eroot) {
03342          /* found entry, now look for the right priority */
03343          if (q->status < STATUS_NO_PRIORITY)
03344             q->status = STATUS_NO_PRIORITY;
03345          e = NULL;
03346          if (action == E_FINDLABEL && label ) {
03347             if (q->status < STATUS_NO_LABEL)
03348                q->status = STATUS_NO_LABEL;
03349             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03350          } else {
03351             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03352          }
03353          if (e) { /* found a valid match */
03354             q->status = STATUS_SUCCESS;
03355             q->foundcontext = context;
03356 #ifdef NEED_DEBUG_HERE
03357             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
03358 #endif
03359             return e;
03360          }
03361       }
03362    } else {   /* the old/current default exten pattern match algorithm */
03363 
03364       /* scan the list trying to match extension and CID */
03365       eroot = NULL;
03366       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
03367          int match = extension_match_core(eroot->exten, exten, action);
03368          /* 0 on fail, 1 on match, 2 on earlymatch */
03369 
03370          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
03371             continue;   /* keep trying */
03372          if (match == 2 && action == E_MATCHMORE) {
03373             /* We match an extension ending in '!'.
03374              * The decision in this case is final and is NULL (no match).
03375              */
03376             return NULL;
03377          }
03378          /* found entry, now look for the right priority */
03379          if (q->status < STATUS_NO_PRIORITY)
03380             q->status = STATUS_NO_PRIORITY;
03381          e = NULL;
03382          if (action == E_FINDLABEL && label ) {
03383             if (q->status < STATUS_NO_LABEL)
03384                q->status = STATUS_NO_LABEL;
03385             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03386          } else {
03387             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03388          }
03389          if (e) { /* found a valid match */
03390             q->status = STATUS_SUCCESS;
03391             q->foundcontext = context;
03392             return e;
03393          }
03394       }
03395    }
03396 
03397    /* Check alternative switches */
03398    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
03399       struct ast_switch *asw = pbx_findswitch(sw->name);
03400       ast_switch_f *aswf = NULL;
03401       char *datap;
03402 
03403       if (!asw) {
03404          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
03405          continue;
03406       }
03407 
03408       /* Substitute variables now */
03409       if (sw->eval) {
03410          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03411             ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
03412             continue;
03413          }
03414          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03415       }
03416 
03417       /* equivalent of extension_match_core() at the switch level */
03418       if (action == E_CANMATCH)
03419          aswf = asw->canmatch;
03420       else if (action == E_MATCHMORE)
03421          aswf = asw->matchmore;
03422       else /* action == E_MATCH */
03423          aswf = asw->exists;
03424       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
03425       if (!aswf)
03426          res = 0;
03427       else {
03428          if (chan)
03429             ast_autoservice_start(chan);
03430          res = aswf(chan, context, exten, priority, callerid, datap);
03431          if (chan)
03432             ast_autoservice_stop(chan);
03433       }
03434       if (res) {  /* Got a match */
03435          q->swo = asw;
03436          q->data = datap;
03437          q->foundcontext = context;
03438          /* XXX keep status = STATUS_NO_CONTEXT ? */
03439          return NULL;
03440       }
03441    }
03442    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
03443    /* Now try any includes we have in this context */
03444    for (i = tmp->includes; i; i = i->next) {
03445       if (include_valid(i)) {
03446          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
03447 #ifdef NEED_DEBUG_HERE
03448             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
03449 #endif
03450             return e;
03451          }
03452          if (q->swo)
03453             return NULL;
03454       }
03455    }
03456    return NULL;
03457 }

void pbx_substitute_variables_helper ( struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 4839 of file pbx.c.

04840 {
04841    size_t used;
04842    pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, &used);
04843 }


Variable Documentation

const char* ast_config_AST_CONFIG_DIR = "/etc/asterisk"

char* config = "extensions.conf"

Definition at line 66 of file conf2ael.c.

static struct ast_context * contexts [read]

Definition at line 4724 of file extconf.c.

char* days[]

Definition at line 4073 of file extconf.c.

char* months[]

Definition at line 4085 of file extconf.c.


Generated on Thu Apr 16 06:30:19 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6