#ifdef HAVE_CONFIG_H # include #endif #undef alloca #ifdef HAVE_ALLOCA_H # include #elif defined __GNUC__ # define alloca __builtin_alloca #elif defined _AIX # define alloca __alloca #elif defined _MSC_VER # include # define alloca _alloca #else # include # ifdef __cplusplus extern "C" # endif void *alloca (size_t); #endif #include /* define macros and variable for using the eina logging system */ #define EFREET_MODULE_LOG_DOM _efreet_base_log_dom static int _efreet_base_log_dom = -1; #include "Efreet.h" #include "efreet_private.h" static Efreet_Version _version = { VMAJ, VMIN, VMIC, VREV }; EAPI Efreet_Version *efreet_version = &_version; #ifdef _WIN32 # define EFREET_PATH_SEP ';' #else # define EFREET_PATH_SEP ':' #endif static const char *efreet_home_dir = NULL; static const char *xdg_data_home = NULL; static const char *xdg_config_home = NULL; static const char *xdg_cache_home = NULL; static Eina_List *xdg_data_dirs = NULL; static Eina_List *xdg_config_dirs = NULL; static const char *xdg_desktop_dir = NULL; static const char *hostname = NULL; static const char *efreet_dir_get(const char *key, const char *fallback); static Eina_List *efreet_dirs_get(const char *key, const char *fallback); /** * @internal * @return Returns @c 1 on success or @c 0 on failure * @brief Initializes the efreet base settings */ int efreet_base_init(void) { _efreet_base_log_dom = eina_log_domain_register ("efreet_base", EFREET_DEFAULT_LOG_COLOR); if (_efreet_base_log_dom < 0) { EINA_LOG_ERR("Efreet: Could not create a log domain for efreet_base.\n"); return 0; } return 1; } /** * @internal * @return Returns no value * @brief Cleans up the efreet base settings system */ void efreet_base_shutdown(void) { IF_RELEASE(efreet_home_dir); IF_RELEASE(xdg_desktop_dir); IF_RELEASE(xdg_data_home); IF_RELEASE(xdg_config_home); IF_RELEASE(xdg_cache_home); IF_FREE_LIST(xdg_data_dirs, eina_stringshare_del); IF_FREE_LIST(xdg_config_dirs, eina_stringshare_del); IF_RELEASE(hostname); eina_log_domain_unregister(_efreet_base_log_dom); _efreet_base_log_dom = -1; } /** * @internal * @return Returns the users home directory * @brief Gets the users home directory and returns it. */ const char * efreet_home_dir_get(void) { if (efreet_home_dir) return efreet_home_dir; efreet_home_dir = getenv("HOME"); #ifdef _WIN32 if (!efreet_home_dir || efreet_home_dir[0] == '\0') efreet_home_dir = getenv("USERPROFILE"); #endif if (!efreet_home_dir || efreet_home_dir[0] == '\0') efreet_home_dir = "/tmp"; efreet_home_dir = eina_stringshare_add(efreet_home_dir); return efreet_home_dir; } EAPI const char * efreet_desktop_dir_get(void) { if (xdg_desktop_dir) return xdg_desktop_dir; xdg_desktop_dir = efreet_dir_get("XDG_DESKTOP_DIR", _("/Desktop")); return xdg_desktop_dir; } EAPI const char * efreet_data_home_get(void) { if (xdg_data_home) return xdg_data_home; xdg_data_home = efreet_dir_get("XDG_DATA_HOME", "/.local/share"); return xdg_data_home; } EAPI Eina_List * efreet_data_dirs_get(void) { #ifdef _WIN32 char buf[4096]; #endif if (xdg_data_dirs) return xdg_data_dirs; #ifdef _WIN32 snprintf(buf, 4096, "%s\\Efl;" PACKAGE_DATA_DIR ";/usr/share;/usr/local/share", getenv("APPDATA")); xdg_data_dirs = efreet_dirs_get("XDG_DATA_DIRS", buf); #else xdg_data_dirs = efreet_dirs_get("XDG_DATA_DIRS", PACKAGE_DATA_DIR ":/usr/share:/usr/local/share"); #endif return xdg_data_dirs; } EAPI const char * efreet_config_home_get(void) { if (xdg_config_home) return xdg_config_home; xdg_config_home = efreet_dir_get("XDG_CONFIG_HOME", "/.config"); return xdg_config_home; } EAPI Eina_List * efreet_config_dirs_get(void) { if (xdg_config_dirs) return xdg_config_dirs; xdg_config_dirs = efreet_dirs_get("XDG_CONFIG_DIRS", "/etc/xdg"); return xdg_config_dirs; } EAPI const char * efreet_cache_home_get(void) { if (xdg_cache_home) return xdg_cache_home; xdg_cache_home = efreet_dir_get("XDG_CACHE_HOME", "/.cache"); return xdg_cache_home; } EAPI const char * efreet_hostname_get(void) { char buf[256]; if (hostname) return hostname; if (gethostname(buf, sizeof(buf)) < 0) hostname = eina_stringshare_add(""); else hostname = eina_stringshare_add(buf); return hostname; } void efreet_dirs_reset(void) { eina_stringshare_replace(&xdg_desktop_dir, NULL); } /** * @internal * @param key The environment key to lookup * @param fallback The fallback value to use * @return Returns the directory related to the given key or the fallback * @brief This tries to determine the correct directory name given the * environment key @a key and fallbacks @a fallback. */ static const char * efreet_dir_get(const char *key, const char *fallback) { char *dir; const char *t; dir = getenv(key); if (!dir || dir[0] == '\0') { int len; const char *user; user = efreet_home_dir_get(); len = strlen(user) + strlen(fallback) + 1; dir = malloc(len); if (!dir) return NULL; snprintf(dir, len, "%s%s", user, fallback); t = eina_stringshare_add(dir); FREE(dir); } else t = eina_stringshare_add(dir); return t; } /** * @internal * @param key The environment key to lookup * @param fallback The fallback value to use * @return Returns a list of directories specified by the given key @a key * or from the list of fallbacks in @a fallback. * @brief Creates a list of directories as given in the environment key @a * key or from the fallbacks in @a fallback */ static Eina_List * efreet_dirs_get(const char *key, const char *fallback) { Eina_List *dirs = NULL; const char *path; char *tmp, *s, *p; char ts[PATH_MAX]; size_t len; path = getenv(key); if (!path || (path[0] == '\0')) path = fallback; if (!path) return dirs; len = strlen(path) + 1; tmp = alloca(len); memcpy(tmp, path, len); s = tmp; p = strchr(s, EFREET_PATH_SEP); while (p) { *p = '\0'; if (!eina_list_search_unsorted(dirs, EINA_COMPARE_CB(strcmp), s)) { // resolve path properly/fully to remove path//path2 to // path/path2, path/./path2 to path/path2 etc. if (realpath(s, ts)) dirs = eina_list_append(dirs, (void *)eina_stringshare_add(ts)); } s = ++p; p = strchr(s, EFREET_PATH_SEP); } if (!eina_list_search_unsorted(dirs, EINA_COMPARE_CB(strcmp), s)) { // resolve path properly/fully to remove path//path2 to // path/path2, path/./path2 to path/path2 etc. if (realpath(s, ts)) dirs = eina_list_append(dirs, (void *)eina_stringshare_add(ts)); } return dirs; }