diff options
75 files changed, 871 insertions, 551 deletions
diff --git a/apps/app_alarmreceiver.c b/apps/app_alarmreceiver.c index b48c8dba3..194a33237 100644 --- a/apps/app_alarmreceiver.c +++ b/apps/app_alarmreceiver.c @@ -714,10 +714,11 @@ static int load_config(void) { struct ast_config *cfg; const char *p; + struct ast_flags config_flags = { 0 }; /* Read in the config file */ - cfg = ast_config_load(ALMRCV_CONFIG); + cfg = ast_config_load(ALMRCV_CONFIG, config_flags); if(!cfg){ diff --git a/apps/app_amd.c b/apps/app_amd.c index 2d88dd861..dea61fffe 100644 --- a/apps/app_amd.c +++ b/apps/app_amd.c @@ -317,16 +317,18 @@ static int amd_exec(struct ast_channel *chan, void *data) return 0; } -static void load_config(void) +static void load_config(int reload) { struct ast_config *cfg = NULL; char *cat = NULL; struct ast_variable *var = NULL; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - if (!(cfg = ast_config_load("amd.conf"))) { + if (!(cfg = ast_config_load("amd.conf", config_flags))) { ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n"); return; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return; cat = ast_category_browse(cfg, NULL); @@ -377,13 +379,13 @@ static int unload_module(void) static int load_module(void) { - load_config(); + load_config(0); return ast_register_application(app, amd_exec, synopsis, descrip); } static int reload(void) { - load_config(); + load_config(1); return 0; } diff --git a/apps/app_directory.c b/apps/app_directory.c index 4564014ef..896f9cbe1 100644 --- a/apps/app_directory.c +++ b/apps/app_directory.c @@ -364,9 +364,10 @@ static struct ast_config *realtime_directory(char *context) const char *fullname; const char *hidefromdir; char tmp[100]; + struct ast_flags config_flags = { 0 }; /* Load flat file config. */ - cfg = ast_config_load(VOICEMAIL_CONFIG); + cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); if (!cfg) { /* Loading config failed. */ @@ -597,6 +598,7 @@ static int directory_exec(struct ast_channel *chan, void *data) int fromappvm = 0; const char *dirintro; char *parse; + struct ast_flags config_flags = { 0 }; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(vmcontext); AST_APP_ARG(dialcontext); @@ -630,7 +632,7 @@ static int directory_exec(struct ast_channel *chan, void *data) return -1; } - ucfg = ast_config_load("users.conf"); + ucfg = ast_config_load("users.conf", config_flags); dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro"); if (ast_strlen_zero(dirintro)) @@ -674,7 +676,8 @@ static int unload_module(void) static int load_module(void) { #ifdef ODBC_STORAGE - struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG); + struct ast_flags config_flags = { 0 }; + struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); const char *tmp; if (cfg) { diff --git a/apps/app_festival.c b/apps/app_festival.c index 60950ad75..b6097be87 100644 --- a/apps/app_festival.c +++ b/apps/app_festival.c @@ -306,6 +306,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata) char *data; struct ast_config *cfg; char *newfestivalcommand; + struct ast_flags config_flags = { 0 }; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(text); AST_APP_ARG(interrupt); @@ -316,7 +317,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata) return -1; } - cfg = ast_config_load(FESTIVAL_CONFIG); + cfg = ast_config_load(FESTIVAL_CONFIG, config_flags); if (!cfg) { ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG); return -1; @@ -520,7 +521,8 @@ static int unload_module(void) static int load_module(void) { - struct ast_config *cfg = ast_config_load(FESTIVAL_CONFIG); + struct ast_flags config_flags = { 0 }; + struct ast_config *cfg = ast_config_load(FESTIVAL_CONFIG, config_flags); if (!cfg) { ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG); return AST_MODULE_LOAD_DECLINE; diff --git a/apps/app_followme.c b/apps/app_followme.c index f81472e6d..1a697e526 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -275,7 +275,7 @@ static struct number *create_followme_number(char *number, int timeout, int numo } /*! \brief Reload followme application module */ -static int reload_followme(void) +static int reload_followme(int reload) { struct call_followme *f; struct ast_config *cfg; @@ -289,11 +289,13 @@ static int reload_followme(void) const char *takecallstr; const char *declinecallstr; const char *tmpstr; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - if (!(cfg = ast_config_load("followme.conf"))) { + if (!(cfg = ast_config_load("followme.conf", config_flags))) { ast_log(LOG_WARNING, "No follow me config file (followme.conf), so no follow me\n"); return 0; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; AST_RWLIST_WRLOCK(&followmes); @@ -1051,7 +1053,7 @@ static int unload_module(void) static int load_module(void) { - if(!reload_followme()) + if(!reload_followme(0)) return AST_MODULE_LOAD_DECLINE; return ast_register_application(app, app_exec, synopsis, descrip); @@ -1059,7 +1061,7 @@ static int load_module(void) static int reload(void) { - reload_followme(); + reload_followme(1); return 0; } diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 5a0745311..e4f487ae6 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -2407,6 +2407,7 @@ static struct ast_conference *find_conf(struct ast_channel *chan, char *confno, { struct ast_config *cfg; struct ast_variable *var; + struct ast_flags config_flags = { 0 }; struct ast_conference *cnf; char *parse; AST_DECLARE_APP_ARGS(args, @@ -2444,7 +2445,7 @@ static struct ast_conference *find_conf(struct ast_channel *chan, char *confno, } } else { /* Check the config */ - cfg = ast_config_load(CONFIG_FILE_NAME); + cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); if (!cfg) { ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); return NULL; @@ -2551,7 +2552,7 @@ static int conf_exec(struct ast_channel *chan, void *data) int allowretry = 0; int retrycnt = 0; struct ast_conference *cnf = NULL; - struct ast_flags confflags = {0}; + struct ast_flags confflags = {0}, config_flags = { 0 }; int dynamic = 0; int empty = 0, empty_no_pin = 0; int always_prompt = 0; @@ -2609,7 +2610,7 @@ static int conf_exec(struct ast_channel *chan, void *data) /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ if ((empty_no_pin) || (!dynamic)) { - cfg = ast_config_load(CONFIG_FILE_NAME); + cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); if (cfg) { var = ast_variable_browse(cfg, "rooms"); while (var) { @@ -3174,11 +3175,12 @@ static enum ast_device_state meetmestate(const char *data) static void load_config_meetme(void) { struct ast_config *cfg; + struct ast_flags config_flags = { 0 }; const char *val; audio_buffers = DEFAULT_AUDIO_BUFFERS; - if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) + if (!(cfg = ast_config_load(CONFIG_FILE_NAME, config_flags))) return; if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { @@ -4894,6 +4896,7 @@ static int sla_build_station(struct ast_config *cfg, const char *cat) static int sla_load_config(int reload) { struct ast_config *cfg; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; const char *cat = NULL; int res = 0; const char *val; @@ -4903,8 +4906,10 @@ static int sla_load_config(int reload) ast_cond_init(&sla.cond, NULL); } - if (!(cfg = ast_config_load(SLA_CONFIG_FILE))) + if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) return 0; /* Treat no config as normal */ + else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) sla.attempt_callerid = ast_true(val); diff --git a/apps/app_minivm.c b/apps/app_minivm.c index a868bac83..1841e5267 100644 --- a/apps/app_minivm.c +++ b/apps/app_minivm.c @@ -2349,7 +2349,7 @@ static int apply_general_options(struct ast_variable *var) } /*! \brief Load minivoicemail configuration */ -static int load_config(void) +static int load_config(int reload) { struct ast_config *cfg; struct ast_variable *var; @@ -2357,8 +2357,12 @@ static int load_config(void) const char *chanvar; int error = 0; struct minivm_template *template; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); + if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; - cfg = ast_config_load(VOICEMAIL_CONFIG); ast_mutex_lock(&minivmlock); /* Destroy lists to reconfigure */ @@ -3039,7 +3043,7 @@ static int load_module(void) if (res) return(res); - if ((res = load_config())) + if ((res = load_config(0))) return(res); ast_cli_register_multiple(cli_minivm, sizeof(cli_minivm)/sizeof(cli_minivm[0])); @@ -3053,7 +3057,7 @@ static int load_module(void) /*! \brief Reload mini voicemail module */ static int reload(void) { - return(load_config()); + return(load_config(1)); } /*! \brief Reload cofiguration */ diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c index 3e7f9b2b3..25b3fb518 100644 --- a/apps/app_osplookup.c +++ b/apps/app_osplookup.c @@ -1773,15 +1773,22 @@ static int ospfinished_exec( /* OSP Module APIs */ -static int osp_load(void) +static int osp_unload(void); +static int osp_load(int reload) { const char* t; unsigned int v; struct ast_config* cfg; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; int error = OSPC_ERR_NO_ERROR; - cfg = ast_config_load(OSP_CONFIG_FILE); + if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; + if (cfg) { + if (reload) + osp_unload(); + t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate"); if (t && ast_true(t)) { if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) { @@ -2000,7 +2007,7 @@ static int load_module(void) { int res; - if(!osp_load()) + if (!osp_load(0)) return AST_MODULE_LOAD_DECLINE; ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry)); @@ -2028,8 +2035,7 @@ static int unload_module(void) static int reload(void) { - osp_unload(); - osp_load(); + osp_load(1); return 0; } diff --git a/apps/app_playback.c b/apps/app_playback.c index d39d25c0a..db9e0e1f8 100644 --- a/apps/app_playback.c +++ b/apps/app_playback.c @@ -470,12 +470,17 @@ done: static int reload(void) { struct ast_variable *v; + struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; + struct ast_config *newcfg; + + if ((newcfg = ast_config_load("say.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; if (say_cfg) { ast_config_destroy(say_cfg); ast_log(LOG_NOTICE, "Reloading say.conf\n"); + say_cfg = newcfg; } - say_cfg = ast_config_load("say.conf"); if (say_cfg) { for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) { @@ -510,8 +515,9 @@ static int unload_module(void) static int load_module(void) { struct ast_variable *v; + struct ast_flags config_flags = { 0 }; - say_cfg = ast_config_load("say.conf"); + say_cfg = ast_config_load("say.conf", config_flags); if (say_cfg) { for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) { if (ast_extension_match(v->name, "mode")) { diff --git a/apps/app_privacy.c b/apps/app_privacy.c index cf3d6371f..e470b9ed0 100644 --- a/apps/app_privacy.c +++ b/apps/app_privacy.c @@ -83,6 +83,7 @@ static int privacy_exec (struct ast_channel *chan, void *data) char phone[30]; struct ast_config *cfg = NULL; char *parse = NULL; + struct ast_flags config_flags = { 0 }; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(maxretries); AST_APP_ARG(minlength); @@ -122,7 +123,7 @@ static int privacy_exec (struct ast_channel *chan, void *data) if (!x) { /*Read in the config file*/ - cfg = ast_config_load(PRIV_CONFIG); + cfg = ast_config_load(PRIV_CONFIG, config_flags); if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) { if (sscanf(s, "%d", &x) == 1) diff --git a/apps/app_queue.c b/apps/app_queue.c index d571dc354..1908454da 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3947,7 +3947,7 @@ static struct ast_custom_function queuememberlist_function = { .read = queue_function_queuememberlist, }; -static int reload_queues(void) +static int reload_queues(int reload) { struct call_queue *q; struct ast_config *cfg; @@ -3960,16 +3960,18 @@ static int reload_queues(void) char *interface; char *membername; int penalty; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(interface); AST_APP_ARG(penalty); AST_APP_ARG(membername); ); - if (!(cfg = ast_config_load("queues.conf"))) { + if (!(cfg = ast_config_load("queues.conf", config_flags))) { ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n"); return 0; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; AST_LIST_LOCK(&queues); use_weight=0; /* Mark all queues as dead for the moment */ @@ -4766,7 +4768,7 @@ static int load_module(void) int res; struct ast_context *con; - if (!reload_queues()) + if (!reload_queues(0)) return AST_MODULE_LOAD_DECLINE; con = ast_context_find("app_queue_gosub_virtual_context"); @@ -4810,7 +4812,7 @@ static int load_module(void) static int reload(void) { - reload_queues(); + reload_queues(1); return 0; } diff --git a/apps/app_rpt.c b/apps/app_rpt.c index ad38de179..77e4ee4ef 100644 --- a/apps/app_rpt.c +++ b/apps/app_rpt.c @@ -918,6 +918,7 @@ static void load_rpt_vars(int n, int init) int j; struct ast_variable *vp, *var; struct ast_config *cfg; + struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; #ifdef __RPT_NOTCH AST_DECLARE_APP_ARGS(strs, AST_APP_ARG(str)[100]; @@ -929,7 +930,7 @@ static void load_rpt_vars(int n, int init) ast_mutex_lock(&rpt_vars[n].lock); if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg); - cfg = ast_config_load("rpt.conf"); + cfg = ast_config_load("rpt.conf", config_flags); if (!cfg) { ast_mutex_unlock(&rpt_vars[n].lock); ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n"); @@ -7437,7 +7438,8 @@ static int unload_module(void) static int load_module(void) { - struct ast_config *cfg = ast_config_load("rpt.conf"); + struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; + struct ast_config *cfg = ast_config_load("rpt.conf", config_flags); if (!cfg) { ast_log(LOG_WARNING, "No such configuration file rpt.conf\n"); return AST_MODULE_LOAD_DECLINE; diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index c2e8afdac..752d2a8be 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -260,7 +260,7 @@ AST_APP_OPTIONS(vm_app_options, { AST_APP_OPTION_ARG('a', OPT_AUTOPLAY, OPT_ARG_PLAYFOLDER), }); -static int load_config(void); +static int load_config(int reload); /*! \page vmlang Voicemail Language Syntaxes Supported @@ -911,12 +911,13 @@ static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword) struct ast_category *cat=NULL; char *category=NULL, *value=NULL, *new=NULL; const char *tmp=NULL; + struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS }; if (!change_password_realtime(vmu, newpassword)) return; /* check voicemail.conf */ - if ((cfg = ast_config_load_with_comments(VOICEMAIL_CONFIG))) { + if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags))) { while ((category = ast_category_browse(cfg, category))) { if (!strcasecmp(category, vmu->context)) { if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) { @@ -946,7 +947,7 @@ static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword) var = NULL; /* check users.conf and update the password stored for the mailbox*/ /* if no vmsecret entry exists create one. */ - if ((cfg = ast_config_load_with_comments("users.conf"))) { + if ((cfg = ast_config_load("users.conf", config_flags))) { ast_debug(4, "we are looking for %s\n", vmu->mailbox); while ((category = ast_category_browse(cfg, category))) { ast_debug(4, "users.conf: %s\n", category); @@ -1427,6 +1428,7 @@ static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int ms const char *category = ""; struct ast_config *cfg=NULL; struct odbc_obj *obj; + struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; delete_file(dir, msgnum); obj = ast_odbc_request_obj(odbc_database, 0); @@ -1443,7 +1445,7 @@ static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int ms else ast_copy_string(fn, dir, sizeof(fn)); snprintf(full_fn, sizeof(full_fn), "%s.txt", fn); - cfg = ast_config_load(full_fn); + cfg = ast_config_load(full_fn, config_flags); snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt); fd = open(full_fn, O_RDWR); if (fd < 0) { @@ -3975,6 +3977,7 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, int cmd = 0; int retries = 0; signed char zero_gain = 0; + struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) { if (cmd) @@ -3995,7 +3998,7 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, *duration = 0; /* if we can't read the message metadata, stop now */ - if (!(msg_cfg = ast_config_load(textfile))) { + if (!(msg_cfg = ast_config_load(textfile, config_flags))) { cmd = 0; break; } @@ -4733,6 +4736,7 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc char filename[256], *cid; const char *origtime, *context, *category, *duration; struct ast_config *msg_cfg; + struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; vms->starting = 0; make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg); @@ -4782,7 +4786,7 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg); snprintf(filename, sizeof(filename), "%s.txt", vms->fn2); RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); - msg_cfg = ast_config_load(filename); + msg_cfg = ast_config_load(filename, config_flags); if (!msg_cfg) { ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename); return 0; @@ -7850,7 +7854,7 @@ static int manager_list_voicemail_users(struct mansession *s, const struct messa return RESULT_SUCCESS; } -static int load_config(void) +static int load_config(int reload) { struct ast_vm_user *cur; struct vm_zone *zcur; @@ -7863,6 +7867,17 @@ static int load_config(void) char *q, *stringp; int x; int tmpadsi[4]; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { + if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); + } else { + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + ucfg = ast_config_load("users.conf", config_flags); + } /* set audio control prompts */ strcpy(listen_control_forward_key,DEFAULT_LISTEN_CONTROL_FORWARD_KEY); @@ -7871,8 +7886,6 @@ static int load_config(void) strcpy(listen_control_restart_key,DEFAULT_LISTEN_CONTROL_RESTART_KEY); strcpy(listen_control_stop_key,DEFAULT_LISTEN_CONTROL_STOP_KEY); - cfg = ast_config_load(VOICEMAIL_CONFIG); - AST_LIST_LOCK(&users); while ((cur = AST_LIST_REMOVE_HEAD(&users, list))) { ast_set_flag(cur, VM_ALLOCED); @@ -8259,7 +8272,7 @@ static int load_config(void) if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes"))) poll_mailboxes = ast_true(val); - if ((ucfg = ast_config_load("users.conf"))) { + if (ucfg) { for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail"))) continue; @@ -8427,13 +8440,15 @@ static int load_config(void) } else { AST_LIST_UNLOCK(&users); ast_log(LOG_WARNING, "Failed to load configuration file.\n"); + if (ucfg) + ast_config_destroy(ucfg); return 0; } } static int reload(void) { - return load_config(); + return load_config(1); } static int unload_module(void) @@ -8464,7 +8479,7 @@ static int load_module(void) /* compute the location of the voicemail spool directory */ snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR); - if ((res = load_config())) + if ((res = load_config(0))) return res; res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm); @@ -8555,6 +8570,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s const char *origtime, *context; char *cid, *name, *num; int retries = 0; + struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; vms->starting = 0; #ifdef IMAP_STORAGE @@ -8605,7 +8621,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg); snprintf(filename,sizeof(filename), "%s.txt", vms->fn2); RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); - msg_cfg = ast_config_load(filename); + msg_cfg = ast_config_load(filename, config_flags); DISPOSE(vms->curdir, vms->curmsg); if (!msg_cfg) { ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename); diff --git a/cdr/cdr_adaptive_odbc.c b/cdr/cdr_adaptive_odbc.c index f97f5ed4f..66f704d68 100644 --- a/cdr/cdr_adaptive_odbc.c +++ b/cdr/cdr_adaptive_odbc.c @@ -95,8 +95,9 @@ static int load_config(void) SQLLEN sqlptr; int res = 0; SQLHSTMT stmt = NULL; + struct ast_flags config_flags = { 0 }; /* Part of our config comes from the database */ - cfg = ast_config_load(CONFIG); + cfg = ast_config_load(CONFIG, config_flags); if (!cfg) { ast_log(LOG_WARNING, "Unable to load " CONFIG ". No adaptive ODBC CDRs.\n"); return -1; diff --git a/cdr/cdr_csv.c b/cdr/cdr_csv.c index bfc509803..8ae8b3c99 100644 --- a/cdr/cdr_csv.c +++ b/cdr/cdr_csv.c @@ -95,22 +95,24 @@ static char *name = "csv"; static FILE *mf = NULL; -static int load_config(void) +static int load_config(int reload) { struct ast_config *cfg; struct ast_variable *var; const char *tmp; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; usegmtime = 0; loguniqueid = 0; loguserfield = 0; - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); if (!cfg) { ast_log(LOG_WARNING, "unable to load config: %s\n", config); return 0; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; var = ast_variable_browse(cfg, "csv"); if (!var) { @@ -316,7 +318,7 @@ static int load_module(void) { int res; - if(!load_config()) + if(!load_config(0)) return AST_MODULE_LOAD_DECLINE; res = ast_cdr_register(name, ast_module_info->description, csv_log); @@ -330,7 +332,7 @@ static int load_module(void) static int reload(void) { - load_config(); + load_config(1); return 0; } diff --git a/cdr/cdr_custom.c b/cdr/cdr_custom.c index 80cd47ecf..fa4eb11c4 100644 --- a/cdr/cdr_custom.c +++ b/cdr/cdr_custom.c @@ -68,12 +68,16 @@ static int load_config(int reload) { struct ast_config *cfg; struct ast_variable *var; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; int res = -1; + if ((cfg = ast_config_load("cdr_custom.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; + strcpy(format, ""); strcpy(master, ""); ast_mutex_lock(&lock); - if((cfg = ast_config_load("cdr_custom.conf"))) { + if (cfg) { var = ast_variable_browse(cfg, "mappings"); while(var) { if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) { diff --git a/cdr/cdr_manager.c b/cdr/cdr_manager.c index 5dc4da6fe..028b4a8c9 100644 --- a/cdr/cdr_manager.c +++ b/cdr/cdr_manager.c @@ -52,15 +52,22 @@ static char *name = "cdr_manager"; static int enablecdr = 0; struct ast_str *customfields; -static int load_config(void) +static int load_config(int reload) { char *cat = NULL; struct ast_config *cfg; struct ast_variable *v; - + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + cfg = ast_config_load(CONF_FILE, config_flags); + if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + + if (reload && customfields) { + ast_free(customfields); + } customfields = NULL; - cfg = ast_config_load(CONF_FILE); if (!cfg) { /* Standard configuration */ ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n"); @@ -174,7 +181,7 @@ static int load_module(void) int res; /* Configuration file */ - if (!load_config()) + if (!load_config(0)) return AST_MODULE_LOAD_DECLINE; res = ast_cdr_register(name, "Asterisk Manager Interface CDR Backend", manager_log); @@ -187,12 +194,7 @@ static int load_module(void) static int reload(void) { - if (customfields) { - ast_free(customfields); - } - - load_config(); - return 0; + return load_config(1); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk Manager Interface CDR Backend", diff --git a/cdr/cdr_odbc.c b/cdr/cdr_odbc.c index 1ba24f50a..19acbe389 100644 --- a/cdr/cdr_odbc.c +++ b/cdr/cdr_odbc.c @@ -226,124 +226,124 @@ static int odbc_unload_module(void) return 0; } -static int odbc_load_module(void) +static int odbc_load_module(int reload) { int res = 0; struct ast_config *cfg; struct ast_variable *var; const char *tmp; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; ast_mutex_lock(&odbc_lock); - cfg = ast_config_load(config); - if (!cfg) { - ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config); - res = AST_MODULE_LOAD_DECLINE; - goto out; - } + do { + cfg = ast_config_load(config, config_flags); + if (!cfg) { + ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config); + res = AST_MODULE_LOAD_DECLINE; + break; + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + break; - var = ast_variable_browse(cfg, "global"); - if (!var) { - /* nothing configured */ - goto out; - } - - tmp = ast_variable_retrieve(cfg,"global","dsn"); - if (tmp == NULL) { - ast_log(LOG_WARNING,"cdr_odbc: dsn not specified. Assuming asteriskdb\n"); - tmp = "asteriskdb"; - } - dsn = strdup(tmp); - if (dsn == NULL) { - ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n"); - res = -1; - goto out; - } + var = ast_variable_browse(cfg, "global"); + if (!var) { + /* nothing configured */ + break; + } - tmp = ast_variable_retrieve(cfg,"global","dispositionstring"); - if (tmp) { - dispositionstring = ast_true(tmp); - } else { - dispositionstring = 0; - } - - tmp = ast_variable_retrieve(cfg,"global","username"); - if (tmp) { - username = strdup(tmp); - if (username == NULL) { - ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n"); + if ((tmp = ast_variable_retrieve(cfg, "global", "dsn")) == NULL) { + ast_log(LOG_WARNING, "cdr_odbc: dsn not specified. Assuming asteriskdb\n"); + tmp = "asteriskdb"; + } + if (dsn) + ast_free(dsn); + dsn = ast_strdup(tmp); + if (dsn == NULL) { res = -1; - goto out; + break; } - } - tmp = ast_variable_retrieve(cfg,"global","password"); - if (tmp) { - password = strdup(tmp); - if (password == NULL) { - ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n"); - res = -1; - goto out; + if ((tmp = ast_variable_retrieve(cfg, "global", "dispositionstring"))) + dispositionstring = ast_true(tmp); + else + dispositionstring = 0; + + if ((tmp = ast_variable_retrieve(cfg, "global", "username"))) { + if (username) + ast_free(username); + username = ast_strdup(tmp); + if (username == NULL) { + res = -1; + break; + } } - } - tmp = ast_variable_retrieve(cfg,"global","loguniqueid"); - if (tmp) { - loguniqueid = ast_true(tmp); - if (loguniqueid) { - ast_debug(1,"cdr_odbc: Logging uniqueid\n"); + if ((tmp = ast_variable_retrieve(cfg, "global", "password"))) { + if (password) + ast_free(password); + password = ast_strdup(tmp); + if (password == NULL) { + res = -1; + break; + } + } + + if ((tmp = ast_variable_retrieve(cfg, "global", "loguniqueid"))) { + loguniqueid = ast_true(tmp); + if (loguniqueid) { + ast_debug(1, "cdr_odbc: Logging uniqueid\n"); + } else { + ast_debug(1, "cdr_odbc: Not logging uniqueid\n"); + } } else { - ast_debug(1,"cdr_odbc: Not logging uniqueid\n"); + ast_debug(1, "cdr_odbc: Not logging uniqueid\n"); + loguniqueid = 0; } - } else { - ast_debug(1,"cdr_odbc: Not logging uniqueid\n"); - loguniqueid = 0; - } - tmp = ast_variable_retrieve(cfg,"global","usegmtime"); - if (tmp) { - usegmtime = ast_true(tmp); - if (usegmtime) { - ast_debug(1,"cdr_odbc: Logging in GMT\n"); + if ((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) { + usegmtime = ast_true(tmp); + if (usegmtime) { + ast_debug(1, "cdr_odbc: Logging in GMT\n"); + } else { + ast_debug(1, "cdr_odbc: Not logging in GMT\n"); + } } else { - ast_debug(1,"cdr_odbc: Not logging in GMT\n"); + ast_debug(1, "cdr_odbc: Not logging in GMT\n"); + usegmtime = 0; } - } else { - ast_debug(1,"cdr_odbc: Not logging in GMT\n"); - usegmtime = 0; - } - tmp = ast_variable_retrieve(cfg,"global","table"); - if (tmp == NULL) { - ast_log(LOG_WARNING,"cdr_odbc: table not specified. Assuming cdr\n"); - tmp = "cdr"; - } - table = strdup(tmp); - if (table == NULL) { - ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n"); - res = -1; - goto out; - } + if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) { + ast_log(LOG_WARNING, "cdr_odbc: table not specified. Assuming cdr\n"); + tmp = "cdr"; + } + if (table) + ast_free(table); + table = ast_strdup(tmp); + if (table == NULL) { + res = -1; + break; + } - ast_verb(3, "cdr_odbc: dsn is %s\n",dsn); - if (username) { - ast_verb(3, "cdr_odbc: username is %s\n",username); - ast_verb(3, "cdr_odbc: password is [secret]\n"); - } else - ast_verb(3, "cdr_odbc: retreiving username and password from odbc config\n"); - ast_verb(3, "cdr_odbc: table is %s\n",table); - - res = odbc_init(); - if (res < 0) { - ast_log(LOG_ERROR, "cdr_odbc: Unable to connect to datasource: %s\n", dsn); - ast_verb(3, "cdr_odbc: Unable to connect to datasource: %s\n", dsn); + ast_verb(3, "cdr_odbc: dsn is %s\n", dsn); + if (username) { + ast_verb(3, "cdr_odbc: username is %s\n", username); + ast_verb(3, "cdr_odbc: password is [secret]\n"); + } else + ast_verb(3, "cdr_odbc: retrieving username and password from odbc config\n"); + ast_verb(3, "cdr_odbc: table is %s\n", table); + + res = odbc_init(); + if (res < 0) { + ast_log(LOG_ERROR, "cdr_odbc: Unable to connect to datasource: %s\n", dsn); + ast_verb(3, "cdr_odbc: Unable to connect to datasource: %s\n", dsn); + } + res = ast_cdr_register(name, ast_module_info->description, odbc_log); + if (res) { + ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n"); } - res = ast_cdr_register(name, ast_module_info->description, odbc_log); - if (res) { - ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n"); - } -out: - if (cfg) + } while (0); + + if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) ast_config_destroy(cfg); ast_mutex_unlock(&odbc_lock); return res; @@ -418,7 +418,7 @@ static int odbc_init(void) static int load_module(void) { - return odbc_load_module(); + return odbc_load_module(0); } static int unload_module(void) @@ -428,8 +428,7 @@ static int unload_module(void) static int reload(void) { - odbc_unload_module(); - return odbc_load_module(); + return odbc_load_module(1); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ODBC CDR Backend", diff --git a/cdr/cdr_pgsql.c b/cdr/cdr_pgsql.c index 4ccd4aa83..d3813c65a 100644 --- a/cdr/cdr_pgsql.c +++ b/cdr/cdr_pgsql.c @@ -183,7 +183,7 @@ static int pgsql_log(struct ast_cdr *cdr) return 0; } -static int my_unload_module(void) +static int unload_module(void) { PQfinish(conn); if (pghostname) @@ -202,20 +202,30 @@ static int my_unload_module(void) return 0; } -static int process_my_load_module(struct ast_config *cfg) +static int config_module(int reload) { struct ast_variable *var; - char *pgerror; + char *pgerror; const char *tmp; + struct ast_config *cfg; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load(config, config_flags)) == NULL) { + ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config); + return -1; + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; if (!(var = ast_variable_browse(cfg, "global"))) return 0; - if (!(tmp = ast_variable_retrieve(cfg,"global","hostname"))) { - ast_log(LOG_WARNING,"PostgreSQL server hostname not specified. Assuming unix socket connection\n"); + if (!(tmp = ast_variable_retrieve(cfg, "global", "hostname"))) { + ast_log(LOG_WARNING, "PostgreSQL server hostname not specified. Assuming unix socket connection\n"); tmp = ""; /* connect via UNIX-socket by default */ } - + + if (pghostname) + ast_free(pghostname); if (!(pghostname = ast_strdup(tmp))) return -1; @@ -224,6 +234,8 @@ static int process_my_load_module(struct ast_config *cfg) tmp = "asteriskcdrdb"; } + if (pgdbname) + ast_free(pgdbname); if (!(pgdbname = ast_strdup(tmp))) return -1; @@ -232,6 +244,8 @@ static int process_my_load_module(struct ast_config *cfg) tmp = "asterisk"; } + if (pgdbuser) + ast_free(pgdbuser); if (!(pgdbuser = ast_strdup(tmp))) return -1; @@ -240,6 +254,8 @@ static int process_my_load_module(struct ast_config *cfg) tmp = ""; } + if (pgpassword) + ast_free(pgpassword); if (!(pgpassword = ast_strdup(tmp))) return -1; @@ -248,6 +264,8 @@ static int process_my_load_module(struct ast_config *cfg) tmp = "5432"; } + if (pgdbport) + ast_free(pgdbport); if (!(pgdbport = ast_strdup(tmp))) return -1; @@ -256,6 +274,8 @@ static int process_my_load_module(struct ast_config *cfg) tmp = "cdr"; } + if (table) + ast_free(table); if (!(table = ast_strdup(tmp))) return -1; @@ -276,49 +296,23 @@ static int process_my_load_module(struct ast_config *cfg) ast_debug(1, "Successfully connected to PostgreSQL database.\n"); connected = 1; } else { - pgerror = PQerrorMessage(conn); + pgerror = PQerrorMessage(conn); ast_log(LOG_ERROR, "cdr_pgsql: Unable to connect to database server %s. CALLS WILL NOT BE LOGGED!!\n", pghostname); - ast_log(LOG_ERROR, "cdr_pgsql: Reason: %s\n", pgerror); + ast_log(LOG_ERROR, "cdr_pgsql: Reason: %s\n", pgerror); connected = 0; } return ast_cdr_register(name, ast_module_info->description, pgsql_log); } -static int my_load_module(void) -{ - struct ast_config *cfg; - int res; - - if (!(cfg = ast_config_load(config))) { - ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config); - return AST_MODULE_LOAD_DECLINE; - } - - res = process_my_load_module(cfg); - ast_config_destroy(cfg); - - return res; -} - static int load_module(void) { - return my_load_module(); -} - -static int unload_module(void) -{ - return my_unload_module(); + return config_module(0) ? AST_MODULE_LOAD_DECLINE : 0; } static int reload(void) { - int res; - ast_mutex_lock(&pgsql_lock); - my_unload_module(); - res = my_load_module(); - ast_mutex_unlock(&pgsql_lock); - return res; + return config_module(1); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "PostgreSQL CDR Backend", diff --git a/cdr/cdr_radius.c b/cdr/cdr_radius.c index b344c0b26..207e24762 100644 --- a/cdr/cdr_radius.c +++ b/cdr/cdr_radius.c @@ -232,10 +232,11 @@ static int unload_module(void) static int load_module(void) { struct ast_config *cfg; + struct ast_flags config_flags = { 0 }; int res; const char *tmp; - if ((cfg = ast_config_load(cdr_config))) { + if ((cfg = ast_config_load(cdr_config, config_flags))) { ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "usegmtime")), RADIUS_FLAG_USEGMTIME); ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "loguniqueid")), RADIUS_FLAG_LOGUNIQUEID); ast_set2_flag(&global_flags, ast_true(ast_variable_retrieve(cfg, "radius", "loguserfield")), RADIUS_FLAG_LOGUSERFIELD); diff --git a/cdr/cdr_sqlite3_custom.c b/cdr/cdr_sqlite3_custom.c index c3dcbd269..1c663362b 100644 --- a/cdr/cdr_sqlite3_custom.c +++ b/cdr/cdr_sqlite3_custom.c @@ -74,10 +74,11 @@ static char values[1024]; static int load_config(int reload) { struct ast_config *cfg; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; struct ast_variable *mappingvar; const char *tmp; - if (!(cfg = ast_config_load(config_file))) { + if (!(cfg = ast_config_load(config_file, config_flags))) { if (reload) ast_log(LOG_WARNING, "%s: Failed to reload configuration file.\n", name); else { @@ -86,10 +87,10 @@ static int load_config(int reload) name); } return -1; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; - if (!reload) - ast_mutex_lock(&lock); + ast_mutex_lock(&lock); if (!(mappingvar = ast_variable_browse(cfg, "master"))) { /* nothing configured */ @@ -125,8 +126,7 @@ static int load_config(int reload) return -1; } - if (!reload) - ast_mutex_unlock(&lock); + ast_mutex_unlock(&lock); ast_config_destroy(cfg); @@ -248,13 +248,7 @@ static int load_module(void) static int reload(void) { - int res; - - ast_mutex_lock(&lock); - res = load_config(1); - ast_mutex_unlock(&lock); - - return res; + return load_config(1); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "SQLite3 Custom CDR Module", diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c index 2707a4b89..af58b86e6 100644 --- a/cdr/cdr_tds.c +++ b/cdr/cdr_tds.c @@ -422,95 +422,106 @@ static int tds_unload_module(void) return 0; } -static int tds_load_module(void) +static int tds_load_module(int reload) { int res = 0; struct ast_config *cfg; struct ast_variable *var; const char *ptr = NULL; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; #ifdef FREETDS_PRE_0_62 TDS_INT result_type; #endif - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); if (!cfg) { ast_log(LOG_NOTICE, "Unable to load config for MSSQL CDR's: %s\n", config); return 0; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; var = ast_variable_browse(cfg, "global"); if (!var) /* nothing configured */ return 0; ptr = ast_variable_retrieve(cfg, "global", "hostname"); - if (ptr) - hostname = strdup(ptr); - else - ast_log(LOG_ERROR,"Database server hostname not specified.\n"); + if (ptr) { + if (hostname) + ast_free(hostname); + hostname = ast_strdup(ptr); + } else + ast_log(LOG_ERROR, "Database server hostname not specified.\n"); ptr = ast_variable_retrieve(cfg, "global", "dbname"); - if (ptr) - dbname = strdup(ptr); - else - ast_log(LOG_ERROR,"Database dbname not specified.\n"); + if (ptr) { + if (dbname) + ast_free(dbname); + dbname = ast_strdup(ptr); + } else + ast_log(LOG_ERROR, "Database dbname not specified.\n"); ptr = ast_variable_retrieve(cfg, "global", "user"); - if (ptr) - dbuser = strdup(ptr); - else - ast_log(LOG_ERROR,"Database dbuser not specified.\n"); + if (ptr) { + if (dbuser) + ast_free(dbuser); + dbuser = ast_strdup(ptr); + } else + ast_log(LOG_ERROR, "Database dbuser not specified.\n"); ptr = ast_variable_retrieve(cfg, "global", "password"); - if (ptr) - password = strdup(ptr); - else + if (ptr) { + if (password) + ast_free(password); + password = ast_strdup(ptr); + } else ast_log(LOG_ERROR,"Database password not specified.\n"); ptr = ast_variable_retrieve(cfg, "global", "charset"); + if (charset) + ast_free(charset); if (ptr) - charset = strdup(ptr); + charset = ast_strdup(ptr); else - charset = strdup("iso_1"); + charset = ast_strdup("iso_1"); + if (language) + ast_free(language); ptr = ast_variable_retrieve(cfg, "global", "language"); if (ptr) - language = strdup(ptr); + language = ast_strdup(ptr); else - language = strdup("us_english"); + language = ast_strdup("us_english"); - ptr = ast_variable_retrieve(cfg,"global","table"); + ptr = ast_variable_retrieve(cfg, "global", "table"); if (ptr == NULL) { - ast_debug(1,"cdr_tds: table not specified. Assuming cdr\n"); + ast_debug(1, "cdr_tds: table not specified. Assuming cdr\n"); ptr = "cdr"; } - table = strdup(ptr); + if (table) + ast_free(table); + table = ast_strdup(ptr); ast_config_destroy(cfg); + ast_mutex_lock(&tds_lock); + mssql_disconnect(); mssql_connect(); - - /* Register MSSQL CDR handler */ - res = ast_cdr_register(name, ast_module_info->description, tds_log); - if (res) - { - ast_log(LOG_ERROR, "Unable to register MSSQL CDR handling\n"); - } + ast_mutex_unlock(&tds_lock); return res; } static int reload(void) { - tds_unload_module(); - return tds_load_module(); + return tds_load_module(1); } static int load_module(void) { - if(!tds_load_module()) + if (!tds_load_module(0)) return AST_MODULE_LOAD_DECLINE; - else - return AST_MODULE_LOAD_SUCCESS; + ast_cdr_register(name, ast_module_info->description, tds_log); + return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void) diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 880501ac9..c4e0ecb61 100644 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -976,7 +976,7 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state) * * \returns Always 0, or so it seems. */ -static int read_agent_config(void) +static int read_agent_config(int reload) { struct ast_config *cfg; struct ast_config *ucfg; @@ -986,17 +986,19 @@ static int read_agent_config(void) const char *catname; const char *hasagent; int genhasagent; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; group = 0; autologoff = 0; wrapuptime = 0; ackcall = 0; endcall = 1; - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); if (!cfg) { ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); return 0; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return -1; AST_LIST_LOCK(&agents); AST_LIST_TRAVERSE(&agents, p, list) { p->dead = 1; @@ -1081,7 +1083,7 @@ static int read_agent_config(void) } v = v->next; } - if ((ucfg = ast_config_load("users.conf"))) { + if ((ucfg = ast_config_load("users.conf", config_flags)) && ucfg != CONFIG_STATUS_FILEUNCHANGED) { genhasagent = ast_true(ast_variable_retrieve(ucfg, "general", "hasagent")); catname = ast_category_browse(ucfg, NULL); while(catname) { @@ -2276,7 +2278,7 @@ static int load_module(void) return -1; } /* Read in the config */ - if (!read_agent_config()) + if (!read_agent_config(0)) return AST_MODULE_LOAD_DECLINE; if (persistent_agents) reload_agents(); @@ -2299,9 +2301,10 @@ static int load_module(void) static int reload(void) { - read_agent_config(); - if (persistent_agents) - reload_agents(); + if (!read_agent_config(1)) { + if (persistent_agents) + reload_agents(); + } return 0; } diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index a2a10e85f..f043cbde3 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -1082,13 +1082,14 @@ static int load_module(void) { struct ast_config *cfg; struct ast_variable *v; + struct ast_flags config_flags = { 0 }; /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); strcpy(mohinterpret, "default"); - if (!(cfg = ast_config_load(config))) + if (!(cfg = ast_config_load(config, config_flags))) return AST_MODULE_LOAD_DECLINE; v = ast_variable_browse(cfg, "general"); diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index b4306fefe..22d8a29b6 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -1702,8 +1702,9 @@ static int gtalk_load_config(void) struct gtalk_candidate *global_candidates = NULL; struct hostent *hp; struct ast_hostent ahp; + struct ast_flags config_flags = { 0 }; - cfg = ast_config_load(GOOGLE_CONFIG); + cfg = ast_config_load(GOOGLE_CONFIG, config_flags); if (!cfg) return 0; diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 36f42e878..6da113ddb 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -2812,13 +2812,23 @@ static int reload_config(int is_reload) int is_user, is_peer, is_alias; char _gatekeeper[100]; int gk_discover, gk_disable, gk_changed; + struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config); return 1; + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { + ucfg = ast_config_load("users.conf", config_flags); + if (ucfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + cfg = ast_config_load(config, config_flags); + } else { + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + ucfg = ast_config_load("users.conf", config_flags); } /* fire up the H.323 Endpoint */ @@ -2851,8 +2861,6 @@ static int reload_config(int is_reload) /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); - /* Load configuration from users.conf */ - ucfg = ast_config_load("users.conf"); if (ucfg) { struct ast_variable *gen; int genhas_h323; diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 6f41fdb69..333ccb2fe 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -9776,15 +9776,26 @@ static int set_config(char *config_file, int reload) struct iax2_user *user; struct iax2_peer *peer; struct ast_netsock *ns; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; #if 0 static unsigned short int last_port=0; #endif - cfg = ast_config_load(config_file); - + cfg = ast_config_load(config_file, config_flags); + if (!cfg) { ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); return -1; + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { + ucfg = ast_config_load("users.conf", config_flags); + if (ucfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + /* Otherwise we need to reread both files */ + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + cfg = ast_config_load(config_file, config_flags); + } else { /* iax.conf changed, gotta reread users.conf, too */ + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + ucfg = ast_config_load("users.conf", config_flags); } /* Reset global codec prefs */ @@ -10048,7 +10059,6 @@ static int set_config(char *config_file, int reload) } iax2_capability = capability; - ucfg = ast_config_load("users.conf"); if (ucfg) { struct ast_variable *gen; int genhasiax; @@ -10176,7 +10186,7 @@ static int reload_config(void) iax2_poke_peer(peer, 0); AST_LIST_UNLOCK(&peers); reload_firmware(); - iax_provision_reload(); + iax_provision_reload(1); return 0; } @@ -11097,7 +11107,7 @@ static int load_module(void) AST_LIST_UNLOCK(&peers); reload_firmware(); - iax_provision_reload(); + iax_provision_reload(0); return AST_MODULE_LOAD_SUCCESS; } diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c index 8a3321c05..9848b9665 100644 --- a/channels/chan_jingle.c +++ b/channels/chan_jingle.c @@ -1567,8 +1567,9 @@ static int jingle_load_config(void) struct ast_codec_pref prefs; struct aji_client_container *clients; struct jingle_candidate *global_candidates = NULL; + struct ast_flags config_flags = { 0 }; - cfg = ast_config_load(JINGLE_CONFIG); + cfg = ast_config_load(JINGLE_CONFIG, config_flags); if (!cfg) return 0; diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 64d300faf..c4229e0a1 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -422,8 +422,8 @@ static void start_rtp(struct mgcp_subchannel *sub); static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp); static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub); -static int mgcp_do_reload(void); static int mgcp_reload(int fd, int argc, char *argv[]); +static int reload_config(int reload); static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause); static int mgcp_call(struct ast_channel *ast, char *dest, int timeout); @@ -3379,7 +3379,7 @@ static void *do_monitor(void *data) ast_mutex_unlock(&mgcp_reload_lock); if (reloading) { ast_verb(1, "Reloading MGCP\n"); - mgcp_do_reload(); + reload_config(1); /* Add an I/O event to our UDP socket */ if (mgcpsock > -1) mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); @@ -4042,7 +4042,7 @@ static void prune_gateways(void) ast_mutex_unlock(&gatelock); } -static int reload_config(void) +static int reload_config(int reload) { struct ast_config *cfg; struct ast_variable *v; @@ -4052,18 +4052,21 @@ static int reload_config(void) struct ast_hostent ahp; struct hostent *hp; int format; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; if (gethostname(ourhost, sizeof(ourhost)-1)) { ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); return 0; } - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); return 0; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + memset(&bindaddr, 0, sizeof(bindaddr)); dtmfmode = 0; @@ -4222,7 +4225,7 @@ static int load_module(void) return AST_MODULE_LOAD_FAILURE; } - if (reload_config()) + if (reload_config(0)) return AST_MODULE_LOAD_DECLINE; /* Make sure we can register our mgcp channel type */ @@ -4242,13 +4245,6 @@ static int load_module(void) return AST_MODULE_LOAD_SUCCESS; } -/*! \brief mgcp_do_reload: Reload module */ -static int mgcp_do_reload(void) -{ - reload_config(); - return 0; -} - static int mgcp_reload(int fd, int argc, char *argv[]) { static int deprecated = 0; diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index eb19e0326..96c55da8d 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -4753,7 +4753,7 @@ static int load_module(void) return AST_MODULE_LOAD_DECLINE; } - if (misdn_cfg_init(max_ports)) { + if (misdn_cfg_init(max_ports, 0)) { ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n"); return AST_MODULE_LOAD_DECLINE; } diff --git a/channels/chan_oss.c b/channels/chan_oss.c index 6256deb37..42e054609 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -1577,12 +1577,13 @@ static int load_module(void) { struct ast_config *cfg = NULL; char *ctg = NULL; + struct ast_flags config_flags = { 0 }; /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); /* load config file */ - if (!(cfg = ast_config_load(config))) { + if (!(cfg = ast_config_load(config, config_flags))) { ast_log(LOG_NOTICE, "Unable to load config %s\n", config); return AST_MODULE_LOAD_DECLINE; } diff --git a/channels/chan_phone.c b/channels/chan_phone.c index e99b74ee9..49b9cf77a 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -1347,7 +1347,9 @@ static int load_module(void) struct phone_pvt *tmp; int mode = MODE_IMMEDIATE; int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */ - cfg = ast_config_load(config); + struct ast_flags config_flags = { 0 }; + + cfg = ast_config_load(config, config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f096ffa73..4df005db1 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -17629,16 +17629,27 @@ static int reload_config(enum channelreloadreason reason) char *cat, *stringp, *context, *oldregcontext; char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT]; struct ast_flags dummy[2]; + struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; int auto_sip_domains = FALSE; struct sockaddr_in old_bindaddr = bindaddr; int registry_count = 0, peer_count = 0, user_count = 0; - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { ast_log(LOG_NOTICE, "Unable to load config %s\n", config); return -1; + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { + ucfg = ast_config_load("users.conf", config_flags); + if (ucfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + /* Must reread both files, because one changed */ + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + cfg = ast_config_load(config, config_flags); + } else { + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + ucfg = ast_config_load("users.conf", config_flags); } /* Initialize copy of current global_regcontext for later use in removing stale contexts */ @@ -18007,7 +18018,6 @@ static int reload_config(enum channelreloadreason reason) authl = add_realm_authentication(authl, v->value, v->lineno); } - ucfg = ast_config_load("users.conf"); if (ucfg) { struct ast_variable *gen; int genhassip, genregistersip; @@ -18181,7 +18191,7 @@ static int reload_config(enum channelreloadreason reason) /* Load the list of manual NOTIFY types to support */ if (notify_types) ast_config_destroy(notify_types); - notify_types = ast_config_load(notify_config); + notify_types = ast_config_load(notify_config, config_flags); /* Done, tell the manager */ manager_event(EVENT_FLAG_SYSTEM, "ChannelReload", "ChannelType: SIP\r\nReloadReason: %s\r\nRegistry_Count: %d\r\nPeer_Count: %d\r\nUser_Count: %d\r\n\r\n", channelreloadreason2txt(reason), registry_count, peer_count, user_count); diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index d9629ed2f..f8e22d93e 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -5142,12 +5142,13 @@ static int reload_config(void) int oldport = ntohs(bindaddr.sin_port); char *stringp, *context, *oldregcontext; char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT]; + struct ast_flags config_flags = { 0 }; if (gethostname(ourhost, sizeof(ourhost))) { ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled\n"); return 0; } - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc index bcc3f6834..852872714 100644 --- a/channels/chan_vpb.cc +++ b/channels/chan_vpb.cc @@ -2636,7 +2636,7 @@ static float parse_gain_value(char *gain_type, char *value) } -int unload_module() +static int unload_module() { struct vpb_pvt *p; /* First, take us out of the channel loop */ @@ -2701,10 +2701,11 @@ int unload_module() return 0; } -int load_module() +static int load_module() { struct ast_config *cfg; struct ast_variable *v; + struct ast_flags config_flags = { 0 }; struct vpb_pvt *tmp; int board = 0, group = 0; ast_group_t callgroup = 0; @@ -2721,7 +2722,7 @@ int load_module() int bal3 = -1; char * callerid = NULL; - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { @@ -2897,29 +2898,10 @@ int load_module() return error; } -int usecount() -{ - return usecnt; -} - -const char *description() -{ - return (char *) desc; -} - -const char *key() -{ - return ASTERISK_GPL_KEY; -} - /**/ #if defined(__cplusplus) || defined(c_plusplus) } #endif /**/ -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "VoiceTronix API driver", - .load = load_module, - .unload = unload_module, - .reload = reload, - ); +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "VoiceTronix API driver"); diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 35be3ecdf..d4feae885 100644 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -12623,27 +12623,37 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r static int setup_zap(int reload) { - struct ast_config *cfg; + struct ast_config *cfg, *ucfg; struct ast_variable *v; struct zt_chan_conf base_conf = zt_chan_conf_default(); struct zt_chan_conf conf; - int res; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + int res, x; #ifdef HAVE_PRI char *c; int spanno; - int i, x; + int i; int logicalspan; int trunkgroup; int dchannels[NUM_DCHANS]; #endif - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); /* Error if we have no config file */ if (!cfg) { ast_log(LOG_ERROR, "Unable to load config %s\n", config); return 0; + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { + ucfg = ast_config_load("users.conf", config_flags); + if (ucfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + cfg = ast_config_load(config, config_flags); + } else { + ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); + ucfg = ast_config_load("users.conf", config_flags); } /* It's a little silly to lock it, but we mind as well just to be sure */ @@ -12718,25 +12728,24 @@ static int setup_zap(int reload) ast_config_destroy(cfg); if (res) return res; - cfg = ast_config_load("users.conf"); - if (cfg) { + if (ucfg) { char *cat; const char *chans; process_zap(&base_conf, ast_variable_browse(cfg, "general"), 1, 1); - for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { + for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { if (!strcasecmp(cat, "general")) continue; - chans = ast_variable_retrieve(cfg, cat, "zapchan"); + chans = ast_variable_retrieve(ucfg, cat, "zapchan"); if (!ast_strlen_zero(chans)) { if (memcpy(&conf, &base_conf, sizeof(conf)) == NULL) { ast_log(LOG_ERROR, "Not enough memory for conf copy\n"); - ast_config_destroy(cfg); + ast_config_destroy(ucfg); return -1; } - process_zap(&conf, ast_variable_browse(cfg, cat), reload, 0); + process_zap(&conf, ast_variable_browse(ucfg, cat), reload, 0); } } - ast_config_destroy(cfg); + ast_config_destroy(ucfg); } #ifdef HAVE_PRI if (!reload) { diff --git a/channels/iax2-provision.c b/channels/iax2-provision.c index dd3419a9e..031897fc7 100644 --- a/channels/iax2-provision.c +++ b/channels/iax2-provision.c @@ -485,12 +485,13 @@ int iax_provision_unload(void) return 0; } -int iax_provision_reload(void) +int iax_provision_reload(int reload) { struct ast_config *cfg; struct iax_template *cur, *prev, *next; char *cat; int found = 0; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; if (!provinit) iax_provision_init(); /* Mark all as dead. No need for locking */ @@ -499,8 +500,8 @@ int iax_provision_reload(void) cur->dead = 1; cur = cur->next; } - cfg = ast_config_load("iaxprov.conf"); - if (cfg) { + cfg = ast_config_load("iaxprov.conf", config_flags); + if (cfg != NULL && cfg != CONFIG_STATUS_FILEUNCHANGED) { /* Load as appropriate */ cat = ast_category_browse(cfg, NULL); while(cat) { @@ -512,7 +513,9 @@ int iax_provision_reload(void) cat = ast_category_browse(cfg, cat); } ast_config_destroy(cfg); - } else + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + else ast_log(LOG_NOTICE, "No IAX provisioning configuration found, IAX provisioning disabled.\n"); ast_mutex_lock(&provlock); /* Drop dead entries while locked */ diff --git a/channels/iax2-provision.h b/channels/iax2-provision.h index d95150253..b1dfd06d0 100644 --- a/channels/iax2-provision.h +++ b/channels/iax2-provision.h @@ -46,7 +46,7 @@ #define PROV_FLAG_DIS_THREEWAY (1 << 7) /* Three-way calling, transfer disabled */ char *iax_provflags2str(char *buf, int buflen, unsigned int flags); -int iax_provision_reload(void); +int iax_provision_reload(int reload); int iax_provision_unload(void); int iax_provision_build(struct iax_ie_data *provdata, unsigned int *signature, const char *template, int force); int iax_provision_version(unsigned int *signature, const char *template, int force); diff --git a/channels/misdn/chan_misdn_config.h b/channels/misdn/chan_misdn_config.h index 2708da4d3..87481deb3 100644 --- a/channels/misdn/chan_misdn_config.h +++ b/channels/misdn/chan_misdn_config.h @@ -108,7 +108,7 @@ enum misdn_cfg_method { }; /* you must call misdn_cfg_init before any other function of this header file */ -int misdn_cfg_init(int max_ports); +int misdn_cfg_init(int max_ports, int reload); void misdn_cfg_reload(void); void misdn_cfg_destroy(void); diff --git a/channels/misdn_config.c b/channels/misdn_config.c index bdd14370c..008f0f6e4 100644 --- a/channels/misdn_config.c +++ b/channels/misdn_config.c @@ -1063,7 +1063,7 @@ static void _fill_defaults (void) void misdn_cfg_reload (void) { - misdn_cfg_init (0); + misdn_cfg_init(0, 1); } void misdn_cfg_destroy (void) @@ -1082,18 +1082,20 @@ void misdn_cfg_destroy (void) ast_mutex_destroy(&config_mutex); } -int misdn_cfg_init (int this_max_ports) +int misdn_cfg_init(int this_max_ports, int reload) { char config[] = "misdn.conf"; char *cat, *p; int i; struct ast_config *cfg; struct ast_variable *v; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - if (!(cfg = AST_LOAD_CFG(config))) { + if (!(cfg = AST_LOAD_CFG(config, config_flags))) { ast_log(LOG_WARNING, "missing file: misdn.conf\n"); return -1; - } + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; ast_mutex_init(&config_mutex); diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c index fb4bb8bd7..e76470b6c 100644 --- a/codecs/codec_adpcm.c +++ b/codecs/codec_adpcm.c @@ -350,11 +350,12 @@ static struct ast_translator lintoadpcm = { .buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */ }; -static void parse_config(void) +static void parse_config(int reload) { - struct ast_config *cfg = ast_config_load("codecs.conf"); + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); struct ast_variable *var; - if (cfg == NULL) + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var ; var = var->next) { if (!strcasecmp(var->name, "genericplc")) { @@ -368,7 +369,7 @@ static void parse_config(void) /*! \brief standard module glue */ static int reload(void) { - parse_config(); + parse_config(1); return 0; } @@ -386,7 +387,7 @@ static int load_module(void) { int res; - parse_config(); + parse_config(0); res = ast_register_translator(&adpcmtolin); if (!res) res = ast_register_translator(&lintoadpcm); diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c index 9edae5130..1c2805535 100644 --- a/codecs/codec_alaw.c +++ b/codecs/codec_alaw.c @@ -134,11 +134,12 @@ static struct ast_translator lintoalaw = { .buf_size = BUFFER_SAMPLES, }; -static void parse_config(void) +static void parse_config(int reload) { struct ast_variable *var; - struct ast_config *cfg = ast_config_load("codecs.conf"); - if (!cfg) + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { if (!strcasecmp(var->name, "genericplc")) { @@ -153,7 +154,7 @@ static void parse_config(void) static int reload(void) { - parse_config(); + parse_config(1); return 0; } @@ -171,7 +172,7 @@ static int load_module(void) { int res; - parse_config(); + parse_config(0); res = ast_register_translator(&alawtolin); if (!res) res = ast_register_translator(&lintoalaw); diff --git a/codecs/codec_g722.c b/codecs/codec_g722.c index 46d34f1ba..b2b760912 100644 --- a/codecs/codec_g722.c +++ b/codecs/codec_g722.c @@ -164,12 +164,13 @@ static struct ast_translator lintog722 = { .buf_size = BUFFER_SAMPLES, }; -static void parse_config(void) +static void parse_config(int reload) { struct ast_variable *var; - struct ast_config *cfg = ast_config_load("codecs.conf"); + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); - if (!cfg) + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { if (!strcasecmp(var->name, "genericplc")) { @@ -183,7 +184,7 @@ static void parse_config(void) static int reload(void) { - parse_config(); + parse_config(1); return 0; } @@ -203,7 +204,7 @@ static int load_module(void) int res = 0; - parse_config(); + parse_config(0); res |= ast_register_translator(&g722tolin); res |= ast_register_translator(&lintog722); diff --git a/codecs/codec_g726.c b/codecs/codec_g726.c index 425ba9bef..ba80588fa 100644 --- a/codecs/codec_g726.c +++ b/codecs/codec_g726.c @@ -894,12 +894,13 @@ static struct ast_translator g726aal2tog726 = { .buf_size = BUFFER_SAMPLES, }; -static void parse_config(void) +static void parse_config(int reload) { struct ast_variable *var; - struct ast_config *cfg = ast_config_load("codecs.conf"); + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); - if (!cfg) + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { if (!strcasecmp(var->name, "genericplc")) { @@ -913,7 +914,7 @@ static void parse_config(void) static int reload(void) { - parse_config(); + parse_config(1); return 0; } @@ -939,7 +940,7 @@ static int load_module(void) int res = 0; - parse_config(); + parse_config(0); res |= ast_register_translator(&g726tolin); res |= ast_register_translator(&lintog726); diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c index c346f24cf..b19abfe88 100644 --- a/codecs/codec_gsm.c +++ b/codecs/codec_gsm.c @@ -235,11 +235,12 @@ static struct ast_translator lintogsm = { }; -static void parse_config(void) +static void parse_config(int reload) { struct ast_variable *var; - struct ast_config *cfg = ast_config_load("codecs.conf"); - if (!cfg) + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); + if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { if (!strcasecmp(var->name, "genericplc")) { @@ -253,7 +254,7 @@ static void parse_config(void) /*! \brief standard module glue */ static int reload(void) { - parse_config(); + parse_config(1); return 0; } @@ -272,7 +273,7 @@ static int load_module(void) { int res; - parse_config(); + parse_config(0); res = ast_register_translator(&gsmtolin); if (!res) res=ast_register_translator(&lintogsm); diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c index d4688cd9b..3ed528bef 100644 --- a/codecs/codec_lpc10.c +++ b/codecs/codec_lpc10.c @@ -261,27 +261,28 @@ static struct ast_translator lintolpc10 = { .buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME), }; -static void parse_config(void) +static void parse_config(int reload) { - struct ast_variable *var; - struct ast_config *cfg = ast_config_load("codecs.conf"); - if (!cfg) + struct ast_variable *var; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { - if (!strcasecmp(var->name, "genericplc")) { + if (!strcasecmp(var->name, "genericplc")) { lpc10tolin.useplc = ast_true(var->value) ? 1 : 0; ast_verb(3, "codec_lpc10: %susing generic PLC\n", lpc10tolin.useplc ? "" : "not "); } - } + } ast_config_destroy(cfg); } static int reload(void) { - parse_config(); + parse_config(1); - return 0; + return 0; } @@ -299,10 +300,10 @@ static int load_module(void) { int res; - parse_config(); - res=ast_register_translator(&lpc10tolin); + parse_config(0); + res = ast_register_translator(&lpc10tolin); if (!res) - res=ast_register_translator(&lintolpc10); + res = ast_register_translator(&lintolpc10); else ast_unregister_translator(&lpc10tolin); diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c index 1cbd5d9fb..c4e24f915 100644 --- a/codecs/codec_speex.c +++ b/codecs/codec_speex.c @@ -375,14 +375,15 @@ static struct ast_translator lintospeex = { .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */ }; -static void parse_config(void) +static void parse_config(int reload) { - struct ast_config *cfg = ast_config_load("codecs.conf"); + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); struct ast_variable *var; int res; float res_f; - if (cfg == NULL) + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) { @@ -470,7 +471,7 @@ static void parse_config(void) static int reload(void) { - parse_config(); + parse_config(1); return 0; } @@ -489,7 +490,7 @@ static int load_module(void) { int res; - parse_config(); + parse_config(0); res=ast_register_translator(&speextolin); if (!res) res=ast_register_translator(&lintospeex); diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c index ce248f1c1..4ffbe835f 100644 --- a/codecs/codec_ulaw.c +++ b/codecs/codec_ulaw.c @@ -147,11 +147,12 @@ static struct ast_translator lintoulaw = { .buffer_samples = BUFFER_SAMPLES, }; -static void parse_config(void) +static void parse_config(int reload) { struct ast_variable *var; - struct ast_config *cfg = ast_config_load("codecs.conf"); - if (!cfg) + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { if (!strcasecmp(var->name, "genericplc")) { @@ -164,7 +165,7 @@ static void parse_config(void) static int reload(void) { - parse_config(); + parse_config(1); return 0; } @@ -183,7 +184,7 @@ static int load_module(void) { int res; - parse_config(); + parse_config(0); res = ast_register_translator(&ulawtolin); if (!res) res = ast_register_translator(&lintoulaw); diff --git a/codecs/codec_zap.c b/codecs/codec_zap.c index 9204baad7..b3226ffc3 100644 --- a/codecs/codec_zap.c +++ b/codecs/codec_zap.c @@ -312,12 +312,13 @@ static void unregister_translators(void) AST_LIST_UNLOCK(&translators); } -static void parse_config(void) +static void parse_config(int reload) { struct ast_variable *var; - struct ast_config *cfg = ast_config_load("codecs.conf"); + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); - if (!cfg) + if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED) return; for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { @@ -387,7 +388,7 @@ static int reload(void) { struct translator *cur; - parse_config(); + parse_config(1); AST_LIST_LOCK(&translators); AST_LIST_TRAVERSE(&translators, cur, entry) @@ -406,7 +407,7 @@ static int unload_module(void) static int load_module(void) { - parse_config(); + parse_config(0); find_transcoders(); return 0; diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index 856c5c288..ee80fcc98 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -746,12 +746,13 @@ static int load_module(void) int res = 0; struct ast_config *cfg; char *catg; + struct ast_flags config_flags = { 0 }; res |= ast_custom_function_register(&fetch_function); res |= ast_register_application(app_odbcfinish, exec_odbcfinish, syn_odbcfinish, desc_odbcfinish); AST_LIST_LOCK(&queries); - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); if (!cfg) { ast_log(LOG_NOTICE, "Unable to load config for func_odbc: %s\n", config); AST_LIST_UNLOCK(&queries); @@ -815,6 +816,11 @@ static int reload(void) struct ast_config *cfg; struct acf_odbc_query *oldquery; char *catg; + struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; + + cfg = ast_config_load(config, config_flags); + if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; AST_LIST_LOCK(&queries); @@ -824,7 +830,6 @@ static int reload(void) free_acf_query(oldquery); } - cfg = ast_config_load(config); if (!cfg) { ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config); goto reload_out; diff --git a/include/asterisk/config.h b/include/asterisk/config.h index 2df0a435a..bbea0c47f 100644 --- a/include/asterisk/config.h +++ b/include/asterisk/config.h @@ -27,12 +27,26 @@ extern "C" { #endif +#include "asterisk/utils.h" #include <stdarg.h> struct ast_config; struct ast_category; +/*! Options for ast_config_load() + */ +enum { + /*! Load the configuration, including comments */ + CONFIG_FLAG_WITHCOMMENTS = (1 << 0), + /*! On a reload, give us a -1 if the file hasn't changed. */ + CONFIG_FLAG_FILEUNCHANGED = (1 << 1), + /*! Don't attempt to cache mtime on this config file. */ + CONFIG_FLAG_NOCACHE = (1 << 2), +}; + +#define CONFIG_STATUS_FILEUNCHANGED (void *)-1 + /*! \brief Structure for variables, used for configurations and for channel variables */ struct ast_variable { @@ -47,7 +61,7 @@ struct ast_variable { char stuff[0]; }; -typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, int withcomments); +typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, struct ast_flags flags); typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap); typedef struct ast_config *realtime_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); @@ -69,12 +83,15 @@ struct ast_config_engine { /*! \brief Load a config file * \param 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. + * \param flags Optional flags: + * CONFIG_FLAG_WITHCOMMENTS - load the file with comments intact; + * CONFIG_FLAG_FILEUNCHANGED - check the file mtime and return CONFIG_STATUS_FILEUNCHANGED if the mtime is the same; or + * CONFIG_FLAG_NOCACHE - don't cache file mtime (main purpose of this option is to save memory on temporary files). * * \retval an ast_config data structure on success * \retval NULL on error */ -struct ast_config *ast_config_load(const char *filename); -struct ast_config *ast_config_load_with_comments(const char *filename); +struct ast_config *ast_config_load(const char *filename, struct ast_flags flags); /*! \brief Destroys a config * \param config pointer to config data structure @@ -240,7 +257,7 @@ int ast_variable_update(struct ast_category *category, const char *variable, int config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator); -struct ast_config *ast_config_internal_load(const char *configfile, struct ast_config *cfg, int withcomments); +struct ast_config *ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags); /*! \brief Support code to parse config file arguments * diff --git a/main/asterisk.c b/main/asterisk.c index 118dd2982..052bf629d 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -2290,13 +2290,14 @@ static void ast_readconfig(void) struct ast_variable *v; char *config = AST_CONFIG_FILE; char hostname[MAXHOSTNAMELEN] = ""; + struct ast_flags config_flags = { 0 }; if (ast_opt_override_config) { - cfg = ast_config_load(ast_config_AST_CONFIG_FILE); + cfg = ast_config_load(ast_config_AST_CONFIG_FILE, config_flags); if (!cfg) ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE); } else - cfg = ast_config_load(config); + cfg = ast_config_load(config, config_flags); /* init with buildtime config */ ast_copy_string(ast_config_AST_CONFIG_DIR, AST_CONFIG_DIR, sizeof(ast_config_AST_CONFIG_DIR)); diff --git a/main/cdr.c b/main/cdr.c index 6f0d75aab..6cbb52f7e 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -1281,7 +1281,7 @@ static struct ast_cli_entry cli_status = { " Displays the Call Detail Record engine system status.\n" }; -static int do_reload(void) +static int do_reload(int reload) { struct ast_config *config; const char *enabled_value; @@ -1296,6 +1296,10 @@ static int do_reload(void) int was_enabled; int was_batchmode; int res=0; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((config = ast_config_load("cdr.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; ast_mutex_lock(&cdr_batch_lock); @@ -1312,7 +1316,7 @@ static int do_reload(void) if (cdr_sched > -1) ast_sched_del(sched, cdr_sched); - if ((config = ast_config_load("cdr.conf"))) { + if (config) { if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { enabled = ast_true(enabled_value); } @@ -1405,7 +1409,7 @@ int ast_cdr_engine_init(void) ast_cli_register(&cli_status); - res = do_reload(); + res = do_reload(0); if (res) { ast_mutex_lock(&cdr_batch_lock); res = init_batch(); @@ -1424,6 +1428,6 @@ void ast_cdr_engine_term(void) int ast_cdr_engine_reload(void) { - return do_reload(); + return do_reload(1); } diff --git a/main/config.c b/main/config.c index 01c9c9a0c..1405423c4 100644 --- a/main/config.c +++ b/main/config.c @@ -65,12 +65,27 @@ static char *extconfig_conf = "extconfig.conf"; /*! \brief Structure to keep comments for rewriting configuration files */ -/*! \brief Structure to keep comments for rewriting configuration files */ struct ast_comment { struct ast_comment *next; char cmt[0]; }; +/*! \brief Hold the mtime for config files, so if we don't need to reread our config, don't. */ +struct cache_file_include { + AST_LIST_ENTRY(cache_file_include) list; + char include[0]; +}; + +struct cache_file_mtime { + AST_LIST_ENTRY(cache_file_mtime) list; + AST_LIST_HEAD(includes, cache_file_include) includes; + unsigned int has_exec:1; + time_t mtime; + char filename[0]; +}; + +static AST_LIST_HEAD_STATIC(cfmtime_head, cache_file_mtime); + #define CB_INCR 250 static void CB_INIT(char **comment_buffer, int *comment_buffer_size, char **lline_buffer, int *lline_buffer_size) @@ -590,7 +605,58 @@ void ast_config_set_current_category(struct ast_config *cfg, const struct ast_ca cfg->current = (struct ast_category *) cat; } -static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, int withcomments, +enum config_cache_attribute_enum { + ATTRIBUTE_INCLUDE = 0, + ATTRIBUTE_EXEC = 1, +}; + +static void config_cache_attribute(const char *configfile, enum config_cache_attribute_enum attrtype, const char *filename) +{ + struct cache_file_mtime *cfmtime; + struct cache_file_include *cfinclude; + struct stat statbuf = { 0, }; + + /* Find our cached entry for this configuration file */ + AST_LIST_LOCK(&cfmtime_head); + AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) { + if (!strcmp(cfmtime->filename, configfile)) + break; + } + if (!cfmtime) { + cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(configfile) + 1); + if (!cfmtime) { + AST_LIST_UNLOCK(&cfmtime_head); + return; + } + AST_LIST_HEAD_INIT(&cfmtime->includes); + strcpy(cfmtime->filename, configfile); + /* Note that the file mtime is initialized to 0, i.e. 1970 */ + AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list); + } + + if (!stat(configfile, &statbuf)) + cfmtime->mtime = 0; + else + cfmtime->mtime = statbuf.st_mtime; + + switch (attrtype) { + case ATTRIBUTE_INCLUDE: + cfinclude = ast_calloc(1, sizeof(*cfinclude) + strlen(filename) + 1); + if (!cfinclude) { + AST_LIST_UNLOCK(&cfmtime_head); + return; + } + strcpy(cfinclude->include, filename); + AST_LIST_INSERT_TAIL(&cfmtime->includes, cfinclude, list); + break; + case ATTRIBUTE_EXEC: + cfmtime->has_exec = 1; + break; + } + AST_LIST_UNLOCK(&cfmtime_head); +} + +static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, struct ast_flags flags, char **comment_buffer, int *comment_buffer_size, char **lline_buffer, int *lline_buffer_size) { char *c; @@ -619,13 +685,13 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, return -1; } /* add comments */ - if (withcomments && *comment_buffer && (*comment_buffer)[0] ) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *comment_buffer && (*comment_buffer)[0] ) { newcat->precomments = ALLOC_COMMENT(*comment_buffer); } - if (withcomments && *lline_buffer && (*lline_buffer)[0] ) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *lline_buffer && (*lline_buffer)[0] ) { newcat->sameline = ALLOC_COMMENT(*lline_buffer); } - if ( withcomments ) + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) CB_RESET(comment_buffer, lline_buffer); /* If there are options or categories to inherit from, process them now */ @@ -702,15 +768,20 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, } /* #exec </path/to/executable> We create a tmp file, then we #include it, then we delete it. */ - if (do_exec) { + if (do_exec) { + if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) + config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL); snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self()); snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file); ast_safe_system(cmd); cur = exec_file; - } else + } else { + if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) + config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur); exec_file[0] = '\0'; + } /* A #include */ - do_include = ast_config_internal_load(cur, cfg, withcomments) ? 1 : 0; + do_include = ast_config_internal_load(cur, cfg, flags) ? 1 : 0; if (!ast_strlen_zero(exec_file)) unlink(exec_file); if (!do_include) @@ -750,13 +821,13 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, v->blanklines = 0; ast_variable_append(*cat, v); /* add comments */ - if (withcomments && *comment_buffer && (*comment_buffer)[0] ) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *comment_buffer && (*comment_buffer)[0] ) { v->precomments = ALLOC_COMMENT(*comment_buffer); } - if (withcomments && *lline_buffer && (*lline_buffer)[0] ) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *lline_buffer && (*lline_buffer)[0] ) { v->sameline = ALLOC_COMMENT(*lline_buffer); } - if ( withcomments ) + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) CB_RESET(comment_buffer, lline_buffer); } else { @@ -769,7 +840,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, return 0; } -static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments) +static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, struct ast_flags flags) { char fn[256]; char buf[8192]; @@ -780,6 +851,8 @@ static struct ast_config *config_text_file_load(const char *database, const char struct ast_category *cat = NULL; int count = 0; struct stat statbuf; + struct cache_file_mtime *cfmtime = NULL; + struct cache_file_include *cfinclude; /*! Growable string buffer */ char *comment_buffer=0; /*!< this will be a comment collector.*/ int comment_buffer_size=0; /*!< the amount of storage so far alloc'd for the comment_buffer */ @@ -787,8 +860,8 @@ static struct ast_config *config_text_file_load(const char *database, const char char *lline_buffer=0; /*!< A buffer for stuff behind the ; */ int lline_buffer_size=0; - - cat = ast_config_get_current_category(cfg); + if (cfg) + cat = ast_config_get_current_category(cfg); if (filename[0] == '/') { ast_copy_string(fn, filename, sizeof(fn)); @@ -796,7 +869,7 @@ static struct ast_config *config_text_file_load(const char *database, const char snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, filename); } - if (withcomments) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) { CB_INIT(&comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size); if (!lline_buffer || !comment_buffer) { ast_log(LOG_ERROR, "Failed to initialize the comment buffer!\n"); @@ -833,6 +906,77 @@ static struct ast_config *config_text_file_load(const char *database, const char ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn); continue; } + + if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) { + /* Find our cached entry for this configuration file */ + AST_LIST_LOCK(&cfmtime_head); + AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) { + if (!strcmp(cfmtime->filename, fn)) + break; + } + if (!cfmtime) { + cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(fn) + 1); + if (!cfmtime) + continue; + AST_LIST_HEAD_INIT(&cfmtime->includes); + strcpy(cfmtime->filename, fn); + /* Note that the file mtime is initialized to 0, i.e. 1970 */ + AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list); + } + } + + if (cfmtime && (!cfmtime->has_exec) && (cfmtime->mtime == statbuf.st_mtime) && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) { + /* File is unchanged, what about the (cached) includes (if any)? */ + int unchanged = 1; + AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) { + /* We must glob here, because if we did not, then adding a file to globbed directory would + * incorrectly cause no reload to be necessary. */ + char fn2[256]; +#ifdef AST_INCLUDE_GLOB + int glob_ret; + glob_t globbuf = { .gl_offs = 0 }; +#ifdef SOLARIS + glob_ret = glob(cfinclude->include, GLOB_NOCHECK, NULL, &globbuf); +#else + glob_ret = glob(cfinclude->include, GLOB_NOMAGIC|GLOB_BRACE, NULL, &globbuf); +#endif + /* On error, we reparse */ + if (glob_ret == GLOB_NOSPACE || glob_ret == GLOB_ABORTED) + unchanged = 0; + else { + /* loop over expanded files */ + int j; + for (j = 0; j < globbuf.gl_pathc; j++) { + ast_copy_string(fn2, globbuf.gl_pathv[j], sizeof(fn2)); +#else + ast_copy_string(fn2, cfinclude->include); +#endif + if (config_text_file_load(NULL, NULL, fn2, NULL, flags) == NULL) { + unchanged = 0; + /* One change is enough to short-circuit and reload the whole shebang */ + break; + } +#ifdef AST_INCLUDE_GLOB + } + } +#endif + } + + if (unchanged) { + AST_LIST_UNLOCK(&cfmtime_head); + return CONFIG_STATUS_FILEUNCHANGED; + } + } + if (cfmtime) + AST_LIST_UNLOCK(&cfmtime_head); + + /* If cfg is NULL, then we just want an answer */ + if (cfg == NULL) + return NULL; + + if (cfmtime) + cfmtime->mtime = statbuf.st_mtime; + ast_verb(2, "Parsing '%s': ", fn); fflush(stdout); if (!(f = fopen(fn, "r"))) { @@ -846,7 +990,7 @@ static struct ast_config *config_text_file_load(const char *database, const char while (!feof(f)) { lineno++; if (fgets(buf, sizeof(buf), f)) { - if ( withcomments ) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) { CB_ADD(&comment_buffer, &comment_buffer_size, lline_buffer); /* add the current lline buffer to the comment buffer */ lline_buffer[0] = 0; /* erase the lline buffer */ } @@ -883,7 +1027,7 @@ static struct ast_config *config_text_file_load(const char *database, const char /* Actually have to move what's left over the top, then continue */ char *oldptr; oldptr = process_buf + strlen(process_buf); - if ( withcomments ) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) { CB_ADD(&comment_buffer, &comment_buffer_size, ";"); CB_ADD_LEN(&comment_buffer, &comment_buffer_size, oldptr+1, new_buf-oldptr-1); } @@ -897,7 +1041,7 @@ static struct ast_config *config_text_file_load(const char *database, const char if (!comment) { /* If ; is found, and we are not nested in a comment, we immediately stop all comment processing */ - if ( withcomments ) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) { LLB_ADD(&lline_buffer, &lline_buffer_size, comment_p); } *comment_p = '\0'; @@ -906,7 +1050,7 @@ static struct ast_config *config_text_file_load(const char *database, const char new_buf = comment_p + 1; } } - if ( withcomments && comment && !process_buf ) + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment && !process_buf ) { CB_ADD(&comment_buffer, &comment_buffer_size, buf); /* the whole line is a comment, store it */ } @@ -914,7 +1058,7 @@ static struct ast_config *config_text_file_load(const char *database, const char if (process_buf) { char *buf = ast_strip(process_buf); if (!ast_strlen_zero(buf)) { - if (process_text_line(cfg, &cat, buf, lineno, fn, withcomments, &comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size)) { + if (process_text_line(cfg, &cat, buf, lineno, fn, flags, &comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size)) { cfg = NULL; break; } @@ -928,7 +1072,7 @@ static struct ast_config *config_text_file_load(const char *database, const char ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]); } #ifdef AST_INCLUDE_GLOB - if (!cfg) + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) break; } globfree(&globbuf); @@ -936,7 +1080,7 @@ static struct ast_config *config_text_file_load(const char *database, const char } #endif - if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) { + if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg->include_level == 1 && ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer) { ast_free(comment_buffer); ast_free(lline_buffer); comment_buffer = NULL; @@ -1090,12 +1234,13 @@ int read_config_maps(void) struct ast_config *config, *configtmp; struct ast_variable *v; char *driver, *table, *database, *stringp, *tmp; + struct ast_flags flags = { 0 }; clear_config_maps(); configtmp = ast_config_new(); configtmp->max_include_level = 1; - config = ast_config_internal_load(extconfig_conf, configtmp, 0); + config = ast_config_internal_load(extconfig_conf, configtmp, flags); if (!config) { ast_config_destroy(configtmp); return 0; @@ -1234,7 +1379,7 @@ static struct ast_config_engine text_file_engine = { .load_func = config_text_file_load, }; -struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments) +struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, struct ast_flags flags) { char db[256]; char table[256]; @@ -1263,9 +1408,9 @@ struct ast_config *ast_config_internal_load(const char *filename, struct ast_con } } - result = loader->load_func(db, table, filename, cfg, withcomments); + result = loader->load_func(db, table, filename, cfg, flags); - if (result) + if (result && result != CONFIG_STATUS_FILEUNCHANGED) result->include_level--; else cfg->include_level--; @@ -1273,23 +1418,7 @@ struct ast_config *ast_config_internal_load(const char *filename, struct ast_con return result; } -struct ast_config *ast_config_load(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, 0); - if (!result) - ast_config_destroy(cfg); - - return result; -} - -struct ast_config *ast_config_load_with_comments(const char *filename) +struct ast_config *ast_config_load(const char *filename, struct ast_flags flags) { struct ast_config *cfg; struct ast_config *result; @@ -1298,8 +1427,8 @@ struct ast_config *ast_config_load_with_comments(const char *filename) if (!cfg) return NULL; - result = ast_config_internal_load(filename, cfg, 1); - if (!result) + result = ast_config_internal_load(filename, cfg, flags); + if (!result || result == CONFIG_STATUS_FILEUNCHANGED) ast_config_destroy(cfg); return result; diff --git a/main/dnsmgr.c b/main/dnsmgr.c index d3eb9a50f..d1e5dd30b 100644 --- a/main/dnsmgr.c +++ b/main/dnsmgr.c @@ -349,12 +349,16 @@ int dnsmgr_reload(void) static int do_reload(int loading) { struct ast_config *config; + struct ast_flags config_flags = { loading ? 0 : CONFIG_FLAG_FILEUNCHANGED }; const char *interval_value; const char *enabled_value; int interval; int was_enabled; int res = -1; + if ((config = ast_config_load("dnsmgr.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; + /* ensure that no refresh cycles run while the reload is in progress */ ast_mutex_lock(&refresh_lock); @@ -366,7 +370,7 @@ static int do_reload(int loading) if (refresh_sched > -1) ast_sched_del(sched, refresh_sched); - if ((config = ast_config_load("dnsmgr.conf"))) { + if (config) { if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { enabled = ast_true(enabled_value); } diff --git a/main/enum.c b/main/enum.c index cf298a655..9e771b948 100644 --- a/main/enum.c +++ b/main/enum.c @@ -605,11 +605,15 @@ static struct enum_search *enum_newtoplev(char *s) } /*! \brief Initialize the ENUM support subsystem */ -int ast_enum_init(void) +static int private_enum_init(int reload) { struct ast_config *cfg; struct enum_search *s, *sl; struct ast_variable *v; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load("enum.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; /* Destroy existing list */ ast_mutex_lock(&enumlock); @@ -620,7 +624,6 @@ int ast_enum_init(void) ast_free(sl); } toplevs = NULL; - cfg = ast_config_load("enum.conf"); if (cfg) { sl = NULL; v = ast_variable_browse(cfg, "general"); @@ -646,7 +649,12 @@ int ast_enum_init(void) return 0; } +int ast_enum_init(void) +{ + return private_enum_init(0); +} + int ast_enum_reload(void) { - return ast_enum_init(); + return private_enum_init(1); } diff --git a/main/http.c b/main/http.c index b61858cde..b4aac2636 100644 --- a/main/http.c +++ b/main/http.c @@ -1134,6 +1134,10 @@ static int __ast_http_load(int reload) char newprefix[MAX_PREFIX]; int have_sslbindaddr = 0; struct http_uri_redirect *redirect; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load("http.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; /* default values */ memset(&http_desc.sin, 0, sizeof(http_desc.sin)); @@ -1159,7 +1163,6 @@ static int __ast_http_load(int reload) destroy_post_mappings(); - cfg = ast_config_load("http.conf"); if (cfg) { v = ast_variable_browse(cfg, "general"); for (; v; v = v->next) { diff --git a/main/loader.c b/main/loader.c index f3db6841c..359d7323c 100644 --- a/main/loader.c +++ b/main/loader.c @@ -731,6 +731,7 @@ int load_modules(unsigned int preload_only) unsigned int load_count; struct load_order load_order; int res = 0; + struct ast_flags config_flags = { 0 }; #if LOADABLE_MODULES struct dirent *dirent; DIR *dir; @@ -745,7 +746,7 @@ int load_modules(unsigned int preload_only) AST_LIST_LOCK(&module_list); - if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) { + if (!(cfg = ast_config_load(AST_MODULE_CONFIG, config_flags))) { ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); goto done; } diff --git a/main/logger.c b/main/logger.c index 209da2167..fff798aee 100644 --- a/main/logger.c +++ b/main/logger.c @@ -305,12 +305,16 @@ static struct logchannel *make_logchannel(char *channel, char *components, int l return chan; } -static void init_logger_chain(void) +static void init_logger_chain(int reload) { struct logchannel *chan; struct ast_config *cfg; struct ast_variable *var; const char *s; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load("logger.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return; /* delete our list of log channels */ AST_RWLIST_WRLOCK(&logchannels); @@ -323,8 +327,6 @@ static void init_logger_chain(void) /* close syslog */ closelog(); - cfg = ast_config_load("logger.conf"); - /* If no config file, we're fine, set default options. */ if (!cfg) { if (errno) @@ -454,7 +456,7 @@ int reload_logger(int rotate) filesize_reload_needed = 0; - init_logger_chain(); + init_logger_chain(1); if (logfiles.event_log) { snprintf(old, sizeof(old), "%s/%s", ast_config_AST_LOG_DIR, EVENTLOG); @@ -802,7 +804,7 @@ int init_logger(void) ast_mkdir(ast_config_AST_LOG_DIR, 0777); /* create log channels */ - init_logger_chain(); + init_logger_chain(0); /* create the eventlog */ if (logfiles.event_log) { diff --git a/main/manager.c b/main/manager.c index 69c809204..9abb6c5b1 100644 --- a/main/manager.c +++ b/main/manager.c @@ -954,6 +954,7 @@ static int authenticate(struct mansession *s, const struct message *m) struct ast_ha *ha = NULL; char *password = NULL; int readperm = 0, writeperm = 0; + struct ast_flags config_flags = { 0 }; if (ast_strlen_zero(user)) /* missing username */ return -1; @@ -964,7 +965,7 @@ static int authenticate(struct mansession *s, const struct message *m) * suffices to call get_manager_by_name_locked() to fetch * the user's entry. */ - struct ast_config *cfg = ast_config_load("manager.conf"); + struct ast_config *cfg = ast_config_load("manager.conf", config_flags); char *cat = NULL; struct ast_variable *v; @@ -1001,7 +1002,7 @@ static int authenticate(struct mansession *s, const struct message *m) if (!cat) { /* Didn't find the user in manager.conf, check users.conf */ int hasmanager = 0; - cfg = ast_config_load("users.conf"); + cfg = ast_config_load("users.conf", config_flags); if (!cfg) return -1; while ( (cat = ast_category_browse(cfg, cat)) ) { @@ -1117,12 +1118,13 @@ static int action_getconfig(struct mansession *s, const struct message *m) int lineno = 0; char *category=NULL; struct ast_variable *v; + struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; if (ast_strlen_zero(fn)) { astman_send_error(s, m, "Filename not specified"); return 0; } - if (!(cfg = ast_config_load_with_comments(fn))) { + if (!(cfg = ast_config_load(fn, config_flags))) { astman_send_error(s, m, "Config file not found"); return 0; } @@ -1167,13 +1169,14 @@ static int action_getconfigjson(struct mansession *s, const struct message *m) int comma1 = 0; char *buf = NULL; unsigned int buf_len = 0; + struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; if (ast_strlen_zero(fn)) { astman_send_error(s, m, "Filename not specified"); return 0; } - if (!(cfg = ast_config_load_with_comments(fn))) { + if (!(cfg = ast_config_load(fn, config_flags))) { astman_send_error(s, m, "Config file not found"); return 0; } @@ -1302,12 +1305,13 @@ static int action_updateconfig(struct mansession *s, const struct message *m) const char *dfn = astman_get_header(m, "DstFilename"); int res; const char *rld = astman_get_header(m, "Reload"); + struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) { astman_send_error(s, m, "Filename not specified"); return 0; } - if (!(cfg = ast_config_load_with_comments(sfn))) { + if (!(cfg = ast_config_load(sfn, config_flags))) { astman_send_error(s, m, "Config file not found"); return 0; } @@ -3246,7 +3250,7 @@ static struct server_args amis_desc = { .worker_fn = session_do, /* thread handling the session */ }; -int init_manager(void) +static int __init_manager(int reload) { struct ast_config *cfg = NULL; const char *val; @@ -3257,6 +3261,7 @@ int init_manager(void) struct ast_hostent ahp; struct ast_manager_user *user = NULL; struct ast_variable *var; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; if (!registered) { /* Register default actions */ @@ -3292,8 +3297,10 @@ int init_manager(void) /* Append placeholder event so master_eventq never runs dry */ append_event("Event: Placeholder\r\n\r\n", 0); } + if ((cfg = ast_config_load("manager.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; + displayconnects = 1; - cfg = ast_config_load("manager.conf"); if (!cfg) { ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); return 0; @@ -3474,8 +3481,13 @@ int init_manager(void) return 0; } +int init_manager(void) +{ + return __init_manager(0); +} + int reload_manager(void) { manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); - return init_manager(); + return __init_manager(1); } diff --git a/main/rtp.c b/main/rtp.c index 7f81ed7cf..2ff4440f0 100644 --- a/main/rtp.c +++ b/main/rtp.c @@ -3997,15 +3997,18 @@ static struct ast_cli_entry cli_rtp[] = { stun_no_debug_usage }, }; -int ast_rtp_reload(void) +static int __ast_rtp_reload(int reload) { struct ast_config *cfg; const char *s; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load("rtp.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; rtpstart = 5000; rtpend = 31000; dtmftimeout = DEFAULT_DTMF_TIMEOUT; - cfg = ast_config_load("rtp.conf"); if (cfg) { if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { rtpstart = atoi(s); @@ -4060,10 +4063,15 @@ int ast_rtp_reload(void) return 0; } +int ast_rtp_reload(void) +{ + return __ast_rtp_reload(1); +} + /*! \brief Initialize the RTP system in Asterisk */ void ast_rtp_init(void) { ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); - ast_rtp_reload(); + __ast_rtp_reload(0); } diff --git a/main/udptl.c b/main/udptl.c index 2385679a8..d3c6163e7 100644 --- a/main/udptl.c +++ b/main/udptl.c @@ -1183,10 +1183,14 @@ static struct ast_cli_entry cli_udptl[] = { nodebug_usage }, }; -void ast_udptl_reload(void) +static void __ast_udptl_reload(int reload) { struct ast_config *cfg; const char *s; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load("udptl.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return; udptlstart = 4500; udptlend = 4999; @@ -1195,7 +1199,7 @@ void ast_udptl_reload(void) udptlfecspan = 0; udptlmaxdatagram = 0; - if ((cfg = ast_config_load("udptl.conf"))) { + if (cfg) { if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { udptlstart = atoi(s); if (udptlstart < 1024) @@ -1258,8 +1262,13 @@ void ast_udptl_reload(void) ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); } +void ast_udptl_reload(void) +{ + __ast_udptl_reload(1); +} + void ast_udptl_init(void) { ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry)); - ast_udptl_reload(); + __ast_udptl_reload(0); } diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c index a6b4e0171..77862d0c1 100644 --- a/pbx/pbx_config.c +++ b/pbx/pbx_config.c @@ -722,6 +722,7 @@ static int handle_save_dialplan(int fd, int argc, char *argv[]) struct ast_variable *v; int incomplete = 0; /* incomplete config write? */ FILE *output; + struct ast_flags config_flags = { 0 }; const char *base, *slash, *file; @@ -761,7 +762,7 @@ static int handle_save_dialplan(int fd, int argc, char *argv[]) } snprintf(filename, sizeof(filename), "%s%s%s", base, slash, config); - cfg = ast_config_load("extensions.conf"); + cfg = ast_config_load("extensions.conf", config_flags); /* try to lock contexts list */ if (ast_rdlock_contexts()) { @@ -1329,8 +1330,9 @@ static int pbx_load_config(const char *config_file) struct ast_variable *v; const char *cxt; const char *aft; + struct ast_flags config_flags = { 0 }; - cfg = ast_config_load(config_file); + cfg = ast_config_load(config_file, config_flags); if (!cfg) return 0; @@ -1501,8 +1503,9 @@ static void pbx_load_users(void) int hasvoicemail; int start, finish, x; struct ast_context *con; + struct ast_flags config_flags = { 0 }; - cfg = ast_config_load("users.conf"); + cfg = ast_config_load("users.conf", config_flags); if (!cfg) return; con = ast_context_find_or_create(&local_contexts, userscontext, registrar); diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c index c077f4d5d..7d3fd82c1 100644 --- a/pbx/pbx_dundi.c +++ b/pbx/pbx_dundi.c @@ -4555,13 +4555,14 @@ static struct ast_switch dundi_switch = matchmore: dundi_matchmore, }; -static int set_config(char *config_file, struct sockaddr_in* sin) +static int set_config(char *config_file, struct sockaddr_in* sin, int reload) { struct ast_config *cfg; struct ast_variable *v; char *cat; int format; int x; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; char hn[MAXHOSTNAMELEN] = ""; struct ast_hostent he; struct hostent *hp; @@ -4570,11 +4571,12 @@ static int set_config(char *config_file, struct sockaddr_in* sin) int globalpcmodel = 0; dundi_eid testeid; + if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; + dundi_ttl = DUNDI_DEFAULT_TTL; dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME; - cfg = ast_config_load(config_file); - - + if (!cfg) { ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); return -1; @@ -4741,7 +4743,7 @@ static int reload(void) { struct sockaddr_in sin; - if (set_config("dundi.conf", &sin)) + if (set_config("dundi.conf", &sin, 1)) return -1; return 0; @@ -4765,7 +4767,7 @@ static int load_module(void) if (!io || !sched) return AST_MODULE_LOAD_FAILURE; - if (set_config("dundi.conf", &sin)) + if (set_config("dundi.conf", &sin, 0)) return AST_MODULE_LOAD_DECLINE; netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); diff --git a/res/res_adsi.c b/res/res_adsi.c index 28ff200e4..21f1d89fa 100644 --- a/res/res_adsi.c +++ b/res/res_adsi.c @@ -1067,9 +1067,10 @@ static void adsi_load(void) int x; struct ast_config *conf; struct ast_variable *v; + struct ast_flags config_flags = { 0 }; char *name, *sname; init_state(); - conf = ast_config_load("adsi.conf"); + conf = ast_config_load("adsi.conf", config_flags); if (conf) { x=0; for (v = ast_variable_browse(conf, "intro"); v; v = v->next) { diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c index 5a9ad5cd0..6388ab72b 100644 --- a/res/res_config_odbc.c +++ b/res/res_config_odbc.c @@ -486,7 +486,7 @@ static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data) return sth; } -static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments) +static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags) { struct ast_variable *new_v; struct ast_category *cur_cat; @@ -500,6 +500,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c SQLHSTMT stmt; char last[128] = ""; struct config_odbc_obj q; + struct ast_flags loader_flags = { 0 }; memset(&q, 0, sizeof(q)); @@ -542,7 +543,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c while ((res = SQLFetch(stmt)) != SQL_NO_DATA) { if (!strcmp (q.var_name, "#include")) { - if (!ast_config_internal_load(q.var_val, cfg, 0)) { + if (!ast_config_internal_load(q.var_val, cfg, loader_flags)) { SQLFreeHandle(SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); return NULL; diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c index 2fb0a0e38..c3e9777c2 100644 --- a/res/res_config_pgsql.c +++ b/res/res_config_pgsql.c @@ -62,7 +62,7 @@ static char dbsock[MAX_DB_OPTION_SIZE] = ""; static int dbport = 5432; static time_t connect_time = 0; -static int parse_config(void); +static int parse_config(int reload); static int pgsql_reconnect(const char *database); static int realtime_pgsql_status(int fd, int argc, char **argv); @@ -431,7 +431,7 @@ static int update_pgsql(const char *database, const char *table, const char *key static struct ast_config *config_pgsql(const char *database, const char *table, const char *file, struct ast_config *cfg, - int withcomments) + struct ast_flags flags) { PGresult *result = NULL; long num_rows; @@ -496,7 +496,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table, char *field_var_val = PQgetvalue(result, rowIndex, 2); char *field_cat_metric = PQgetvalue(result, rowIndex, 3); if (!strcmp(field_var_name, "#include")) { - if (!ast_config_internal_load(field_var_val, cfg, 0)) { + if (!ast_config_internal_load(field_var_val, cfg, flags)) { PQclear(result); ast_mutex_unlock(&pgsql_lock); return NULL; @@ -536,35 +536,25 @@ static struct ast_config_engine pgsql_engine = { static int load_module(void) { - if(!parse_config()) + if(!parse_config(0)) return AST_MODULE_LOAD_DECLINE; - ast_mutex_lock(&pgsql_lock); - - if (!pgsql_reconnect(NULL)) { - ast_log(LOG_WARNING, - "Postgresql RealTime: Couldn't establish connection. Check debug.\n"); - ast_debug(1, "Postgresql RealTime: Cannot Connect: %s\n", PQerrorMessage(pgsqlConn)); - } - ast_config_engine_register(&pgsql_engine); ast_verb(1, "Postgresql RealTime driver loaded.\n"); ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry)); - ast_mutex_unlock(&pgsql_lock); - return 0; } static int unload_module(void) { - /* Aquire control before doing anything to the module itself. */ + /* Acquire control before doing anything to the module itself. */ ast_mutex_lock(&pgsql_lock); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; - }; + } ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry)); ast_config_engine_deregister(&pgsql_engine); ast_verb(1, "Postgresql RealTime unloaded.\n"); @@ -577,40 +567,32 @@ static int unload_module(void) static int reload(void) { - /* Aquire control before doing anything to the module itself. */ - ast_mutex_lock(&pgsql_lock); - - if (pgsqlConn) { - PQfinish(pgsqlConn); - pgsqlConn = NULL; - }; - parse_config(); - - if (!pgsql_reconnect(NULL)) { - ast_log(LOG_WARNING, - "Postgresql RealTime: Couldn't establish connection. Check debug.\n"); - ast_debug(1, "Postgresql RealTime: Cannot Connect: %s\n", PQerrorMessage(pgsqlConn)); - } - - ast_verb(2, "Postgresql RealTime reloaded.\n"); - - /* Done reloading. Release lock so others can now use driver. */ - ast_mutex_unlock(&pgsql_lock); + parse_config(1); return 0; } -static int parse_config(void) +static int parse_config(int reload) { struct ast_config *config; const char *s; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - config = ast_config_load(RES_CONFIG_PGSQL_CONF); + if ((config = ast_config_load(RES_CONFIG_PGSQL_CONF, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return 0; if (!config) { - ast_log(LOG_WARNING, "Unable to load config %s\n",RES_CONFIG_PGSQL_CONF); + ast_log(LOG_WARNING, "Unable to load config %s\n", RES_CONFIG_PGSQL_CONF); return 0; } + + ast_mutex_lock(&pgsql_lock); + + if (pgsqlConn) { + PQfinish(pgsqlConn); + pgsqlConn = NULL; + } + if (!(s = ast_variable_retrieve(config, "general", "dbuser"))) { ast_log(LOG_WARNING, "Postgresql RealTime: No database user found, using 'asterisk' as default.\n"); @@ -672,6 +654,17 @@ static int parse_config(void) ast_debug(1, "Postgresql RealTime DBName: %s\n", dbname); } + if (!pgsql_reconnect(NULL)) { + ast_log(LOG_WARNING, + "Postgresql RealTime: Couldn't establish connection. Check debug.\n"); + ast_debug(1, "Postgresql RealTime: Cannot Connect: %s\n", PQerrorMessage(pgsqlConn)); + } + + ast_verb(2, "Postgresql RealTime reloaded.\n"); + + /* Done reloading. Release lock so others can now use driver. */ + ast_mutex_unlock(&pgsql_lock); + return 1; } diff --git a/res/res_config_sqlite.c b/res/res_config_sqlite.c index c9c65f881..fd28ef62d 100644 --- a/res/res_config_sqlite.c +++ b/res/res_config_sqlite.c @@ -300,14 +300,14 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames); * \param table the table to use * \param file the file to load from the database * \param cfg the struct ast_config object to use when storing variables - * \param withcomments Integer. Flag + * \param flags Optional flags. Not used. * \retval cfg object * \retval NULL if an error occurred * \see add_cfg_entry() */ static struct ast_config * config_handler(const char *database, const char *table, const char *file, - struct ast_config *cfg, int withcomments); + struct ast_config *cfg, struct ast_flags flags); /*! * \brief Helper function to parse a va_list object into 2 dynamic arrays of @@ -611,8 +611,9 @@ static int load_config(void) struct ast_config *config; struct ast_variable *var; int error; + struct ast_flags config_flags = { 0 }; - config = ast_config_load(RES_SQLITE_CONF_FILE); + config = ast_config_load(RES_SQLITE_CONF_FILE, config_flags); if (!config) { ast_log(LOG_ERROR, "Unable to load " RES_SQLITE_CONF_FILE "\n"); @@ -725,7 +726,7 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames) } static struct ast_config *config_handler(const char *database, - const char *table, const char *file, struct ast_config *cfg, int withcomments) + const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags) { struct cfg_entry_args args; char *errormsg; diff --git a/res/res_features.c b/res/res_features.c index 70cf1ec81..08cedc071 100644 --- a/res/res_features.c +++ b/res/res_features.c @@ -2768,6 +2768,7 @@ static int load_config(void) struct ast_config *cfg = NULL; struct ast_variable *var = NULL; struct feature_group *fg = NULL; + struct ast_flags config_flags = { 0 }; char old_parking_ext[AST_MAX_EXTENSION]; char old_parking_con[AST_MAX_EXTENSION] = ""; char *ctg; @@ -2810,7 +2811,7 @@ static int load_config(void) atxferdropcall = DEFAULT_ATXFER_DROP_CALL; atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES; - cfg = ast_config_load("features.conf"); + cfg = ast_config_load("features.conf", config_flags); if (!cfg) { ast_log(LOG_WARNING,"Could not load features.conf\n"); return AST_MODULE_LOAD_DECLINE; diff --git a/res/res_indications.c b/res/res_indications.c index 2a4f38a3a..e12b6f9a1 100644 --- a/res/res_indications.c +++ b/res/res_indications.c @@ -236,7 +236,7 @@ static int handle_stopplaytones(struct ast_channel *chan, void *data) } /*! \brief load indications module */ -static int ind_load_module(void) +static int ind_load_module(int reload) { struct ast_config *cfg; struct ast_variable *v; @@ -244,12 +244,18 @@ static int ind_load_module(void) char *c; struct ind_tone_zone *tones; const char *country = NULL; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; /* that the following cast is needed, is yuk! */ /* yup, checked it out. It is NOT written to. */ - cfg = ast_config_load((char *)config); + cfg = ast_config_load((char *)config, config_flags); if (!cfg) return -1; + else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + return 0; + + if (reload) + ast_unregister_indication_country(NULL); /* Use existing config to populate the Indication table */ cxt = ast_category_browse(cfg, NULL); @@ -385,7 +391,7 @@ static int unload_module(void) /*! \brief Load indications module */ static int load_module(void) { - if (ind_load_module()) + if (ind_load_module(0)) return AST_MODULE_LOAD_DECLINE; ast_cli_register_multiple(cli_indications, sizeof(cli_indications) / sizeof(struct ast_cli_entry)); ast_register_application("PlayTones", handle_playtones, "Play a tone list", playtones_desc); @@ -397,10 +403,7 @@ static int load_module(void) /*! \brief Reload indications module */ static int reload(void) { - /* remove the registed indications... */ - ast_unregister_indication_country(NULL); - - return ind_load_module(); + return ind_load_module(1); } AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Region-specific tones", diff --git a/res/res_jabber.c b/res/res_jabber.c index 6653efec5..8410bf2c0 100644 --- a/res/res_jabber.c +++ b/res/res_jabber.c @@ -94,8 +94,8 @@ static int aji_test(int fd, int argc, char *argv[]); static int aji_show_clients(int fd, int argc, char *argv[]); static int aji_create_client(char *label, struct ast_variable *var, int debug); static int aji_create_buddy(char *label, struct aji_client *client); -static int aji_reload(void); -static int aji_load_config(void); +static int aji_reload(int reload); +static int aji_load_config(int reload); static void aji_pruneregister(struct aji_client *client); static int aji_filter_roster(void *data, ikspak *pak); static int aji_get_roster(struct aji_client *client); @@ -2062,7 +2062,7 @@ static int aji_do_debug(int fd, int argc, char *argv[]) */ static int aji_do_reload(int fd, int argc, char *argv[]) { - aji_reload(); + aji_reload(1); ast_cli(fd, "Jabber Reloaded.\n"); return RESULT_SUCCESS; } @@ -2398,17 +2398,20 @@ static int aji_create_buddy(char *label, struct aji_client *client) } /*!< load config file. \return 1. */ -static int aji_load_config(void) +static int aji_load_config(int reload) { char *cat = NULL; int debug = 1; struct ast_config *cfg = NULL; struct ast_variable *var = NULL; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + + if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) + return -1; /* Reset flags to default value */ ast_set_flag(&globalflags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); - cfg = ast_config_load(JABBER_CONFIG); if (!cfg) { ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); return 0; @@ -2508,13 +2511,17 @@ static int manager_jabber_send(struct mansession *s, const struct message *m) } /*! \brief Reload the jabber module */ -static int aji_reload() +static int aji_reload(int reload) { + int res; + ASTOBJ_CONTAINER_MARKALL(&clients); - if (!aji_load_config()) { + if (!(res = aji_load_config(reload))) { ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); return 0; - } + } else if (res == -1) + return 1; + ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { ASTOBJ_RDLOCK(iterator); @@ -2566,7 +2573,7 @@ static int unload_module(void) static int load_module(void) { ASTOBJ_CONTAINER_INIT(&clients); - if(!aji_reload()) + if(!aji_reload(0)) return AST_MODULE_LOAD_DECLINE; ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send, "Sends a message to a Jabber Client", mandescr_jabber_send); @@ -2580,7 +2587,7 @@ static int load_module(void) /*! \brief Wrapper for aji_reload */ static int reload(void) { - aji_reload(); + aji_reload(1); return 0; } diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 0aa3cc595..9a66b7518 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -1013,10 +1013,11 @@ static int load_moh_classes(int reload) struct mohclass *class; char *cat; int numclasses = 0; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - cfg = ast_config_load("musiconhold.conf"); + cfg = ast_config_load("musiconhold.conf", config_flags); - if (!cfg) + if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED) return 0; cat = ast_category_browse(cfg, NULL); diff --git a/res/res_odbc.c b/res/res_odbc.c index 6b70f16f6..c9d3ee700 100644 --- a/res/res_odbc.c +++ b/res/res_odbc.c @@ -213,10 +213,11 @@ static int load_odbc_config(void) char *cat, *dsn, *username, *password, *sanitysql; int enabled, pooling, limit; int connect = 0, res = 0; + struct ast_flags config_flags = { 0 }; struct odbc_class *new; - config = ast_config_load(cfg); + config = ast_config_load(cfg, config_flags); if (!config) { ast_log(LOG_WARNING, "Unable to load config file res_odbc.conf\n"); return -1; @@ -538,6 +539,7 @@ static int reload(void) char *cat, *dsn, *username, *password, *sanitysql; int enabled, pooling, limit; int connect = 0, res = 0; + struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; struct odbc_class *new, *class; struct odbc_obj *current; @@ -548,8 +550,8 @@ static int reload(void) class->delme = 1; } - config = ast_config_load(cfg); - if (config) { + config = ast_config_load(cfg, config_flags); + if (config != NULL && config != CONFIG_STATUS_FILEUNCHANGED) { for (cat = ast_category_browse(config, NULL); cat; cat=ast_category_browse(config, cat)) { if (!strcasecmp(cat, "ENV")) { for (v = ast_variable_browse(config, cat); v; v = v->next) { diff --git a/res/res_smdi.c b/res/res_smdi.c index f1f1b193e..01a6404a2 100644 --- a/res/res_smdi.c +++ b/res/res_smdi.c @@ -513,6 +513,7 @@ static int smdi_load(int reload) struct ast_config *conf; struct ast_variable *v; struct ast_smdi_interface *iface = NULL; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; int res = 0; /* Config options */ @@ -524,13 +525,14 @@ static int smdi_load(int reload) int msdstrip = 0; /* strip zero digits */ long msg_expiry = SMDI_MSG_EXPIRY_TIME; - if (!(conf = ast_config_load(config_file))) { + if (!(conf = ast_config_load(config_file, config_flags))) { if (reload) ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file); else ast_log(LOG_NOTICE, "Unable to load config %s: SMDI disabled\n", config_file); return 1; - } + } else if (conf == CONFIG_STATUS_FILEUNCHANGED) + return 0; /* Mark all interfaces that we are listening on. We will unmark them * as we find them in the config file, this way we know any interfaces diff --git a/res/res_snmp.c b/res/res_snmp.c index 05c483ec5..1fac2c31e 100644 --- a/res/res_snmp.c +++ b/res/res_snmp.c @@ -48,11 +48,12 @@ static int load_config(void) { struct ast_variable *var; struct ast_config *cfg; + struct ast_flags config_flags = { 0 }; char *cat; res_snmp_enabled = 0; res_snmp_agentx_subagent = 1; - cfg = ast_config_load("res_snmp.conf"); + cfg = ast_config_load("res_snmp.conf", config_flags); if (!cfg) { ast_log(LOG_WARNING, "Could not load res_snmp.conf\n"); return 0; |