1 /*
2 * vim:ts=4:sw=4:expandtab
3 *
4 * i3 - an improved dynamic tiling window manager
5 * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
6 *
7 */
8 #include "libi3.h"
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/stat.h>
13
14 /*
15 * Get the path of the first configuration file found. If override_configpath is
16 * specified, that path is returned and saved for further calls. Otherwise,
17 * checks the home directory first, then the system directory, always taking
18 * into account the XDG Base Directory Specification ($XDG_CONFIG_HOME,
19 * $XDG_CONFIG_DIRS).
20 *
21 */
get_config_path(const char * override_configpath,bool use_system_paths)22 char *get_config_path(const char *override_configpath, bool use_system_paths) {
23 char *xdg_config_home, *xdg_config_dirs, *config_path;
24
25 static const char *saved_configpath = NULL;
26
27 if (override_configpath != NULL) {
28 saved_configpath = override_configpath;
29 return sstrdup(saved_configpath);
30 }
31
32 if (saved_configpath != NULL) {
33 return sstrdup(saved_configpath);
34 }
35
36 /* 1: check for $XDG_CONFIG_HOME/i3/config */
37 if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL) {
38 xdg_config_home = "~/.config";
39 }
40
41 xdg_config_home = resolve_tilde(xdg_config_home);
42 sasprintf(&config_path, "%s/i3/config", xdg_config_home);
43 free(xdg_config_home);
44
45 if (path_exists(config_path)) {
46 return config_path;
47 }
48 free(config_path);
49
50 /* 2: check the traditional path under the home directory */
51 config_path = resolve_tilde("~/.i3/config");
52 if (path_exists(config_path)) {
53 return config_path;
54 }
55 free(config_path);
56
57 /* The below paths are considered system-level, and can be skipped if the
58 * caller only wants user-level configs. */
59 if (!use_system_paths) {
60 return NULL;
61 }
62
63 /* 3: check for $XDG_CONFIG_DIRS/i3/config */
64 if ((xdg_config_dirs = getenv("XDG_CONFIG_DIRS")) == NULL) {
65 xdg_config_dirs = SYSCONFDIR "/xdg";
66 }
67
68 char *buf = sstrdup(xdg_config_dirs);
69 char *tok = strtok(buf, ":");
70 while (tok != NULL) {
71 tok = resolve_tilde(tok);
72 sasprintf(&config_path, "%s/i3/config", tok);
73 free(tok);
74 if (path_exists(config_path)) {
75 free(buf);
76 return config_path;
77 }
78 free(config_path);
79 tok = strtok(NULL, ":");
80 }
81 free(buf);
82
83 /* 4: check the traditional path under /etc */
84 config_path = SYSCONFDIR "/i3/config";
85 if (path_exists(config_path)) {
86 return sstrdup(config_path);
87 }
88
89 return NULL;
90 }
91