paulo@0: /* paulo@0: * $Id: gt_conf.c,v 1.4 2004/03/24 06:27:40 hipnod Exp $ paulo@0: * paulo@0: * Copyright (C) 2003 giFT project (gift.sourceforge.net) paulo@0: * paulo@0: * This program is free software; you can redistribute it and/or modify it paulo@0: * under the terms of the GNU General Public License as published by the paulo@0: * Free Software Foundation; either version 2, or (at your option) any paulo@0: * later version. paulo@0: * paulo@0: * This program is distributed in the hope that it will be useful, but paulo@0: * WITHOUT ANY WARRANTY; without even the implied warranty of paulo@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU paulo@0: * General Public License for more details. paulo@0: */ paulo@0: paulo@0: #include "gt_gnutella.h" paulo@0: #include "gt_conf.h" paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: #define CHECK_CONFIG_INTERVAL (1 * MINUTES) paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: static Config *gt_conf; paulo@0: paulo@0: static char *conf_path; paulo@0: static time_t conf_mtime; paulo@0: paulo@0: static Dataset *cache; paulo@0: paulo@0: static timer_id refresh_timer; paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: static char *get_key (const char *key_str) paulo@0: { paulo@0: char *str; paulo@0: char *key; paulo@0: paulo@0: if (!(str = STRDUP (key_str))) paulo@0: return NULL; paulo@0: paulo@0: key = string_sep (&str, "="); paulo@0: return key; paulo@0: } paulo@0: paulo@0: static char *cache_lookup (const char *key_str) paulo@0: { paulo@0: char *key; paulo@0: char *data; paulo@0: paulo@0: if (!(key = get_key (key_str))) paulo@0: return NULL; paulo@0: paulo@0: data = dataset_lookupstr (cache, key); paulo@0: free (key); paulo@0: paulo@0: return data; paulo@0: } paulo@0: paulo@0: static void cache_insert (const char *key_str, const char *value) paulo@0: { paulo@0: char *key; paulo@0: paulo@0: if (!(key = get_key (key_str))) paulo@0: return; paulo@0: paulo@0: dataset_insertstr (&cache, key, value); paulo@0: free (key); paulo@0: } paulo@0: paulo@0: char *gt_config_get_str (const char *key) paulo@0: { paulo@0: char *str; paulo@0: char *ret; paulo@0: paulo@0: if (!(str = cache_lookup (key))) paulo@0: str = config_get_str (gt_conf, (char *)key); paulo@0: paulo@0: ret = str; paulo@0: paulo@0: /* unset keys are marked specially by the empty string so paulo@0: * we don't have to call config_get_xxx for them */ paulo@0: if (string_isempty (str)) paulo@0: { paulo@0: ret = NULL; paulo@0: str = ""; paulo@0: } paulo@0: paulo@0: /* hrm, the dataset doesn't handle inserting the same item you lookup paulo@0: * yet, so we can't do the insert unconditionally here.. */ paulo@0: if (str != cache_lookup (key)) paulo@0: cache_insert (key, str); paulo@0: paulo@0: return ret; paulo@0: } paulo@0: paulo@0: int gt_config_get_int (const char *key) paulo@0: { paulo@0: return ATOI (gt_config_get_str (key)); paulo@0: } paulo@0: paulo@0: /* check the mtime on the conf file. If it has changed, reload */ paulo@0: static int refresh_conf (void *udata) paulo@0: { paulo@0: struct stat conf_st; paulo@0: char *path; paulo@0: BOOL ret; paulo@0: paulo@0: path = STRDUP (gift_conf_path (conf_path)); paulo@0: ret = file_stat (path, &conf_st); paulo@0: paulo@0: if (!ret || conf_st.st_mtime != conf_mtime) paulo@0: { paulo@0: GT->DBGFN (GT, "Gnutella.conf changed on disk. flushing cached config"); paulo@0: paulo@0: /* gt_config_get_xxx will reload the cache */ paulo@0: dataset_clear (cache); paulo@0: cache = NULL; paulo@0: paulo@0: conf_mtime = conf_st.st_mtime; paulo@0: } paulo@0: paulo@0: free (path); paulo@0: return TRUE; paulo@0: } paulo@0: paulo@0: BOOL gt_config_load_file (const char *relative_path, BOOL update, BOOL force) paulo@0: { paulo@0: char *src_path; paulo@0: char *dst_path; paulo@0: BOOL src_exists; paulo@0: BOOL dst_exists; paulo@0: struct stat src_st; paulo@0: struct stat dst_st; paulo@0: BOOL ret = TRUE; paulo@0: paulo@0: src_path = STRDUP (stringf ("%s/%s", platform_data_dir(), relative_path)); paulo@0: dst_path = STRDUP (gift_conf_path (relative_path)); paulo@0: paulo@0: src_exists = file_stat (src_path, &src_st); paulo@0: dst_exists = file_stat (dst_path, &dst_st); paulo@0: paulo@0: /* paulo@0: * NOTE: the user may modify the config files in ~/.giFT/Gnutella/. paulo@0: * If so, the mtime there should be greater, so look for an mtime paulo@0: * greater than instead of not equal to the those files. paulo@0: */ paulo@0: if (force || (src_exists && paulo@0: (!dst_exists || src_st.st_mtime > dst_st.st_mtime))) paulo@0: { paulo@0: /* paulo@0: * Copy the default configuration from the data dir paulo@0: * (usually "/usr/local/share/giFT/Gnutella/") paulo@0: */ paulo@0: GT->DBGFN (GT, "reloading configuration for %s (copying %s -> %s)", paulo@0: relative_path, src_path, dst_path); paulo@0: ret = file_cp (src_path, dst_path); paulo@0: } paulo@0: paulo@0: free (dst_path); paulo@0: free (src_path); paulo@0: paulo@0: return ret; paulo@0: } paulo@0: paulo@0: static Config *load_config (const char *relative_path) paulo@0: { paulo@0: Config *conf; paulo@0: char *full_path; paulo@0: paulo@0: full_path = STRDUP (gift_conf_path (relative_path)); paulo@0: paulo@0: if (!(conf = config_new (full_path))) paulo@0: { paulo@0: /* copy the configuration from the data dir */ paulo@0: gt_config_load_file (relative_path, TRUE, TRUE); paulo@0: paulo@0: /* retry loading the configuration */ paulo@0: conf = config_new (full_path); paulo@0: } paulo@0: paulo@0: free (full_path); paulo@0: paulo@0: return conf; paulo@0: } paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: BOOL gt_config_init (void) paulo@0: { paulo@0: struct stat st; paulo@0: paulo@0: refresh_timer = timer_add (CHECK_CONFIG_INTERVAL, paulo@0: (TimerCallback)refresh_conf, NULL); paulo@0: paulo@0: conf_path = STRDUP (stringf ("%s/%s.conf", GT->name, GT->name)); paulo@0: paulo@0: if (file_stat (gift_conf_path (conf_path), &st)) paulo@0: conf_mtime = st.st_mtime; paulo@0: paulo@0: gt_conf = load_config (conf_path); paulo@0: cache = dataset_new (DATASET_HASH); paulo@0: paulo@0: if (!refresh_timer || !conf_path || !gt_conf) paulo@0: return FALSE; paulo@0: paulo@0: return TRUE; paulo@0: } paulo@0: paulo@0: void gt_config_cleanup (void) paulo@0: { paulo@0: dataset_clear (cache); paulo@0: cache = NULL; paulo@0: paulo@0: config_free (gt_conf); paulo@0: gt_conf = NULL; paulo@0: paulo@0: free (conf_path); paulo@0: conf_path = NULL; paulo@0: paulo@0: timer_remove_zero (&refresh_timer); paulo@0: }