9 # define alloca __builtin_alloca
11 # define alloca __alloca
12 #elif defined _MSC_VER
14 # define alloca _alloca
20 void *alloca (size_t);
27 # include <winsock2.h>
30 /* define macros and variable for using the eina logging system */
31 #define EFREET_MODULE_LOG_DOM _efreet_base_log_dom
32 static int _efreet_base_log_dom = -1;
35 #include "efreet_private.h"
37 static Efreet_Version _version = { VMAJ, VMIN, VMIC, VREV };
38 EAPI Efreet_Version *efreet_version = &_version;
41 # define EFREET_PATH_SEP ';'
43 # define EFREET_PATH_SEP ':'
46 static const char *efreet_home_dir = NULL;
47 static const char *xdg_data_home = NULL;
48 static const char *xdg_config_home = NULL;
49 static const char *xdg_cache_home = NULL;
50 static Eina_List *xdg_data_dirs = NULL;
51 static Eina_List *xdg_config_dirs = NULL;
52 static const char *xdg_desktop_dir = NULL;
53 static const char *hostname = NULL;
55 static const char *efreet_dir_get(const char *key, const char *fallback);
56 static Eina_List *efreet_dirs_get(const char *key,
57 const char *fallback);
58 static const char *efreet_user_dir_get(const char *key, const char *fallback);
62 * @return Returns @c 1 on success or @c 0 on failure
63 * @brief Initializes the efreet base settings
66 efreet_base_init(void)
68 _efreet_base_log_dom = eina_log_domain_register
69 ("efreet_base", EFREET_DEFAULT_LOG_COLOR);
70 if (_efreet_base_log_dom < 0)
72 EINA_LOG_ERR("Efreet: Could not create a log domain for efreet_base.\n");
80 * @return Returns no value
81 * @brief Cleans up the efreet base settings system
84 efreet_base_shutdown(void)
86 IF_RELEASE(efreet_home_dir);
87 IF_RELEASE(xdg_desktop_dir);
88 IF_RELEASE(xdg_data_home);
89 IF_RELEASE(xdg_config_home);
90 IF_RELEASE(xdg_cache_home);
92 IF_FREE_LIST(xdg_data_dirs, eina_stringshare_del);
93 IF_FREE_LIST(xdg_config_dirs, eina_stringshare_del);
97 eina_log_domain_unregister(_efreet_base_log_dom);
98 _efreet_base_log_dom = -1;
103 * @return Returns the users home directory
104 * @brief Gets the users home directory and returns it.
107 efreet_home_dir_get(void)
109 if (efreet_home_dir) return efreet_home_dir;
111 efreet_home_dir = getenv("HOME");
113 if (!efreet_home_dir || efreet_home_dir[0] == '\0')
114 efreet_home_dir = getenv("USERPROFILE");
116 if (!efreet_home_dir || efreet_home_dir[0] == '\0')
117 efreet_home_dir = "/tmp";
119 efreet_home_dir = eina_stringshare_add(efreet_home_dir);
121 return efreet_home_dir;
125 efreet_desktop_dir_get(void)
127 if (xdg_desktop_dir) return xdg_desktop_dir;
128 xdg_desktop_dir = efreet_user_dir_get("XDG_DESKTOP_DIR", _("Desktop"));
129 return xdg_desktop_dir;
133 efreet_data_home_get(void)
135 if (xdg_data_home) return xdg_data_home;
136 xdg_data_home = efreet_dir_get("XDG_DATA_HOME", "/.local/share");
137 return xdg_data_home;
141 efreet_data_dirs_get(void)
147 if (xdg_data_dirs) return xdg_data_dirs;
150 snprintf(buf, 4096, "%s\\Efl;" PACKAGE_DATA_DIR ";/usr/share;/usr/local/share", getenv("APPDATA"));
151 xdg_data_dirs = efreet_dirs_get("XDG_DATA_DIRS", buf);
153 xdg_data_dirs = efreet_dirs_get("XDG_DATA_DIRS",
154 PACKAGE_DATA_DIR ":/usr/share:/usr/local/share");
156 return xdg_data_dirs;
160 efreet_config_home_get(void)
162 if (xdg_config_home) return xdg_config_home;
163 xdg_config_home = efreet_dir_get("XDG_CONFIG_HOME", "/.config");
164 return xdg_config_home;
168 efreet_config_dirs_get(void)
170 if (xdg_config_dirs) return xdg_config_dirs;
171 xdg_config_dirs = efreet_dirs_get("XDG_CONFIG_DIRS", "/etc/xdg");
172 return xdg_config_dirs;
176 efreet_cache_home_get(void)
178 if (xdg_cache_home) return xdg_cache_home;
179 xdg_cache_home = efreet_dir_get("XDG_CACHE_HOME", "/.cache");
180 return xdg_cache_home;
184 efreet_hostname_get(void)
188 if (hostname) return hostname;
189 if (gethostname(buf, sizeof(buf)) < 0)
190 hostname = eina_stringshare_add("");
192 hostname = eina_stringshare_add(buf);
197 efreet_dirs_reset(void)
199 eina_stringshare_replace(&xdg_desktop_dir, NULL);
204 * @param key The environment key to lookup
205 * @param fallback The fallback value to use
206 * @return Returns the directory related to the given key or the fallback
207 * @brief This tries to determine the correct directory name given the
208 * environment key @a key and fallbacks @a fallback.
211 efreet_dir_get(const char *key, const char *fallback)
217 if (!dir || dir[0] == '\0')
222 user = efreet_home_dir_get();
223 len = strlen(user) + strlen(fallback) + 1;
225 snprintf(dir, len, "%s%s", user, fallback);
227 t = eina_stringshare_add(dir);
229 else t = eina_stringshare_add(dir);
236 * @param key The environment key to lookup
237 * @param fallback The fallback value to use
238 * @return Returns a list of directories specified by the given key @a key
239 * or from the list of fallbacks in @a fallback.
240 * @brief Creates a list of directories as given in the environment key @a
241 * key or from the fallbacks in @a fallback
244 efreet_dirs_get(const char *key, const char *fallback)
246 Eina_List *dirs = NULL;
253 if (!path || (path[0] == '\0')) path = fallback;
255 if (!path) return dirs;
257 len = strlen(path) + 1;
259 memcpy(tmp, path, len);
261 p = strchr(s, EFREET_PATH_SEP);
265 if (!eina_list_search_unsorted(dirs, EINA_COMPARE_CB(strcmp), s))
267 // resolve path properly/fully to remove path//path2 to
268 // path/path2, path/./path2 to path/path2 etc.
270 dirs = eina_list_append(dirs, (void *)eina_stringshare_add(ts));
274 p = strchr(s, EFREET_PATH_SEP);
276 if (!eina_list_search_unsorted(dirs, EINA_COMPARE_CB(strcmp), s))
278 // resolve path properly/fully to remove path//path2 to
279 // path/path2, path/./path2 to path/path2 etc.
281 dirs = eina_list_append(dirs, (void *)eina_stringshare_add(ts));
288 efreet_env_expand(const char *in)
291 const char *ret, *p, *e1 = NULL, *e2 = NULL, *val;
294 if (!in) return NULL;
295 sb = eina_strbuf_new();
296 if (!sb) return NULL;
298 /* maximum length of any env var is the input string */
299 env = alloca(strlen(in) + 1);
300 for (p = in; *p; p++)
304 if (*p == '$') e1 = p + 1;
305 else eina_strbuf_append_char(sb, *p);
307 else if (!(((*p >= 'a') && (*p <= 'z')) ||
308 ((*p >= 'A') && (*p <= 'Z')) ||
309 ((*p >= '0') && (*p <= '9')) ||
315 len = (size_t)(e2 - e1);
318 memcpy(env, e1, len);
321 if (val) eina_strbuf_append(sb, val);
324 eina_strbuf_append_char(sb, *p);
327 ret = eina_stringshare_add(eina_strbuf_string_get(sb));
328 eina_strbuf_free(sb);
334 * @param key The user-dirs key to lookup
335 * @param fallback The fallback value to use
336 * @return Returns the directory related to the given key or the fallback
337 * @brief This tries to determine the correct directory name given the
338 * user-dirs key @a key and fallbacks @a fallback.
341 efreet_user_dir_get(const char *key, const char *fallback)
343 Eina_File *file = NULL;
344 Eina_File_Line *line;
345 Eina_Iterator *it = NULL;
346 const char *config_home;
350 config_home = efreet_config_home_get();
351 snprintf(path, sizeof(path), "%s/user-dirs.dirs", config_home);
353 file = eina_file_open(path, EINA_FALSE);
354 if (!file) goto fallback;
355 it = eina_file_map_lines(file);
356 if (!it) goto fallback;
357 EINA_ITERATOR_FOREACH(it, line)
359 const char *eq, *end;
360 Eina_Bool quote = EINA_FALSE;
362 if (line->length < 3) continue;
363 if (line->start[0] == '#') continue;
364 if (strncmp(line->start, "XDG", 3)) continue;
365 eq = memchr(line->start, '=', line->length);
367 if (strncmp(key, line->start, eq - line->start)) continue;
368 if (++eq >= line->end) continue;
372 if (++eq >= line->end) continue;
375 end = memchr(eq, '"', line->end - eq);
379 while (isspace(*end)) end--;
382 ret = alloca(end - eq + 1);
383 memcpy(ret, eq, end - eq);
384 ret[end - eq] = '\0';
388 if (it) eina_iterator_free(it);
389 if (file) eina_file_close(file);
393 home = efreet_home_dir_get();
394 ret = alloca(strlen(home) + strlen(fallback) + 2);
395 sprintf(ret, "%s/%s", home, fallback);
397 return efreet_env_expand(ret);