Thu Oct 9 06:45:20 2008

Asterisk developer's documentation


config.h File Reference

Configuration File Parser. More...

#include <stdarg.h>

Include dependency graph for config.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_config_engine
struct  ast_variable

Typedefs

typedef ast_configconfig_load_func (const char *database, const char *table, const char *configfile, struct ast_config *config)
typedef ast_configrealtime_multi_get (const char *database, const char *table, va_list ap)
typedef int realtime_update (const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
typedef ast_variablerealtime_var_get (const char *database, const char *table, va_list ap)

Functions

void ast_category_append (struct ast_config *config, struct ast_category *cat)
char * ast_category_browse (struct ast_config *config, const char *prev)
 Goes through categories.
int ast_category_delete (struct ast_config *cfg, char *category)
void ast_category_destroy (struct ast_category *cat)
ast_variableast_category_detach_variables (struct ast_category *cat)
int ast_category_exist (const struct ast_config *config, const char *category_name)
 Check for category duplicates.
ast_categoryast_category_get (const struct ast_config *config, const char *category_name)
 Retrieve a category if it exists.
ast_categoryast_category_new (const char *name)
void ast_category_rename (struct ast_category *cat, const char *name)
int ast_check_realtime (const char *family)
 Check if realtime engine is configured for family returns 1 if family is configured in realtime and engine exists.
void ast_config_destroy (struct ast_config *config)
 Destroys a config.
int ast_config_engine_deregister (struct ast_config_engine *del)
 Deegister config engine.
int ast_config_engine_register (struct ast_config_engine *newconfig)
 Register config engine.
ast_categoryast_config_get_current_category (const struct ast_config *cfg)
ast_configast_config_internal_load (const char *configfile, struct ast_config *cfg)
ast_configast_config_load (const char *filename)
 Load a config file.
ast_configast_config_new (void)
void ast_config_set_current_category (struct ast_config *cfg, const struct ast_category *cat)
ast_variableast_load_realtime (const char *family,...)
 Retrieve realtime configuration.
ast_configast_load_realtime_multientry (const char *family,...)
 Retrieve realtime configuration.
int ast_update_realtime (const char *family, const char *keyfield, const char *lookup,...)
 Update realtime configuration.
void ast_variable_append (struct ast_category *category, struct ast_variable *variable)
ast_variableast_variable_browse (const struct ast_config *config, const char *category)
 Goes through variables Somewhat similar in intent as the ast_category_browse. List variables of config file category.
ast_variableast_variable_new (const char *name, const char *value)
char * ast_variable_retrieve (const struct ast_config *config, const char *category, const char *variable)
 Gets a variable.
void ast_variables_destroy (struct ast_variable *var)
 Free variable list.
int config_text_file_save (const char *filename, const struct ast_config *cfg, const char *generator)
void read_config_maps (void)
int register_config_cli (void)


Detailed Description

Configuration File Parser.

Definition in file config.h.


Typedef Documentation

typedef struct ast_config* config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config)

Definition at line 48 of file config.h.

typedef struct ast_config* realtime_multi_get(const char *database, const char *table, va_list ap)

Definition at line 50 of file config.h.

typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)

Definition at line 51 of file config.h.

typedef struct ast_variable* realtime_var_get(const char *database, const char *table, va_list ap)

Definition at line 49 of file config.h.


Function Documentation

void ast_category_append ( struct ast_config config,
struct ast_category cat 
)

Definition at line 242 of file config.c.

References config.

Referenced by config_odbc(), process_text_line(), realtime_directory(), and realtime_multi_odbc().

00243 {
00244    if (config->last)
00245       config->last->next = category;
00246    else
00247       config->root = category;
00248    config->last = category;
00249    config->current = category;
00250 }

char* ast_category_browse ( struct ast_config config,
const char *  prev 
)

Goes through categories.

Parameters:
config Which config structure you wish to "browse"
prev A pointer to a previous category. This funtion is kind of non-intuitive in it's use. To begin, one passes NULL as the second arguement. It will return a pointer to the string of the first category in the file. From here on after, one must then pass the previous usage's return value as the second pointer, and it will return a pointer to the category name afterwards.
Returns a category on success, or NULL on failure/no-more-categories

Definition at line 265 of file config.c.

References config, ast_category::name, ast_category::next, and next_available_category().

Referenced by authenticate(), complete_sipnotify(), config_load(), iax_provision_reload(), ind_load_module(), load_config(), load_module(), load_moh_classes(), load_odbc_config(), loadconfigurationfile(), misdn_cfg_init(), pbx_load_module(), realtime_directory(), realtime_switch_common(), reload_config(), reload_queues(), rpt_master(), and set_config().

00266 {  
00267    struct ast_category *cat = NULL;
00268 
00269    if (prev && config->last_browse && (config->last_browse->name == prev))
00270       cat = config->last_browse->next;
00271    else if (!prev && config->root)
00272          cat = config->root;
00273    else if (prev) {
00274       for (cat = config->root; cat; cat = cat->next) {
00275          if (cat->name == prev) {
00276             cat = cat->next;
00277             break;
00278          }
00279       }
00280       if (!cat) {
00281          for (cat = config->root; cat; cat = cat->next) {
00282             if (!strcasecmp(cat->name, prev)) {
00283                cat = cat->next;
00284                break;
00285             }
00286          }
00287       }
00288    }
00289    
00290    if (cat)
00291       cat = next_available_category(cat);
00292 
00293    config->last_browse = cat;
00294    if (cat)
00295       return cat->name;
00296    else
00297       return NULL;
00298 }

int ast_category_delete ( struct ast_config cfg,
char *  category 
)

void ast_category_destroy ( struct ast_category cat  ) 

Definition at line 252 of file config.c.

References ast_variables_destroy(), free, and ast_category::root.

Referenced by process_text_line(), and realtime_multi_odbc().

00253 {
00254    ast_variables_destroy(cat->root);
00255    free(cat);
00256 }

struct ast_variable* ast_category_detach_variables ( struct ast_category cat  ) 

Definition at line 300 of file config.c.

References ast_category::last, and ast_category::root.

Referenced by realtime_switch_common(), and vm_forwardoptions().

00301 {
00302    struct ast_variable *v;
00303 
00304    v = cat->root;
00305    cat->root = NULL;
00306    cat->last = NULL;
00307 
00308    return v;
00309 }

int ast_category_exist ( const struct ast_config config,
const char *  category_name 
)

Check for category duplicates.

Parameters:
config which config to use
category_name name of the category you're looking for This will search through the categories within a given config file for a match.
Return non-zero if found

Definition at line 237 of file config.c.

References ast_category_get(), and config.

00238 {
00239    return !!ast_category_get(config, category_name);
00240 }

struct ast_category* ast_category_get ( const struct ast_config config,
const char *  category_name 
)

Retrieve a category if it exists.

Parameters:
config which config to use
category_name name of the category you're looking for This will search through the categories within a given config file for a match.
Returns pointer to category if found, NULL if not.

Definition at line 232 of file config.c.

References category_get(), and config.

Referenced by ast_category_exist(), ast_variable_browse(), realtime_directory(), realtime_switch_common(), and vm_forwardoptions().

00233 {
00234    return category_get(config, category_name, 0);
00235 }

struct ast_category* ast_category_new ( const char *  name  ) 

Definition at line 202 of file config.c.

References malloc.

Referenced by config_odbc(), process_text_line(), realtime_directory(), and realtime_multi_odbc().

00203 {
00204    struct ast_category *category;
00205 
00206    category = malloc(sizeof(struct ast_category));
00207    if (category) {
00208       memset(category, 0, sizeof(struct ast_category));
00209       ast_copy_string(category->name, name, sizeof(category->name));
00210    }
00211 
00212    return category;
00213 }

void ast_category_rename ( struct ast_category cat,
const char *  name 
)

Definition at line 311 of file config.c.

References ast_category::name.

Referenced by realtime_multi_odbc().

00312 {
00313    ast_copy_string(cat->name, name, sizeof(cat->name));
00314 }

int ast_check_realtime ( const char *  family  ) 

Check if realtime engine is configured for family returns 1 if family is configured in realtime and engine exists.

Parameters:
family which family/config to be checked

Definition at line 1008 of file config.c.

References find_engine().

Referenced by sip_show_settings().

01009 {
01010    struct ast_config_engine *eng;
01011 
01012    eng = find_engine(family, NULL, 0, NULL, 0);
01013    if (eng)
01014       return 1;
01015    return 0;
01016 
01017 }

void ast_config_destroy ( struct ast_config config  ) 

Destroys a config.

Parameters:
config pointer to config data structure Free memory associated with a given config

Definition at line 342 of file config.c.

References ast_variables_destroy(), cfg, free, ast_category::next, ast_category::root, and ast_config::root.

Referenced by adsi_load(), advanced_options(), ast_config_load(), ast_enum_init(), ast_load_resource(), ast_readconfig(), ast_rtp_reload(), authenticate(), conf_exec(), config_load(), directory_exec(), do_reload(), festival_exec(), find_conf(), handle_save_dialplan(), iax_provision_reload(), ind_load_module(), init_logger_chain(), init_manager(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), loadconfigurationfile(), my_load_module(), odbc_load_module(), parse_config(), pbx_load_module(), play_message(), privacy_exec(), read_agent_config(), read_config_maps(), realtime_directory(), realtime_switch_common(), reload_config(), reload_queues(), rpt_master(), set_config(), setup_zap(), tds_load_module(), and vm_forwardoptions().

00343 {
00344    struct ast_category *cat, *catn;
00345 
00346    if (!cfg)
00347       return;
00348 
00349    cat = cfg->root;
00350    while(cat) {
00351       ast_variables_destroy(cat->root);
00352       catn = cat;
00353       cat = cat->next;
00354       free(catn);
00355    }
00356    free(cfg);
00357 }

int ast_config_engine_deregister ( struct ast_config_engine del  ) 

Deegister config engine.

Definition at line 873 of file config.c.

References ast_mutex_lock(), ast_mutex_unlock(), config_engine_list, last, and ast_config_engine::next.

Referenced by unload_module().

00874 {
00875    struct ast_config_engine *ptr, *last=NULL;
00876 
00877    ast_mutex_lock(&config_lock);
00878 
00879    for (ptr = config_engine_list; ptr; ptr=ptr->next) {
00880       if (ptr == del) {
00881          if (last)
00882             last->next = ptr->next;
00883          else
00884             config_engine_list = ptr->next;
00885          break;
00886       }
00887       last = ptr;
00888    }
00889 
00890    ast_mutex_unlock(&config_lock);
00891 
00892    return 0;
00893 }

int ast_config_engine_register ( struct ast_config_engine newconfig  ) 

Register config engine.

Definition at line 854 of file config.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), config_engine_list, LOG_NOTICE, ast_config_engine::name, and ast_config_engine::next.

Referenced by load_module().

00855 {
00856    struct ast_config_engine *ptr;
00857 
00858    ast_mutex_lock(&config_lock);
00859 
00860    if (!config_engine_list) {
00861       config_engine_list = new;
00862    } else {
00863       for (ptr = config_engine_list; ptr->next; ptr=ptr->next);
00864       ptr->next = new;
00865    }
00866 
00867    ast_mutex_unlock(&config_lock);
00868    ast_log(LOG_NOTICE,"Registered Config Engine %s\n", new->name);
00869 
00870    return 1;
00871 }

struct ast_category* ast_config_get_current_category ( const struct ast_config cfg  ) 

Definition at line 359 of file config.c.

References cfg, and ast_config::current.

Referenced by config_odbc(), and config_text_file_load().

00360 {
00361    return cfg->current;
00362 }

struct ast_config* ast_config_internal_load ( const char *  configfile,
struct ast_config cfg 
)

Definition at line 935 of file config.c.

References ast_log(), cfg, config_engine_list, db, extconfig_conf, find_engine(), ast_config::include_level, ast_config_engine::load_func, LOG_WARNING, ast_config::max_include_level, result, table, and text_file_engine.

Referenced by ast_config_load(), config_odbc(), process_text_line(), and read_config_maps().

00936 {
00937    char db[256];
00938    char table[256];
00939    struct ast_config_engine *loader = &text_file_engine;
00940    struct ast_config *result;
00941 
00942    if (cfg->include_level == cfg->max_include_level) {
00943       ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
00944       return NULL;
00945    }
00946 
00947    cfg->include_level++;
00948 
00949    if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
00950       struct ast_config_engine *eng;
00951 
00952       eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
00953 
00954 
00955       if (eng && eng->load_func) {
00956          loader = eng;
00957       } else {
00958          eng = find_engine("global", db, sizeof(db), table, sizeof(table));
00959          if (eng && eng->load_func)
00960             loader = eng;
00961       }
00962    }
00963 
00964    result = loader->load_func(db, table, filename, cfg);
00965 
00966    if (result)
00967       result->include_level--;
00968    else
00969       cfg->include_level--;
00970 
00971    return result;
00972 }

struct ast_config* ast_config_load ( const char *  filename  ) 

Load a config file.

Parameters:
filename path of file to open. If no preceding '/' character, path is considered relative to AST_CONFIG_DIR Create a config structure from a given configuration file.
Returns NULL on error, or an ast_config data structure on success

Definition at line 974 of file config.c.

References ast_config_destroy(), ast_config_internal_load(), ast_config_new(), cfg, and result.

Referenced by adsi_load(), advanced_options(), ast_enum_init(), ast_load_resource(), ast_readconfig(), ast_rtp_reload(), authenticate(), conf_exec(), config_load(), do_reload(), festival_exec(), find_conf(), handle_save_dialplan(), iax_provision_reload(), ind_load_module(), init_logger_chain(), init_manager(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), loadconfigurationfile(), my_load_module(), odbc_load_module(), parse_config(), pbx_load_module(), play_message(), privacy_exec(), read_agent_config(), realtime_directory(), reload_config(), reload_queues(), rpt_master(), set_config(), setup_zap(), tds_load_module(), and vm_forwardoptions().

00975 {
00976    struct ast_config *cfg;
00977    struct ast_config *result;
00978 
00979    cfg = ast_config_new();
00980    if (!cfg)
00981       return NULL;
00982 
00983    result = ast_config_internal_load(filename, cfg);
00984    if (!result)
00985       ast_config_destroy(cfg);
00986 
00987    return result;
00988 }

struct ast_config* ast_config_new ( void   ) 

Definition at line 329 of file config.c.

References config, malloc, and MAX_INCLUDE_LEVEL.

Referenced by ast_config_load(), read_config_maps(), and realtime_multi_odbc().

00330 {
00331    struct ast_config *config;
00332 
00333    config = malloc(sizeof(*config));
00334    if (config) {
00335       memset(config, 0, sizeof(*config));
00336       config->max_include_level = MAX_INCLUDE_LEVEL;
00337    }
00338 
00339    return config;
00340 }

void ast_config_set_current_category ( struct ast_config cfg,
const struct ast_category cat 
)

Definition at line 364 of file config.c.

References cfg, and ast_config::current.

00365 {
00366    /* cast below is just to silence compiler warning about dropping "const" */
00367    cfg->current = (struct ast_category *) cat;
00368 }

struct ast_variable* ast_load_realtime ( const char *  family,
  ... 
)

Retrieve realtime configuration.

Parameters:
family which family/config to lookup This will use builtin configuration backends to look up a particular entity in realtime and return a variable list of its parameters. Note that unlike the variables in ast_config, the resulting list of variables MUST be fred with ast_free_runtime() as there is no container.

Definition at line 990 of file config.c.

References db, find_engine(), ast_config_engine::realtime_func, and table.

Referenced by cli_load_realtime(), find_user_realtime(), realtime_exec(), realtime_peer(), realtime_switch_common(), and realtime_user().

00991 {
00992    struct ast_config_engine *eng;
00993    char db[256]="";
00994    char table[256]="";
00995    struct ast_variable *res=NULL;
00996    va_list ap;
00997 
00998    va_start(ap, family);
00999    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
01000    if (eng && eng->realtime_func) 
01001       res = eng->realtime_func(db, table, ap);
01002    va_end(ap);
01003 
01004    return res;
01005 }

struct ast_config* ast_load_realtime_multientry ( const char *  family,
  ... 
)

Retrieve realtime configuration.

Parameters:
family which family/config to lookup This will use builtin configuration backends to look up a particular entity in realtime and return a variable list of its parameters. Unlike the ast_load_realtime, this function can return more than one entry and is thus stored inside a taditional ast_config structure rather than just returning a linked list of variables.

Definition at line 1019 of file config.c.

References db, find_engine(), ast_config_engine::realtime_multi_func, and table.

Referenced by realtime_directory(), and realtime_switch_common().

01020 {
01021    struct ast_config_engine *eng;
01022    char db[256]="";
01023    char table[256]="";
01024    struct ast_config *res=NULL;
01025    va_list ap;
01026 
01027    va_start(ap, family);
01028    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
01029    if (eng && eng->realtime_multi_func) 
01030       res = eng->realtime_multi_func(db, table, ap);
01031    va_end(ap);
01032 
01033    return res;
01034 }

int ast_update_realtime ( const char *  family,
const char *  keyfield,
const char *  lookup,
  ... 
)

Update realtime configuration.

Parameters:
family which family/config to be updated
keyfield which field to use as the key
lookup which value to look for in the key field to match the entry. This function is used to update a parameter in realtime configuration space.

Definition at line 1036 of file config.c.

References db, find_engine(), table, and ast_config_engine::update_func.

Referenced by change_password_realtime(), cli_update_realtime(), destroy_association(), realtime_update_exec(), and realtime_update_peer().

01037 {
01038    struct ast_config_engine *eng;
01039    int res = -1;
01040    char db[256]="";
01041    char table[256]="";
01042    va_list ap;
01043 
01044    va_start(ap, lookup);
01045    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
01046    if (eng && eng->update_func) 
01047       res = eng->update_func(db, table, keyfield, lookup, ap);
01048    va_end(ap);
01049 
01050    return res;
01051 }

void ast_variable_append ( struct ast_category category,
struct ast_variable variable 
)

Definition at line 116 of file config.c.

References ast_category::last, ast_variable::next, and ast_category::root.

Referenced by config_odbc(), inherit_category(), move_variables(), process_text_line(), realtime_directory(), realtime_multi_odbc(), and vm_forwardoptions().

00117 {
00118    if (category->last)
00119       category->last->next = variable;
00120    else
00121       category->root = variable;
00122    category->last = variable;
00123    while (category->last->next)
00124       category->last = category->last->next;
00125 }

struct ast_variable* ast_variable_browse ( const struct ast_config config,
const char *  category 
)

Goes through variables Somewhat similar in intent as the ast_category_browse. List variables of config file category.

Returns ast_variable list on success, or NULL on failure

Definition at line 138 of file config.c.

References ast_category_get(), config, and ast_category::root.

Referenced by adsi_load(), ast_enum_init(), ast_readconfig(), ast_variable_retrieve(), authenticate(), collect_function_digits(), conf_exec(), do_directory(), find_conf(), handle_save_dialplan(), iax_template_parse(), ind_load_module(), init_logger_chain(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), loadconfigurationfile(), misdn_cfg_init(), odbc_load_module(), osp_build(), parse_config(), pbx_load_module(), process_my_load_module(), read_agent_config(), read_config_maps(), reload_config(), reload_queues(), rpt_master(), set_config(), setup_zap(), sip_notify(), store_config(), and tds_load_module().

00139 {
00140    struct ast_category *cat = NULL;
00141 
00142    if (category && config->last_browse && (config->last_browse->name == category))
00143       cat = config->last_browse;
00144    else
00145       cat = ast_category_get(config, category);
00146 
00147    if (cat)
00148       return cat->root;
00149    else
00150       return NULL;
00151 }

struct ast_variable* ast_variable_new ( const char *  name,
const char *  value 
)

Definition at line 99 of file config.c.

References malloc.

Referenced by apply_outgoing(), astman_get_variables(), build_peer(), build_user(), check_access(), check_user_full(), config_odbc(), launch_page(), process_text_line(), realtime_directory(), realtime_multi_odbc(), realtime_odbc(), variable_clone(), and vm_forwardoptions().

00100 {
00101    struct ast_variable *variable;
00102 
00103    int length = strlen(name) + strlen(value) + 2 + sizeof(struct ast_variable);
00104    variable = malloc(length);
00105    if (variable) {
00106       memset(variable, 0, length);
00107       variable->name = variable->stuff;
00108       variable->value = variable->stuff + strlen(name) + 1;    
00109       strcpy(variable->name,name);
00110       strcpy(variable->value,value);
00111    }
00112 
00113    return variable;
00114 }

char* ast_variable_retrieve ( const struct ast_config config,
const char *  category,
const char *  variable 
)

Gets a variable.

Parameters:
config which (opened) config to use
category category under which the variable lies
variable which variable you wish to get the data for Goes through a given config file in the given category and searches for the given variable
Returns the variable value on success, or NULL if unable to find it.

Definition at line 153 of file config.c.

References ast_variable_browse(), config, ast_variable::name, ast_category::next, ast_variable::next, ast_category::root, and ast_variable::value.

Referenced by __load_resource(), advanced_options(), ast_rtp_reload(), attempt_reconnect(), authenticate(), config_load(), directory_exec(), do_reload(), festival_exec(), function_ilink(), function_remote(), get_wait_interval(), iax_template_parse(), ind_load_module(), init_logger_chain(), init_manager(), load_config(), load_module(), odbc_load_module(), pbx_load_module(), play_message(), privacy_exec(), process_my_load_module(), read_agent_config(), realtime_directory(), reload_config(), reload_queues(), retrieve_astcfgint(), rpt(), rpt_exec(), rpt_master(), rpt_tele_thread(), set_config(), tds_load_module(), telem_lookup(), and vm_forwardoptions().

00154 {
00155    struct ast_variable *v;
00156 
00157    if (category) {
00158       for (v = ast_variable_browse(config, category); v; v = v->next) {
00159          if (!strcasecmp(variable, v->name))
00160             return v->value;
00161       }
00162    } else {
00163       struct ast_category *cat;
00164 
00165       for (cat = config->root; cat; cat = cat->next)
00166          for (v = cat->root; v; v = v->next)
00167             if (!strcasecmp(variable, v->name))
00168                return v->value;
00169    }
00170 
00171    return NULL;
00172 }

void ast_variables_destroy ( struct ast_variable var  ) 

Free variable list.

Parameters:
var the linked list of variables to free This function frees a list of variables.

Definition at line 127 of file config.c.

References free, and ast_variable::next.

Referenced by __sip_destroy(), ast_category_destroy(), ast_config_destroy(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), build_peer(), destroy_user(), find_user_realtime(), pvt_destructor(), realtime_canmatch(), realtime_exec(), realtime_exists(), realtime_matchmore(), realtime_odbc(), realtime_peer(), realtime_user(), sip_alloc(), sip_destroy_peer(), and sip_destroy_user().

00128 {
00129    struct ast_variable *vn;
00130 
00131    while(v) {
00132       vn = v;
00133       v = v->next;
00134       free(vn);
00135    }
00136 }

int config_text_file_save ( const char *  filename,
const struct ast_config cfg,
const char *  generator 
)

Definition at line 680 of file config.c.

References ast_config_AST_CONFIG_DIR, ast_log(), ast_verbose(), cfg, LOG_DEBUG, ast_category::name, ast_category::next, option_debug, option_verbose, ast_category::root, ast_config::root, t, var, and VERBOSE_PREFIX_2.

Referenced by vm_forwardoptions().

00681 {
00682    FILE *f;
00683    char fn[256];
00684    char date[256]="";
00685    time_t t;
00686    struct ast_variable *var;
00687    struct ast_category *cat;
00688    int blanklines = 0;
00689 
00690    if (configfile[0] == '/') {
00691       ast_copy_string(fn, configfile, sizeof(fn));
00692    } else {
00693       snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
00694    }
00695    time(&t);
00696    ast_copy_string(date, ctime(&t), sizeof(date));
00697 #ifdef __CYGWIN__ 
00698    if ((f = fopen(fn, "w+"))) {
00699 #else
00700    if ((f = fopen(fn, "w"))) {
00701 #endif       
00702       if (option_verbose > 1)
00703          ast_verbose(VERBOSE_PREFIX_2 "Saving '%s': ", fn);
00704       fprintf(f, ";!\n");
00705       fprintf(f, ";! Automatically generated configuration file\n");
00706       if (strcmp(configfile, fn))
00707          fprintf(f, ";! Filename: %s (%s)\n", configfile, fn);
00708       else
00709          fprintf(f, ";! Filename: %s\n", configfile);
00710       fprintf(f, ";! Generator: %s\n", generator);
00711       fprintf(f, ";! Creation Date: %s", date);
00712       fprintf(f, ";!\n");
00713       cat = cfg->root;
00714       while(cat) {
00715          /* Dump section with any appropriate comment */
00716          fprintf(f, "[%s]\n", cat->name);
00717          var = cat->root;
00718          while(