2 * Copyright © 2011 Intel Corporation
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
31 #include <sys/types.h>
37 #include <wayland-util.h>
39 #include "config-parser.h"
42 #define container_of(ptr, type, member) ({ \
43 const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
44 (type *)( (char *)__mptr - offsetof(type,member) );})
46 struct weston_config_entry {
52 struct weston_config_section {
54 struct wl_list entry_list;
58 struct weston_config {
59 struct wl_list section_list;
64 open_config_file(struct weston_config *c, const char *name)
66 const char *config_dir = getenv("XDG_CONFIG_HOME");
67 const char *home_dir = getenv("HOME");
68 const char *config_dirs = getenv("XDG_CONFIG_DIRS");
73 snprintf(c->path, sizeof c->path, "%s", name);
74 return open(name, O_RDONLY | O_CLOEXEC);
77 /* Precedence is given to config files in the home directory,
78 * and then to directories listed in XDG_CONFIG_DIRS and
79 * finally to the current working directory. */
81 /* $XDG_CONFIG_HOME */
83 snprintf(c->path, sizeof c->path, "%s/%s", config_dir, name);
84 fd = open(c->path, O_RDONLY | O_CLOEXEC);
91 snprintf(c->path, sizeof c->path,
92 "%s/.config/%s", home_dir, name);
93 fd = open(c->path, O_RDONLY | O_CLOEXEC);
98 /* For each $XDG_CONFIG_DIRS: weston/<config_file> */
100 config_dirs = "/etc/xdg"; /* See XDG base dir spec. */
102 for (p = config_dirs; *p != '\0'; p = next) {
103 next = strchrnul(p, ':');
104 snprintf(c->path, sizeof c->path,
105 "%.*s/weston/%s", (int)(next - p), p, name);
106 fd = open(c->path, O_RDONLY | O_CLOEXEC);
114 /* Current working directory. */
115 snprintf(c->path, sizeof c->path, "./%s", name);
117 return open(c->path, O_RDONLY | O_CLOEXEC);
120 static struct weston_config_entry *
121 config_section_get_entry(struct weston_config_section *section,
124 struct weston_config_entry *e;
128 wl_list_for_each(e, §ion->entry_list, link)
129 if (strcmp(e->key, key) == 0)
136 struct weston_config_section *
137 weston_config_get_section(struct weston_config *config, const char *section,
138 const char *key, const char *value)
140 struct weston_config_section *s;
141 struct weston_config_entry *e;
145 wl_list_for_each(s, &config->section_list, link) {
146 if (strcmp(s->name, section) != 0)
150 e = config_section_get_entry(s, key);
151 if (e && strcmp(e->value, value) == 0)
160 weston_config_section_get_int(struct weston_config_section *section,
162 int32_t *value, int32_t default_value)
164 struct weston_config_entry *entry;
166 entry = config_section_get_entry(section, key);
168 *value = default_value;
173 if (!weston_strtoi(entry->value, NULL, 0, value)) {
174 *value = default_value;
184 weston_config_section_get_uint(struct weston_config_section *section,
186 uint32_t *value, uint32_t default_value)
188 struct weston_config_entry *entry;
190 entry = config_section_get_entry(section, key);
192 *value = default_value;
197 if (!weston_strtoui(entry->value, NULL, 0, value)) {
198 *value = default_value;
208 weston_config_section_get_double(struct weston_config_section *section,
210 double *value, double default_value)
212 struct weston_config_entry *entry;
215 entry = config_section_get_entry(section, key);
217 *value = default_value;
222 *value = strtod(entry->value, &end);
224 *value = default_value;
234 weston_config_section_get_string(struct weston_config_section *section,
236 char **value, const char *default_value)
238 struct weston_config_entry *entry;
240 entry = config_section_get_entry(section, key);
243 *value = strdup(default_value);
250 *value = strdup(entry->value);
257 weston_config_section_get_bool(struct weston_config_section *section,
259 int *value, int default_value)
261 struct weston_config_entry *entry;
263 entry = config_section_get_entry(section, key);
265 *value = default_value;
270 if (strcmp(entry->value, "false") == 0)
272 else if (strcmp(entry->value, "true") == 0)
275 *value = default_value;
285 weston_config_get_libexec_dir(void)
287 const char *path = getenv("WESTON_BUILD_DIR");
295 static struct weston_config_section *
296 config_add_section(struct weston_config *config, const char *name)
298 struct weston_config_section *section;
300 section = malloc(sizeof *section);
301 section->name = strdup(name);
302 wl_list_init(§ion->entry_list);
303 wl_list_insert(config->section_list.prev, §ion->link);
308 static struct weston_config_entry *
309 section_add_entry(struct weston_config_section *section,
310 const char *key, const char *value)
312 struct weston_config_entry *entry;
314 entry = malloc(sizeof *entry);
315 entry->key = strdup(key);
316 entry->value = strdup(value);
317 wl_list_insert(section->entry_list.prev, &entry->link);
322 struct weston_config *
323 weston_config_parse(const char *name)
327 struct weston_config *config;
328 struct weston_config_section *section = NULL;
331 config = malloc(sizeof *config);
335 wl_list_init(&config->section_list);
337 fd = open_config_file(config, name);
343 fp = fdopen(fd, "r");
349 while (fgets(line, sizeof line, fp)) {
355 p = strchr(&line[1], ']');
356 if (!p || p[1] != '\n') {
357 fprintf(stderr, "malformed "
358 "section header: %s\n", line);
360 weston_config_destroy(config);
364 section = config_add_section(config, &line[1]);
367 p = strchr(line, '=');
368 if (!p || p == line || !section) {
369 fprintf(stderr, "malformed "
370 "config line: %s\n", line);
372 weston_config_destroy(config);
381 while (i > 0 && isspace(p[i - 1])) {
385 section_add_entry(section, line, p);
396 weston_config_get_full_path(struct weston_config *config)
398 return config == NULL ? NULL : config->path;
402 weston_config_next_section(struct weston_config *config,
403 struct weston_config_section **section,
409 if (*section == NULL)
410 *section = container_of(config->section_list.next,
411 struct weston_config_section, link);
413 *section = container_of((*section)->link.next,
414 struct weston_config_section, link);
416 if (&(*section)->link == &config->section_list)
419 *name = (*section)->name;
425 weston_config_destroy(struct weston_config *config)
427 struct weston_config_section *s, *next_s;
428 struct weston_config_entry *e, *next_e;
433 wl_list_for_each_safe(s, next_s, &config->section_list, link) {
434 wl_list_for_each_safe(e, next_e, &s->entry_list, link) {