1999-10-24 18:00:20 +00:00
/*
2005-09-14 20:46:50 +00:00
* Asterisk - - An open source telephony toolkit .
1999-10-24 18:00:20 +00:00
*
2005-01-21 07:06:25 +00:00
* Copyright ( C ) 1999 - 2005 , Digium , Inc .
1999-10-24 18:00:20 +00:00
*
2004-10-02 17:16:36 +00:00
* Mark Spencer < markster @ digium . com >
1999-10-24 18:00:20 +00:00
*
2005-09-14 20:46:50 +00:00
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
* the project provides a web site , mailing lists and IRC
* channels for your use .
*
1999-10-24 18:00:20 +00:00
* This program is free software , distributed under the terms of
2005-09-14 20:46:50 +00:00
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree .
*/
2005-10-24 20:12:06 +00:00
/*! \file
*
* \ brief Configuration File Parser
2005-09-14 20:46:50 +00:00
*
2005-12-30 21:18:06 +00:00
* \ author Mark Spencer < markster @ digium . com >
*
2005-10-24 20:12:06 +00:00
* Includes the Asterisk Realtime API - ARA
2006-03-12 17:27:57 +00:00
* See doc / realtime . txt and doc / extconfig . txt
1999-10-24 18:00:20 +00:00
*/
2006-06-07 18:54:56 +00:00
# include "asterisk.h"
ASTERISK_FILE_VERSION ( __FILE__ , " $Revision$ " )
1999-10-24 18:00:20 +00:00
# include <stdio.h>
# include <unistd.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>
2003-03-09 06:00:18 +00:00
# include <time.h>
2005-10-31 21:08:55 +00:00
# include <sys/stat.h>
2004-12-11 05:16:30 +00:00
# define AST_INCLUDE_GLOB 1
# ifdef AST_INCLUDE_GLOB
2005-11-01 21:53:30 +00:00
# if defined(__Darwin__) || defined(__CYGWIN__)
2004-12-19 17:33:19 +00:00
# define GLOB_ABORTED GLOB_ABEND
# endif
2004-12-11 05:16:30 +00:00
# include <glob.h>
# endif
2005-04-22 13:11:34 +00:00
2005-04-21 06:02:45 +00:00
# include "asterisk/config.h"
# include "asterisk/cli.h"
# include "asterisk/lock.h"
# include "asterisk/options.h"
# include "asterisk/logger.h"
# include "asterisk/utils.h"
# include "asterisk/channel.h"
# include "asterisk/app.h"
1999-10-24 18:00:20 +00:00
2004-12-04 16:09:45 +00:00
# define MAX_NESTED_COMMENTS 128
# define COMMENT_START ";--"
# define COMMENT_END "--;"
# define COMMENT_META ';'
# define COMMENT_TAG '-'
2002-03-05 23:57:31 +00:00
2005-01-25 06:10:20 +00:00
static char * extconfig_conf = " extconfig.conf " ;
2004-10-05 06:46:11 +00:00
static struct ast_config_map {
struct ast_config_map * next ;
char * name ;
char * driver ;
char * database ;
char * table ;
char stuff [ 0 ] ;
2005-01-25 06:10:20 +00:00
} * config_maps = NULL ;
AST_MUTEX_DEFINE_STATIC ( config_lock ) ;
static struct ast_config_engine * config_engine_list ;
# define MAX_INCLUDE_LEVEL 10
struct ast_comment {
struct ast_comment * next ;
char cmt [ 0 ] ;
} ;
struct ast_category {
2006-02-24 10:50:43 +00:00
char name [ 80 ] ;
2005-01-30 06:26:19 +00:00
int ignored ; /* do not let user of the config see this category */
2005-01-25 06:10:20 +00:00
struct ast_variable * root ;
struct ast_variable * last ;
struct ast_category * next ;
} ;
struct ast_config {
struct ast_category * root ;
struct ast_category * last ;
struct ast_category * current ;
struct ast_category * last_browse ; /* used to cache the last category supplied via category_browse */
int include_level ;
int max_include_level ;
} ;
1999-10-24 18:00:20 +00:00
2005-01-25 06:10:20 +00:00
struct ast_variable * ast_variable_new ( const char * name , const char * value )
1999-10-24 18:00:20 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_variable * variable ;
2006-02-09 16:59:50 +00:00
int name_len = strlen ( name ) + 1 ;
2005-01-25 06:10:20 +00:00
2006-02-09 16:59:50 +00:00
if ( ( variable = ast_calloc ( 1 , name_len + strlen ( value ) + 1 + sizeof ( * variable ) ) ) ) {
2005-01-25 06:10:20 +00:00
variable - > name = variable - > stuff ;
2006-02-09 16:59:50 +00:00
variable - > value = variable - > stuff + name_len ;
2005-01-25 06:10:20 +00:00
strcpy ( variable - > name , name ) ;
strcpy ( variable - > value , value ) ;
2001-10-09 14:54:42 +00:00
}
2005-01-25 06:10:20 +00:00
return variable ;
}
void ast_variable_append ( struct ast_category * category , struct ast_variable * variable )
{
2006-04-06 16:06:57 +00:00
if ( ! variable )
return ;
2005-01-30 17:34:44 +00:00
if ( category - > last )
category - > last - > next = variable ;
else
category - > root = variable ;
category - > last = variable ;
2005-01-25 06:10:20 +00:00
}
void ast_variables_destroy ( struct ast_variable * v )
{
struct ast_variable * vn ;
while ( v ) {
vn = v ;
v = v - > next ;
free ( vn ) ;
1999-10-24 18:00:20 +00:00
}
}
2005-01-25 06:10:20 +00:00
struct ast_variable * ast_variable_browse ( const struct ast_config * config , const char * category )
{
struct ast_category * cat = NULL ;
if ( category & & config - > last_browse & & ( config - > last_browse - > name = = category ) )
cat = config - > last_browse ;
else
cat = ast_category_get ( config , category ) ;
2006-04-06 16:06:57 +00:00
return ( cat ) ? cat - > root : NULL ;
2005-01-25 06:10:20 +00:00
}
2006-09-20 20:40:39 +00:00
const char * ast_config_option ( struct ast_config * cfg , const char * cat , const char * var )
2006-09-16 23:53:58 +00:00
{
2006-09-20 20:40:39 +00:00
const char * tmp ;
2006-09-16 23:53:58 +00:00
tmp = ast_variable_retrieve ( cfg , cat , var ) ;
if ( ! tmp )
tmp = ast_variable_retrieve ( cfg , " general " , var ) ;
return tmp ;
}
2006-09-20 20:40:39 +00:00
const char * ast_variable_retrieve ( const struct ast_config * config , const char * category , const char * variable )
1999-10-24 18:00:20 +00:00
{
struct ast_variable * v ;
2005-01-25 06:10:20 +00:00
1999-12-11 20:09:45 +00:00
if ( category ) {
2005-10-17 03:53:27 +00:00
for ( v = ast_variable_browse ( config , category ) ; v ; v = v - > next ) {
2005-01-25 06:10:20 +00:00
if ( ! strcasecmp ( variable , v - > name ) )
2005-10-17 13:53:50 +00:00
return v - > value ;
2005-10-17 03:53:27 +00:00
}
1999-12-11 20:09:45 +00:00
} else {
struct ast_category * cat ;
2005-01-25 06:10:20 +00:00
for ( cat = config - > root ; cat ; cat = cat - > next )
for ( v = cat - > root ; v ; v = v - > next )
if ( ! strcasecmp ( variable , v - > name ) )
1999-12-11 20:09:45 +00:00
return v - > value ;
1999-10-24 18:00:20 +00:00
}
2005-01-25 06:10:20 +00:00
1999-10-24 18:00:20 +00:00
return NULL ;
}
2005-01-30 06:26:19 +00:00
static struct ast_variable * variable_clone ( const struct ast_variable * old )
{
struct ast_variable * new = ast_variable_new ( old - > name , old - > value ) ;
if ( new ) {
new - > lineno = old - > lineno ;
new - > object = old - > object ;
new - > blanklines = old - > blanklines ;
/* TODO: clone comments? */
}
return new ;
}
static void move_variables ( struct ast_category * old , struct ast_category * new )
{
2006-04-06 16:06:57 +00:00
struct ast_variable * var = old - > root ;
2005-01-30 06:26:19 +00:00
old - > root = NULL ;
2006-04-06 16:06:57 +00:00
# if 1
/* we can just move the entire list in a single op */
ast_variable_append ( new , var ) ;
# else
while ( var ) {
struct ast_variable * next = var - > next ;
2005-01-30 06:26:19 +00:00
var - > next = NULL ;
ast_variable_append ( new , var ) ;
2006-04-06 16:06:57 +00:00
var = next ;
2005-01-30 06:26:19 +00:00
}
2006-04-06 16:06:57 +00:00
# endif
2005-01-30 06:26:19 +00:00
}
2005-01-25 06:10:20 +00:00
struct ast_category * ast_category_new ( const char * name )
{
struct ast_category * category ;
2006-04-06 16:06:57 +00:00
if ( ( category = ast_calloc ( 1 , sizeof ( * category ) ) ) )
2005-07-10 22:56:21 +00:00
ast_copy_string ( category - > name , name , sizeof ( category - > name ) ) ;
2005-01-25 06:10:20 +00:00
return category ;
}
2005-01-30 06:26:19 +00:00
static struct ast_category * category_get ( const struct ast_config * config , const char * category_name , int ignored )
2003-03-09 06:00:18 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_category * cat ;
2004-10-05 06:46:11 +00:00
2006-04-06 16:06:57 +00:00
/* try exact match first, then case-insensitive match */
2005-01-25 06:10:20 +00:00
for ( cat = config - > root ; cat ; cat = cat - > next ) {
2005-01-30 06:26:19 +00:00
if ( cat - > name = = category_name & & ( ignored | | ! cat - > ignored ) )
2005-01-25 06:10:20 +00:00
return cat ;
}
for ( cat = config - > root ; cat ; cat = cat - > next ) {
2005-01-30 06:26:19 +00:00
if ( ! strcasecmp ( cat - > name , category_name ) & & ( ignored | | ! cat - > ignored ) )
2005-01-25 06:10:20 +00:00
return cat ;
2005-01-22 22:13:11 +00:00
}
2004-10-05 06:46:11 +00:00
2005-01-22 22:13:11 +00:00
return NULL ;
}
2005-01-30 06:26:19 +00:00
struct ast_category * ast_category_get ( const struct ast_config * config , const char * category_name )
{
return category_get ( config , category_name , 0 ) ;
}
2005-01-25 06:10:20 +00:00
int ast_category_exist ( const struct ast_config * config , const char * category_name )
2005-01-22 22:13:11 +00:00
{
return ! ! ast_category_get ( config , category_name ) ;
2003-03-09 06:00:18 +00:00
}
2005-01-25 06:10:20 +00:00
void ast_category_append ( struct ast_config * config , struct ast_category * category )
{
if ( config - > last )
config - > last - > next = category ;
else
config - > root = category ;
config - > last = category ;
config - > current = category ;
}
2004-10-05 06:46:11 +00:00
2005-01-25 06:10:20 +00:00
void ast_category_destroy ( struct ast_category * cat )
2003-03-09 06:00:18 +00:00
{
2005-01-25 06:10:20 +00:00
ast_variables_destroy ( cat - > root ) ;
free ( cat ) ;
}
2004-10-05 06:46:11 +00:00
2005-01-30 06:26:19 +00:00
static struct ast_category * next_available_category ( struct ast_category * cat )
{
for ( ; cat & & cat - > ignored ; cat = cat - > next ) ;
return cat ;
}
2005-01-25 06:10:20 +00:00
char * ast_category_browse ( struct ast_config * config , const char * prev )
{
struct ast_category * cat = NULL ;
if ( prev & & config - > last_browse & & ( config - > last_browse - > name = = prev ) )
cat = config - > last_browse - > next ;
else if ( ! prev & & config - > root )
2006-04-06 16:06:57 +00:00
cat = config - > root ;
2005-01-25 06:10:20 +00:00
else if ( prev ) {
for ( cat = config - > root ; cat ; cat = cat - > next ) {
if ( cat - > name = = prev ) {
cat = cat - > next ;
break ;
}
2003-03-09 06:00:18 +00:00
}
2005-01-25 06:10:20 +00:00
if ( ! cat ) {
for ( cat = config - > root ; cat ; cat = cat - > next ) {
if ( ! strcasecmp ( cat - > name , prev ) ) {
cat = cat - > next ;
break ;
}
}
2003-03-09 06:00:18 +00:00
}
}
2005-01-30 06:26:19 +00:00
if ( cat )
cat = next_available_category ( cat ) ;
2005-01-25 06:10:20 +00:00
config - > last_browse = cat ;
2006-04-06 16:06:57 +00:00
return ( cat ) ? cat - > name : NULL ;
2003-03-09 06:00:18 +00:00
}
2005-01-25 06:10:20 +00:00
struct ast_variable * ast_category_detach_variables ( struct ast_category * cat )
2003-03-09 06:00:18 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_variable * v ;
v = cat - > root ;
cat - > root = NULL ;
return v ;
}
void ast_category_rename ( struct ast_category * cat , const char * name )
{
2005-07-10 22:56:21 +00:00
ast_copy_string ( cat - > name , name , sizeof ( cat - > name ) ) ;
2005-01-25 06:10:20 +00:00
}
2005-01-30 06:26:19 +00:00
static void inherit_category ( struct ast_category * new , const struct ast_category * base )
{
struct ast_variable * var ;
2006-04-06 16:06:57 +00:00
for ( var = base - > root ; var ; var = var - > next )
ast_variable_append ( new , variable_clone ( var ) ) ;
2005-01-30 06:26:19 +00:00
}
2005-01-25 06:10:20 +00:00
struct ast_config * ast_config_new ( void )
{
struct ast_config * config ;
2006-04-06 16:06:57 +00:00
if ( ( config = ast_calloc ( 1 , sizeof ( * config ) ) ) )
2005-01-25 06:10:20 +00:00
config - > max_include_level = MAX_INCLUDE_LEVEL ;
return config ;
2003-03-09 06:00:18 +00:00
}
2006-07-29 22:02:37 +00:00
int ast_variable_delete ( struct ast_category * category , char * variable , char * match )
2006-07-19 13:28:38 +00:00
{
2006-07-29 22:02:37 +00:00
struct ast_variable * cur , * prev = NULL , * curn ;
int res = - 1 ;
2006-07-19 13:28:38 +00:00
cur = category - > root ;
while ( cur ) {
if ( cur - > name = = variable ) {
if ( prev ) {
prev - > next = cur - > next ;
if ( cur = = category - > last )
category - > last = prev ;
} else {
category - > root = cur - > next ;
if ( cur = = category - > last )
category - > last = NULL ;
}
cur - > next = NULL ;
ast_variables_destroy ( cur ) ;
return 0 ;
}
prev = cur ;
cur = cur - > next ;
}
2006-07-19 17:26:47 +00:00
prev = NULL ;
2006-07-19 13:28:38 +00:00
cur = category - > root ;
while ( cur ) {
2006-07-29 22:02:37 +00:00
curn = cur - > next ;
if ( ! strcasecmp ( cur - > name , variable ) & & ( ast_strlen_zero ( match ) | | ! strcasecmp ( cur - > value , match ) ) ) {
2006-07-19 13:28:38 +00:00
if ( prev ) {
prev - > next = cur - > next ;
if ( cur = = category - > last )
category - > last = prev ;
} else {
category - > root = cur - > next ;
if ( cur = = category - > last )
category - > last = NULL ;
}
cur - > next = NULL ;
ast_variables_destroy ( cur ) ;
2006-07-29 22:02:37 +00:00
res = 0 ;
} else
prev = cur ;
cur = curn ;
2006-07-19 13:28:38 +00:00
}
2006-07-29 22:02:37 +00:00
return res ;
2006-07-19 13:28:38 +00:00
}
2006-07-29 22:02:37 +00:00
int ast_variable_update ( struct ast_category * category , char * variable , char * value , char * match )
2006-07-19 13:28:38 +00:00
{
struct ast_variable * cur , * prev = NULL , * newer ;
newer = ast_variable_new ( variable , value ) ;
if ( ! newer )
return - 1 ;
cur = category - > root ;
while ( cur ) {
if ( cur - > name = = variable ) {
newer - > next = cur - > next ;
2006-07-29 22:02:37 +00:00
newer - > object = cur - > object ;
2006-07-19 13:28:38 +00:00
if ( prev )
prev - > next = newer ;
else
category - > root = newer ;
if ( category - > last = = cur )
category - > last = newer ;
cur - > next = NULL ;
ast_variables_destroy ( cur ) ;
return 0 ;
}
prev = cur ;
cur = cur - > next ;
}
2006-07-19 17:26:47 +00:00
prev = NULL ;
2006-07-19 13:28:38 +00:00
cur = category - > root ;
while ( cur ) {
2006-07-29 22:02:37 +00:00
if ( ! strcasecmp ( cur - > name , variable ) & & ( ast_strlen_zero ( match ) | | ! strcasecmp ( cur - > value , match ) ) ) {
2006-07-19 13:28:38 +00:00
newer - > next = cur - > next ;
2006-07-29 22:02:37 +00:00
newer - > object = cur - > object ;
2006-07-19 13:28:38 +00:00
if ( prev )
prev - > next = newer ;
else
category - > root = newer ;
if ( category - > last = = cur )
category - > last = newer ;
cur - > next = NULL ;
ast_variables_destroy ( cur ) ;
return 0 ;
}
prev = cur ;
cur = cur - > next ;
}
if ( prev )
prev - > next = newer ;
else
category - > root = newer ;
return 0 ;
}
int ast_category_delete ( struct ast_config * cfg , char * category )
{
struct ast_category * prev = NULL , * cat ;
cat = cfg - > root ;
while ( cat ) {
if ( cat - > name = = category ) {
ast_variables_destroy ( cat - > root ) ;
if ( prev ) {
prev - > next = cat - > next ;
if ( cat = = cfg - > last )
cfg - > last = prev ;
} else {
cfg - > root = cat - > next ;
if ( cat = = cfg - > last )
cfg - > last = NULL ;
}
free ( cat ) ;
return 0 ;
}
prev = cat ;
cat = cat - > next ;
}
2006-07-19 17:26:47 +00:00
prev = NULL ;
2006-07-19 13:28:38 +00:00
cat = cfg - > root ;
while ( cat ) {
if ( ! strcasecmp ( cat - > name , category ) ) {
ast_variables_destroy ( cat - > root ) ;
if ( prev ) {
prev - > next = cat - > next ;
if ( cat = = cfg - > last )
cfg - > last = prev ;
} else {
cfg - > root = cat - > next ;
if ( cat = = cfg - > last )
cfg - > last = NULL ;
}
free ( cat ) ;
return 0 ;
}
prev = cat ;
cat = cat - > next ;
}
return - 1 ;
}
2005-01-25 06:10:20 +00:00
void ast_config_destroy ( struct ast_config * cfg )
2001-04-23 16:50:12 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_category * cat , * catn ;
if ( ! cfg )
return ;
cat = cfg - > root ;
while ( cat ) {
ast_variables_destroy ( cat - > root ) ;
catn = cat ;
cat = cat - > next ;
free ( catn ) ;
}
free ( cfg ) ;
2001-04-23 16:50:12 +00:00
}
2005-01-25 06:10:20 +00:00
struct ast_category * ast_config_get_current_category ( const struct ast_config * cfg )
2005-01-22 22:13:11 +00:00
{
2005-01-25 06:10:20 +00:00
return cfg - > current ;
2005-01-22 22:13:11 +00:00
}
2003-04-28 19:58:43 +00:00
2005-01-25 06:10:20 +00:00
void ast_config_set_current_category ( struct ast_config * cfg , const struct ast_category * cat )
2005-01-22 22:13:11 +00:00
{
2005-01-25 06:10:20 +00:00
/* cast below is just to silence compiler warning about dropping "const" */
cfg - > current = ( struct ast_category * ) cat ;
2005-01-22 22:13:11 +00:00
}
2004-12-28 14:53:40 +00:00
2006-07-19 13:28:38 +00:00
static int process_text_line ( struct ast_config * cfg , struct ast_category * * cat , char * buf , int lineno , const char * configfile , int withcomments )
2002-03-05 23:57:31 +00:00
{
char * c ;
2005-01-30 06:26:19 +00:00
char * cur = buf ;
2002-03-05 23:57:31 +00:00
struct ast_variable * v ;
2005-02-02 03:38:24 +00:00
char cmd [ 512 ] , exec_file [ 512 ] ;
int object , do_exec , do_include ;
2005-01-22 22:13:11 +00:00
/* Actually parse the entry */
if ( cur [ 0 ] = = ' [ ' ) {
2005-01-30 06:26:19 +00:00
struct ast_category * newcat = NULL ;
char * catname ;
2005-01-22 22:13:11 +00:00
/* A category header */
c = strchr ( cur , ' ] ' ) ;
if ( ! c ) {
ast_log ( LOG_WARNING , " parse error: no closing ']', line %d of %s \n " , lineno , configfile ) ;
return - 1 ;
}
2005-01-30 06:26:19 +00:00
* c + + = ' \0 ' ;
2005-01-22 22:13:11 +00:00
cur + + ;
2005-01-30 06:26:19 +00:00
if ( * c + + ! = ' ( ' )
c = NULL ;
catname = cur ;
2006-02-09 16:59:50 +00:00
if ( ! ( * cat = newcat = ast_category_new ( catname ) ) ) {
2005-01-22 22:13:11 +00:00
return - 1 ;
}
2005-01-30 06:26:19 +00:00
/* If there are options or categories to inherit from, process them now */
if ( c ) {
if ( ! ( cur = strchr ( c , ' ) ' ) ) ) {
ast_log ( LOG_WARNING , " parse error: no closing ')', line %d of %s \n " , lineno , configfile ) ;
return - 1 ;
}
* cur = ' \0 ' ;
while ( ( cur = strsep ( & c , " , " ) ) ) {
if ( ! strcasecmp ( cur , " ! " ) ) {
( * cat ) - > ignored = 1 ;
} else if ( ! strcasecmp ( cur , " + " ) ) {
* cat = category_get ( cfg , catname , 1 ) ;
if ( ! * cat ) {
2005-08-30 18:32:10 +00:00
ast_config_destroy ( cfg ) ;
2005-01-30 06:26:19 +00:00
if ( newcat )
ast_category_destroy ( newcat ) ;
ast_log ( LOG_WARNING , " Category addition requested, but category '%s' does not exist, line %d of %s \n " , catname , lineno , configfile ) ;
return - 1 ;
}
if ( newcat ) {
move_variables ( newcat , * cat ) ;
ast_category_destroy ( newcat ) ;
newcat = NULL ;
}
} else {
struct ast_category * base ;
base = category_get ( cfg , cur , 1 ) ;
if ( ! base ) {
ast_log ( LOG_WARNING , " Inheritance requested, but category '%s' does not exist, line %d of %s \n " , cur , lineno , configfile ) ;
return - 1 ;
}
inherit_category ( * cat , base ) ;
}
}
}
if ( newcat )
ast_category_append ( cfg , * cat ) ;
2005-01-22 22:13:11 +00:00
} else if ( cur [ 0 ] = = ' # ' ) {
/* A directive */
cur + + ;
c = cur ;
while ( * c & & ( * c > 32 ) ) c + + ;
if ( * c ) {
* c = ' \0 ' ;
/* Find real argument */
2006-01-07 15:18:23 +00:00
c = ast_skip_blanks ( c + 1 ) ;
2005-01-22 22:13:11 +00:00
if ( ! * c )
2005-01-22 21:00:31 +00:00
c = NULL ;
2005-01-22 22:13:11 +00:00
} else
c = NULL ;
2005-02-02 03:38:24 +00:00
do_include = ! strcasecmp ( cur , " include " ) ;
if ( ! do_include )
do_exec = ! strcasecmp ( cur , " exec " ) ;
else
do_exec = 0 ;
2005-12-04 20:40:46 +00:00
if ( do_exec & & ! ast_opt_exec_includes ) {
2005-02-02 19:48:53 +00:00
ast_log ( LOG_WARNING , " Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)! \n " ) ;
2005-02-02 03:38:24 +00:00
do_exec = 0 ;
}
if ( do_include | | do_exec ) {
2005-01-22 22:13:11 +00:00
if ( c ) {
/* Strip off leading and trailing "'s and <>'s */
while ( ( * c = = ' < ' ) | | ( * c = = ' > ' ) | | ( * c = = ' \" ' ) ) c + + ;
/* Get rid of leading mess */
cur = c ;
while ( ! ast_strlen_zero ( cur ) ) {
c = cur + strlen ( cur ) - 1 ;
if ( ( * c = = ' > ' ) | | ( * c = = ' < ' ) | | ( * c = = ' \" ' ) )
2005-01-22 21:00:31 +00:00
* c = ' \0 ' ;
2005-01-22 22:13:11 +00:00
else
break ;
}
2005-02-02 03:38:24 +00:00
/* #exec </path/to/executable>
We create a tmp file , then we # include it , then we delete it . */
if ( do_exec ) {
2005-12-26 18:35:28 +00:00
snprintf ( exec_file , sizeof ( exec_file ) , " /var/tmp/exec.%d.%ld " , ( int ) time ( NULL ) , ( long ) pthread_self ( ) ) ;
2005-02-02 03:38:24 +00:00
snprintf ( cmd , sizeof ( cmd ) , " %s > %s 2>&1 " , cur , exec_file ) ;
ast_safe_system ( cmd ) ;
cur = exec_file ;
} else
exec_file [ 0 ] = ' \0 ' ;
/* A #include */
2006-07-19 13:28:38 +00:00
do_include = ast_config_internal_load ( cur , cfg , withcomments ) ? 1 : 0 ;
2005-02-02 03:38:24 +00:00
if ( ! ast_strlen_zero ( exec_file ) )
unlink ( exec_file ) ;
if ( ! do_include )
2005-06-07 21:28:04 +00:00
return 0 ;
2005-02-02 03:38:24 +00:00
} else {
ast_log ( LOG_WARNING , " Directive '#%s' needs an argument (%s) at line %d of %s \n " ,
do_exec ? " exec " : " include " ,
do_exec ? " /path/to/executable " : " filename " ,
lineno ,
configfile ) ;
}
2005-01-22 22:13:11 +00:00
}
else
ast_log ( LOG_WARNING , " Unknown directive '%s' at line %d of %s \n " , cur , lineno , configfile ) ;
} else {
/* Just a line (variable = value) */
if ( ! * cat ) {
ast_log ( LOG_WARNING ,
" parse error: No category context for line %d of %s \n " , lineno , configfile ) ;
return - 1 ;
}
c = strchr ( cur , ' = ' ) ;
if ( c ) {
* c = 0 ;
c + + ;
/* Ignore > in => */
if ( * c = = ' > ' ) {
object = 1 ;
2005-01-22 21:00:31 +00:00
c + + ;
2005-01-22 22:13:11 +00:00
} else
object = 0 ;
2006-02-09 16:59:50 +00:00
if ( ( v = ast_variable_new ( ast_strip ( cur ) , ast_strip ( c ) ) ) ) {
2005-01-22 22:13:11 +00:00
v - > lineno = lineno ;
v - > object = object ;
/* Put and reset comments */
v - > blanklines = 0 ;
2005-01-25 06:10:20 +00:00
ast_variable_append ( * cat , v ) ;
2005-01-22 21:00:31 +00:00
} else {
2005-01-22 22:13:11 +00:00
return - 1 ;
2005-01-22 21:00:31 +00:00
}
2005-01-22 22:13:11 +00:00
} else {
ast_log ( LOG_WARNING , " No '=' (equal sign) in line %d of %s \n " , lineno , configfile ) ;
2003-03-09 06:00:18 +00:00
}
2005-01-22 22:13:11 +00:00
2002-03-05 23:57:31 +00:00
}
return 0 ;
}
2006-07-19 13:28:38 +00:00
static struct ast_config * config_text_file_load ( const char * database , const char * table , const char * filename , struct ast_config * cfg , int withcomments )
1999-10-24 18:00:20 +00:00
{
2006-02-24 10:50:43 +00:00
char fn [ 256 ] ;
2004-06-12 14:34:15 +00:00
char buf [ 8192 ] ;
2005-01-25 06:10:20 +00:00
char * new_buf , * comment_p , * process_buf ;
1999-10-24 18:00:20 +00:00
FILE * f ;
2006-02-24 10:50:43 +00:00
int lineno = 0 ;
2004-12-04 16:09:45 +00:00
int comment = 0 , nest [ MAX_NESTED_COMMENTS ] ;
2005-01-25 06:10:20 +00:00
struct ast_category * cat = NULL ;
2005-06-07 21:28:04 +00:00
int count = 0 ;
2005-10-31 21:08:55 +00:00
struct stat statbuf ;
2004-12-04 16:09:45 +00:00
2005-01-25 06:10:20 +00:00
cat = ast_config_get_current_category ( cfg ) ;
2004-06-17 04:53:55 +00:00
2005-01-25 06:10:20 +00:00
if ( filename [ 0 ] = = ' / ' ) {
2005-07-10 22:56:21 +00:00
ast_copy_string ( fn , filename , sizeof ( fn ) ) ;
1999-10-24 18:00:20 +00:00
} else {
2005-01-25 06:10:20 +00:00
snprintf ( fn , sizeof ( fn ) , " %s/%s " , ( char * ) ast_config_AST_CONFIG_DIR , filename ) ;
1999-10-24 18:00:20 +00:00
}
2005-01-25 06:10:20 +00:00
2004-12-11 05:16:30 +00:00
# ifdef AST_INCLUDE_GLOB
{
int glob_ret ;
glob_t globbuf ;
globbuf . gl_offs = 0 ; /* initialize it to silence gcc */
2004-12-15 16:00:10 +00:00
# ifdef SOLARIS
2004-12-15 16:01:13 +00:00
glob_ret = glob ( fn , GLOB_NOCHECK , NULL , & globbuf ) ;
2004-12-15 16:00:10 +00:00
# else
glob_ret = glob ( fn , GLOB_NOMAGIC | GLOB_BRACE , NULL , & globbuf ) ;
# endif
2004-12-11 05:16:30 +00:00
if ( glob_ret = = GLOB_NOSPACE )
ast_log ( LOG_WARNING ,
" Glob Expansion of pattern '%s' failed: Not enough memory \n " , fn ) ;
else if ( glob_ret = = GLOB_ABORTED )
ast_log ( LOG_WARNING ,
" Glob Expansion of pattern '%s' failed: Read error \n " , fn ) ;
else {
/* loop over expanded files */
int i ;
for ( i = 0 ; i < globbuf . gl_pathc ; i + + ) {
2005-07-10 22:56:21 +00:00
ast_copy_string ( fn , globbuf . gl_pathv [ i ] , sizeof ( fn ) ) ;
2004-12-11 05:16:30 +00:00
# endif
2005-10-31 21:08:55 +00:00
do {
2005-11-07 22:05:31 +00:00
if ( stat ( fn , & statbuf ) )
2005-10-31 21:08:55 +00:00
continue ;
2005-11-07 22:05:31 +00:00
2005-10-31 21:08:55 +00:00
if ( ! S_ISREG ( statbuf . st_mode ) ) {
ast_log ( LOG_WARNING , " '%s' is not a regular file, ignoring \n " , fn ) ;
continue ;
}
2006-09-19 16:23:45 +00:00
if ( option_verbose > 1 ) {
2005-10-31 21:08:55 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " Parsing '%s': " , fn ) ;
fflush ( stdout ) ;
}
if ( ! ( f = fopen ( fn , " r " ) ) ) {
if ( option_debug )
ast_log ( LOG_DEBUG , " No file to parse: %s \n " , fn ) ;
2006-09-19 16:23:45 +00:00
if ( option_verbose > 1 )
2005-10-31 21:08:55 +00:00
ast_verbose ( " Not found (%s) \n " , strerror ( errno ) ) ;
continue ;
}
2005-06-07 21:28:04 +00:00
count + + ;
1999-10-24 18:00:20 +00:00
if ( option_debug )
ast_log ( LOG_DEBUG , " Parsing %s \n " , fn ) ;
2006-09-19 16:23:45 +00:00
if ( option_verbose > 1 )
2005-01-22 22:13:11 +00:00
ast_verbose ( " Found \n " ) ;
while ( ! feof ( f ) ) {
lineno + + ;
if ( fgets ( buf , sizeof ( buf ) , f ) ) {
new_buf = buf ;
if ( comment )
process_buf = NULL ;
else
process_buf = buf ;
while ( ( comment_p = strchr ( new_buf , COMMENT_META ) ) ) {
if ( ( comment_p > new_buf ) & & ( * ( comment_p - 1 ) = = ' \\ ' ) ) {
/* Yuck, gotta memmove */
memmove ( comment_p - 1 , comment_p , strlen ( comment_p ) + 1 ) ;
new_buf = comment_p ;
} else if ( comment_p [ 1 ] = = COMMENT_TAG & & comment_p [ 2 ] = = COMMENT_TAG & & ( comment_p [ 3 ] ! = ' - ' ) ) {
/* Meta-Comment start detected ";--" */
if ( comment < MAX_NESTED_COMMENTS ) {
* comment_p = ' \0 ' ;
new_buf = comment_p + 3 ;
comment + + ;
nest [ comment - 1 ] = lineno ;
2004-12-04 16:09:45 +00:00
} else {
2005-01-22 22:13:11 +00:00
ast_log ( LOG_ERROR , " Maximum nest limit of %d reached. \n " , MAX_NESTED_COMMENTS ) ;
}
} else if ( ( comment_p > = new_buf + 2 ) & &
( * ( comment_p - 1 ) = = COMMENT_TAG ) & &
( * ( comment_p - 2 ) = = COMMENT_TAG ) ) {
/* Meta-Comment end detected */
comment - - ;
new_buf = comment_p + 1 ;
if ( ! comment ) {
/* Back to non-comment now */
if ( process_buf ) {
/* Actually have to move what's left over the top, then continue */
char * oldptr ;
oldptr = process_buf + strlen ( process_buf ) ;
memmove ( oldptr , new_buf , strlen ( new_buf ) + 1 ) ;
new_buf = oldptr ;
2004-12-04 16:09:45 +00:00
} else
2005-01-22 22:13:11 +00:00
process_buf = new_buf ;
2004-12-04 16:09:45 +00:00
}
2005-01-22 22:13:11 +00:00
} else {
if ( ! comment ) {
/* If ; is found, and we are not nested in a comment,
we immediately stop all comment processing */
* comment_p = ' \0 ' ;
new_buf = comment_p ;
} else
new_buf = comment_p + 1 ;
2004-12-04 16:09:45 +00:00
}
2005-01-22 22:13:11 +00:00
}
2005-01-30 06:26:19 +00:00
if ( process_buf ) {
char * buf = ast_strip ( process_buf ) ;
2005-10-26 18:54:24 +00:00
if ( ! ast_strlen_zero ( buf ) ) {
2006-07-19 13:28:38 +00:00
if ( process_text_line ( cfg , & cat , buf , lineno , filename , withcomments ) ) {
2005-01-30 06:26:19 +00:00
cfg = NULL ;
break ;
}
2005-10-26 18:54:24 +00:00
}
1999-10-24 18:00:20 +00:00
}
}
2005-01-22 22:13:11 +00:00
}
1999-10-24 18:00:20 +00:00
fclose ( f ) ;
2005-10-31 21:08:55 +00:00
} while ( 0 ) ;
2004-12-04 16:09:45 +00:00
if ( comment ) {
ast_log ( LOG_WARNING , " Unterminated comment detected beginning on line %d \n " , nest [ comment ] ) ;
}
2004-12-11 05:16:30 +00:00
# ifdef AST_INCLUDE_GLOB
2005-01-25 06:10:20 +00:00
if ( ! cfg )
2004-12-11 05:16:30 +00:00
break ;
}
globfree ( & globbuf ) ;
}
}
# endif
2005-06-07 21:28:04 +00:00
if ( count = = 0 )
return NULL ;
2004-12-11 05:16:30 +00:00
2005-01-25 06:10:20 +00:00
return cfg ;
1999-10-24 18:00:20 +00:00
}
2005-01-25 06:10:20 +00:00
int config_text_file_save ( const char * configfile , const struct ast_config * cfg , const char * generator )
2004-06-17 04:53:55 +00:00
{
2005-01-25 06:10:20 +00:00
FILE * f ;
2006-02-24 10:50:43 +00:00
char fn [ 256 ] ;
2005-01-25 06:10:20 +00:00
char date [ 256 ] = " " ;
time_t t ;
struct ast_variable * var ;
struct ast_category * cat ;
int blanklines = 0 ;
if ( configfile [ 0 ] = = ' / ' ) {
2005-06-06 03:04:58 +00:00
ast_copy_string ( fn , configfile , sizeof ( fn ) ) ;
2004-06-17 04:53:55 +00:00
} else {
2005-05-08 17:31:09 +00:00
snprintf ( fn , sizeof ( fn ) , " %s/%s " , ast_config_AST_CONFIG_DIR , configfile ) ;
2004-06-11 00:12:35 +00:00
}
2005-01-25 06:10:20 +00:00
time ( & t ) ;
2005-07-10 22:56:21 +00:00
ast_copy_string ( date , ctime ( & t ) , sizeof ( date ) ) ;
2005-11-01 21:53:30 +00:00
# ifdef __CYGWIN__
if ( ( f = fopen ( fn , " w+ " ) ) ) {
# else
2005-01-25 06:10:20 +00:00
if ( ( f = fopen ( fn , " w " ) ) ) {
2005-11-01 21:53:30 +00:00
# endif
2006-09-19 16:23:45 +00:00
if ( option_verbose > 1 )
2005-01-25 06:10:20 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " Saving '%s': " , fn ) ;
fprintf ( f , " ;! \n " ) ;
fprintf ( f , " ;! Automatically generated configuration file \n " ) ;
fprintf ( f , " ;! Filename: %s (%s) \n " , configfile , fn ) ;
fprintf ( f , " ;! Generator: %s \n " , generator ) ;
fprintf ( f , " ;! Creation Date: %s " , date ) ;
fprintf ( f , " ;! \n " ) ;
cat = cfg - > root ;
while ( cat ) {
/* Dump section with any appropriate comment */
2006-07-19 13:28:38 +00:00
fprintf ( f , " \n [%s] \n " , cat - > name ) ;
2005-01-25 06:10:20 +00:00
var = cat - > root ;
while ( var ) {
if ( var - > sameline )
fprintf ( f , " %s %s %s ; %s \n " , var - > name , ( var - > object ? " => " : " = " ) , var - > value , var - > sameline - > cmt ) ;
else
fprintf ( f , " %s %s %s \n " , var - > name , ( var - > object ? " => " : " = " ) , var - > value ) ;
if ( var - > blanklines ) {
blanklines = var - > blanklines ;
while ( blanklines - - )
fprintf ( f , " \n " ) ;
}
var = var - > next ;
}
#if 0
/* Put an empty line */
fprintf ( f , " \n " ) ;
# endif
cat = cat - > next ;
}
2006-07-19 13:28:38 +00:00
if ( ( option_verbose > 1 ) & & ! option_debug )
ast_verbose ( " Saved \n " ) ;
2005-01-25 06:10:20 +00:00
} else {
if ( option_debug )
printf ( " Unable to open for writing: %s \n " , fn ) ;
2006-09-19 16:23:45 +00:00
if ( option_verbose > 1 )
2005-01-25 06:10:20 +00:00
printf ( " Unable to write (%s) " , strerror ( errno ) ) ;
return - 1 ;
}
fclose ( f ) ;
return 0 ;
}
static void clear_config_maps ( void )
{
struct ast_config_map * map ;
ast_mutex_lock ( & config_lock ) ;
while ( config_maps ) {
map = config_maps ;
config_maps = config_maps - > next ;
free ( map ) ;
}
ast_mutex_unlock ( & config_lock ) ;
}
2005-02-10 21:14:11 +00:00
static int append_mapping ( char * name , char * driver , char * database , char * table )
{
struct ast_config_map * map ;
int length ;
length = sizeof ( * map ) ;
length + = strlen ( name ) + 1 ;
length + = strlen ( driver ) + 1 ;
length + = strlen ( database ) + 1 ;
if ( table )
length + = strlen ( table ) + 1 ;
2006-02-09 16:59:50 +00:00
if ( ! ( map = ast_calloc ( 1 , length ) ) )
2005-02-10 21:14:11 +00:00
return - 1 ;
map - > name = map - > stuff ;
strcpy ( map - > name , name ) ;
map - > driver = map - > name + strlen ( map - > name ) + 1 ;
strcpy ( map - > driver , driver ) ;
map - > database = map - > driver + strlen ( map - > driver ) + 1 ;
strcpy ( map - > database , database ) ;
if ( table ) {
map - > table = map - > database + strlen ( map - > database ) + 1 ;
strcpy ( map - > table , table ) ;
}
map - > next = config_maps ;
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Binding %s to %s/%s/%s \n " ,
map - > name , map - > driver , map - > database , map - > table ? map - > table : map - > name ) ;
config_maps = map ;
return 0 ;
}
2006-02-14 23:08:06 +00:00
int read_config_maps ( void )
2005-01-25 06:10:20 +00:00
{
2005-06-07 21:28:04 +00:00
struct ast_config * config , * configtmp ;
2005-01-25 06:10:20 +00:00
struct ast_variable * v ;
char * driver , * table , * database , * stringp ;
clear_config_maps ( ) ;
2005-06-07 21:28:04 +00:00
configtmp = ast_config_new ( ) ;
configtmp - > max_include_level = 1 ;
2006-07-19 13:28:38 +00:00
config = ast_config_internal_load ( extconfig_conf , configtmp , 0 ) ;
2005-06-07 21:28:04 +00:00
if ( ! config ) {
ast_config_destroy ( configtmp ) ;
2006-02-14 23:08:06 +00:00
return 0 ;
2005-06-07 21:28:04 +00:00
}
2005-01-25 06:10:20 +00:00
for ( v = ast_variable_browse ( config , " settings " ) ; v ; v = v - > next ) {
stringp = v - > value ;
driver = strsep ( & stringp , " , " ) ;
2005-12-27 06:42:29 +00:00
/* check if the database text starts with a double quote */
if ( * stringp = = ' " ' ) {
stringp + + ;
database = strsep ( & stringp , " \" " ) ;
strsep ( & stringp , " , " ) ;
} else {
/* apparently this text has no quotes */
database = strsep ( & stringp , " , " ) ;
}
2005-01-25 06:10:20 +00:00
table = strsep ( & stringp , " , " ) ;
2005-12-27 06:42:29 +00:00
2005-07-05 22:11:43 +00:00
if ( ! strcmp ( v - > name , extconfig_conf ) ) {
ast_log ( LOG_WARNING , " Cannot bind '%s'! \n " , extconfig_conf ) ;
continue ;
}
if ( ! strcmp ( v - > name , " asterisk.conf " ) ) {
ast_log ( LOG_WARNING , " Cannot bind 'asterisk.conf'! \n " ) ;
continue ;
}
if ( ! strcmp ( v - > name , " logger.conf " ) ) {
ast_log ( LOG_WARNING , " Cannot bind 'logger.conf'! \n " ) ;
2005-01-25 06:10:20 +00:00
continue ;
}
if ( ! driver | | ! database )
continue ;
2005-02-10 21:14:11 +00:00
if ( ! strcasecmp ( v - > name , " sipfriends " ) ) {
ast_log ( LOG_WARNING , " The 'sipfriends' table is obsolete, update your config to use sipusers and sippeers, though they can point to the same table. \n " ) ;
append_mapping ( " sipusers " , driver , database , table ? table : " sipfriends " ) ;
append_mapping ( " sippeers " , driver , database , table ? table : " sipfriends " ) ;
} else if ( ! strcasecmp ( v - > name , " iaxfriends " ) ) {
ast_log ( LOG_WARNING , " The 'iaxfriends' table is obsolete, update your config to use iaxusers and iaxpeers, though they can point to the same table. \n " ) ;
append_mapping ( " iaxusers " , driver , database , table ? table : " iaxfriends " ) ;
append_mapping ( " iaxpeers " , driver , database , table ? table : " iaxfriends " ) ;
} else
append_mapping ( v - > name , driver , database , table ) ;
2005-01-25 06:10:20 +00:00
}
ast_config_destroy ( config ) ;
2006-02-14 23:08:06 +00:00
return 0 ;
2005-01-25 06:10:20 +00:00
}
int ast_config_engine_register ( struct ast_config_engine * new )
{
struct ast_config_engine * ptr ;
ast_mutex_lock ( & config_lock ) ;
if ( ! config_engine_list ) {
config_engine_list = new ;
} else {
for ( ptr = config_engine_list ; ptr - > next ; ptr = ptr - > next ) ;
ptr - > next = new ;
}
ast_mutex_unlock ( & config_lock ) ;
ast_log ( LOG_NOTICE , " Registered Config Engine %s \n " , new - > name ) ;
2004-06-11 00:12:35 +00:00
return 1 ;
}
2005-01-25 06:10:20 +00:00
int ast_config_engine_deregister ( struct ast_config_engine * del )
2004-06-17 04:53:55 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_config_engine * ptr , * last = NULL ;
ast_mutex_lock ( & config_lock ) ;
for ( ptr = config_engine_list ; ptr ; ptr = ptr - > next ) {
2004-06-17 04:53:55 +00:00
if ( ptr = = del ) {
2005-01-25 06:10:20 +00:00
if ( last )
2004-06-17 04:53:55 +00:00
last - > next = ptr - > next ;
2005-01-25 06:10:20 +00:00
else
config_engine_list = ptr - > next ;
break ;
2004-06-17 04:53:55 +00:00
}
last = ptr ;
}
2004-06-11 00:12:35 +00:00
2005-01-25 06:10:20 +00:00
ast_mutex_unlock ( & config_lock ) ;
return 0 ;
2004-06-11 00:12:35 +00:00
}
2006-01-20 00:18:42 +00:00
/*! \brief Find realtime engine for realtime family */
2005-08-23 01:44:28 +00:00
static struct ast_config_engine * find_engine ( const char * family , char * database , int dbsiz , char * table , int tabsiz )
2002-03-05 23:57:31 +00:00
{
2005-07-05 21:17:58 +00:00
struct ast_config_engine * eng , * ret = NULL ;
2005-01-25 06:10:20 +00:00
struct ast_config_map * map ;
2002-03-05 23:57:31 +00:00
2005-01-25 06:10:20 +00:00
ast_mutex_lock ( & config_lock ) ;
2004-11-23 17:58:59 +00:00
2005-07-05 21:17:58 +00:00
for ( map = config_maps ; map ; map = map - > next ) {
2005-08-23 01:44:28 +00:00
if ( ! strcasecmp ( family , map - > name ) ) {
if ( database )
ast_copy_string ( database , map - > database , dbsiz ) ;
if ( table )
ast_copy_string ( table , map - > table ? map - > table : family , tabsiz ) ;
2005-01-25 06:10:20 +00:00
break ;
2001-10-09 14:54:42 +00:00
}
}
2005-08-23 01:44:28 +00:00
/* Check if the required driver (engine) exist */
2005-01-25 06:10:20 +00:00
if ( map ) {
2005-07-05 21:17:58 +00:00
for ( eng = config_engine_list ; ! ret & & eng ; eng = eng - > next ) {
if ( ! strcasecmp ( eng - > name , map - > driver ) )
2005-01-25 06:10:20 +00:00
ret = eng ;
1999-10-24 18:00:20 +00:00
}
}
2005-07-05 21:17:58 +00:00
2005-01-25 06:10:20 +00:00
ast_mutex_unlock ( & config_lock ) ;
2005-07-05 21:17:58 +00:00
/* if we found a mapping, but the engine is not available, then issue a warning */
if ( map & & ! ret )
2005-08-23 01:44:28 +00:00
ast_log ( LOG_WARNING , " Realtime mapping for '%s' found to engine '%s', but the engine is not available \n " , map - > name , map - > driver ) ;
2005-01-25 06:10:20 +00:00
return ret ;
1999-10-24 18:00:20 +00:00
}
2004-06-11 00:12:35 +00:00
2005-01-25 06:10:20 +00:00
static struct ast_config_engine text_file_engine = {
. name = " text " ,
. load_func = config_text_file_load ,
} ;
2004-06-11 00:12:35 +00:00
2006-07-19 13:28:38 +00:00
struct ast_config * ast_config_internal_load ( const char * filename , struct ast_config * cfg , int withcomments )
2004-06-17 04:53:55 +00:00
{
2006-02-24 10:50:43 +00:00
char db [ 256 ] ;
char table [ 256 ] ;
2005-01-25 06:10:20 +00:00
struct ast_config_engine * loader = & text_file_engine ;
struct ast_config * result ;
2004-06-11 00:12:35 +00:00
2005-01-25 06:10:20 +00:00
if ( cfg - > include_level = = cfg - > max_include_level ) {
ast_log ( LOG_WARNING , " Maximum Include level (%d) exceeded \n " , cfg - > max_include_level ) ;
return NULL ;
2004-06-11 00:12:35 +00:00
}
2005-01-25 06:10:20 +00:00
cfg - > include_level + + ;
if ( strcmp ( filename , extconfig_conf ) & & strcmp ( filename , " asterisk.conf " ) & & config_engine_list ) {
struct ast_config_engine * eng ;
eng = find_engine ( filename , db , sizeof ( db ) , table , sizeof ( table ) ) ;
2005-02-02 03:38:24 +00:00
2005-01-25 06:10:20 +00:00
if ( eng & & eng - > load_func ) {
loader = eng ;
} else {
eng = find_engine ( " global " , db , sizeof ( db ) , table , sizeof ( table ) ) ;
if ( eng & & eng - > load_func )
loader = eng ;
}
}
2006-07-19 13:28:38 +00:00
result = loader - > load_func ( db , table , filename , cfg , withcomments ) ;
2005-02-02 03:38:24 +00:00
2005-01-25 06:10:20 +00:00
if ( result )
result - > include_level - - ;
return result ;
2004-06-11 00:12:35 +00:00
}
2005-01-25 06:10:20 +00:00
struct ast_config * ast_config_load ( const char * filename )
2004-06-17 04:53:55 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_config * cfg ;
struct ast_config * result ;
cfg = ast_config_new ( ) ;
if ( ! cfg )
return NULL ;
2006-07-19 13:28:38 +00:00
result = ast_config_internal_load ( filename , cfg , 0 ) ;
if ( ! result )
ast_config_destroy ( cfg ) ;
return result ;
}
struct ast_config * ast_config_load_with_comments ( const char * filename )
{
struct ast_config * cfg ;
struct ast_config * result ;
cfg = ast_config_new ( ) ;
if ( ! cfg )
return NULL ;
result = ast_config_internal_load ( filename , cfg , 1 ) ;
2005-01-25 06:10:20 +00:00
if ( ! result )
ast_config_destroy ( cfg ) ;
return result ;
2004-06-11 00:12:35 +00:00
}
2005-01-25 06:10:20 +00:00
struct ast_variable * ast_load_realtime ( const char * family , . . . )
2004-06-17 04:53:55 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_config_engine * eng ;
2006-02-24 10:50:43 +00:00
char db [ 256 ] = " " ;
char table [ 256 ] = " " ;
2005-01-25 06:10:20 +00:00
struct ast_variable * res = NULL ;
va_list ap ;
va_start ( ap , family ) ;
eng = find_engine ( family , db , sizeof ( db ) , table , sizeof ( table ) ) ;
if ( eng & & eng - > realtime_func )
res = eng - > realtime_func ( db , table , ap ) ;
va_end ( ap ) ;
return res ;
2004-06-11 00:12:35 +00:00
}
2005-01-25 06:10:20 +00:00
2006-01-20 00:18:42 +00:00
/*! \brief Check if realtime engine is configured for family */
2005-08-23 01:44:28 +00:00
int ast_check_realtime ( const char * family )
{
struct ast_config_engine * eng ;
eng = find_engine ( family , NULL , 0 , NULL , 0 ) ;
if ( eng )
return 1 ;
return 0 ;
}
2005-01-25 06:10:20 +00:00
struct ast_config * ast_load_realtime_multientry ( const char * family , . . . )
2004-06-17 04:53:55 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_config_engine * eng ;
2006-02-24 10:50:43 +00:00
char db [ 256 ] = " " ;
char table [ 256 ] = " " ;
2005-01-25 06:10:20 +00:00
struct ast_config * res = NULL ;
va_list ap ;
va_start ( ap , family ) ;
eng = find_engine ( family , db , sizeof ( db ) , table , sizeof ( table ) ) ;
if ( eng & & eng - > realtime_multi_func )
res = eng - > realtime_multi_func ( db , table , ap ) ;
va_end ( ap ) ;
return res ;
2004-06-11 00:12:35 +00:00
}
2005-01-25 06:10:20 +00:00
int ast_update_realtime ( const char * family , const char * keyfield , const char * lookup , . . . )
2004-06-17 04:53:55 +00:00
{
2005-01-25 06:10:20 +00:00
struct ast_config_engine * eng ;
int res = - 1 ;
2006-02-24 10:50:43 +00:00
char db [ 256 ] = " " ;
char table [ 256 ] = " " ;
2005-01-25 06:10:20 +00:00
va_list ap ;
va_start ( ap , lookup ) ;
eng = find_engine ( family , db , sizeof ( db ) , table , sizeof ( table ) ) ;
if ( eng & & eng - > update_func )
res = eng - > update_func ( db , table , keyfield , lookup , ap ) ;
va_end ( ap ) ;
return res ;
2004-06-11 00:12:35 +00:00
}
2004-06-17 04:53:55 +00:00
static int config_command ( int fd , int argc , char * * argv )
{
2005-01-25 06:10:20 +00:00
struct ast_config_engine * eng ;
2004-10-05 06:46:11 +00:00
struct ast_config_map * map ;
2004-06-11 00:12:35 +00:00
2005-01-25 06:10:20 +00:00
ast_mutex_lock ( & config_lock ) ;
ast_cli ( fd , " \n \n " ) ;
for ( eng = config_engine_list ; eng ; eng = eng - > next ) {
ast_cli ( fd , " \n Config Engine: %s \n " , eng - > name ) ;
for ( map = config_maps ; map ; map = map - > next )
if ( ! strcasecmp ( map - > driver , eng - > name ) ) {
ast_cli ( fd , " ===> %s (db=%s, table=%s) \n " , map - > name , map - > database ,
map - > table ? map - > table : map - > name ) ;
}
2004-06-11 00:12:35 +00:00
}
ast_cli ( fd , " \n \n " ) ;
2005-01-25 06:10:20 +00:00
ast_mutex_unlock ( & config_lock ) ;
2004-06-17 04:53:55 +00:00
return 0 ;
2004-06-11 00:12:35 +00:00
}
2005-03-17 00:35:06 +00:00
static char show_config_help [ ] =
2006-09-18 19:54:18 +00:00
" Usage: core list config mappings \n "
2005-03-17 00:35:06 +00:00
" Shows the filenames to config engines. \n " ;
2006-09-18 19:54:18 +00:00
static struct ast_cli_entry cli_config [ ] = {
{ { " core " , " list " , " config " , " mappings " , NULL } ,
config_command , " Display config mappings (file names to config engines) " ,
2006-09-21 21:17:39 +00:00
show_config_help } ,
2005-01-25 06:10:20 +00:00
} ;
2004-06-11 00:12:35 +00:00
2004-06-17 04:53:55 +00:00
int register_config_cli ( )
{
2006-09-18 19:54:18 +00:00
ast_cli_register_multiple ( cli_config , sizeof ( cli_config ) / sizeof ( struct ast_cli_entry ) ) ;
return 0 ;
2004-06-11 00:12:35 +00:00
}