int main(int argc, char *argv[])
{
struct desktop desktop = { 0 };
- char *config_file;
+ int config_fd;
struct output *output;
int ret;
grab_surface_create(&desktop);
- config_file = config_file_path("weston.ini");
- ret = parse_config_file(config_file,
+ config_fd = open_config_file("weston.ini");
+ ret = parse_config_file(config_fd,
config_sections, ARRAY_LENGTH(config_sections),
&desktop);
- free(config_file);
+ close(config_fd);
if (ret < 0)
add_default_launcher(&desktop);
{
struct tablet tablet = { 0 };
struct display *display;
- char *config_file;
+ int config_fd;
struct output *output;
display = display_create(argc, argv);
window_get_wl_surface(tablet.homescreen->window));
wl_list_init(&tablet.homescreen->launcher_list);
- config_file = config_file_path("weston.ini");
- parse_config_file(config_file,
+ config_fd = open_config_file("weston.ini");
+ parse_config_file(config_fd,
config_sections, ARRAY_LENGTH(config_sections),
&tablet);
- free(config_file);
+ close(config_fd);
signal(SIGCHLD, sigchild_handler);
{
struct display *d;
struct terminal *terminal;
- char *config_file;
+ int config_fd;
option_shell = getenv("SHELL");
if (!option_shell)
option_shell = "/bin/bash";
- config_file = config_file_path("weston.ini");
- parse_config_file(config_file,
+ config_fd = open_config_file("weston.ini");
+ parse_config_file(config_fd,
config_sections, ARRAY_LENGTH(config_sections),
NULL);
- free(config_file);
+ close(config_fd);
argc = parse_options(terminal_options,
ARRAY_LENGTH(terminal_options), argc, argv);
static void
create_cursors(struct display *display)
{
- char *config_file;
+ int config_fd;
char *theme = NULL;
unsigned int i, j;
struct wl_cursor *cursor;
{ "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
};
- config_file = config_file_path("weston.ini");
- parse_config_file(config_file, cs, ARRAY_LENGTH(cs), NULL);
- free(config_file);
+ config_fd = open_config_file("weston.ini");
+ parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), NULL);
+ close(config_fd);
display->cursor_theme = wl_cursor_theme_load(theme, 32, display->shm);
display->cursors =
.nf
.BR "$XDG_CONFIG_HOME/weston.ini " "(if $XDG_CONFIG_HOME is set)"
.BR "$HOME/.config/weston.ini " "(if $HOME is set)"
-.BR "<current dir>/weston.ini " "(if both variables were not set)"
+.B "weston/weston.ini in each"
+.BR "\ \ \ \ $XDG_CONFIG_DIR " "(if $XDG_CONFIG_DIRS is set)"
+.BR "/etc/xdg/weston/weston.ini " "(if $XDG_CONFIG_DIRS is not set)"
+.BR "<current dir>/weston.ini " "(if no variables were set)"
.fi
.RE
.PP
.B $HOME
is the user's home directory, and
.B $XDG_CONFIG_HOME
-is the user specific configuration directory.
+is the user specific configuration directory, and
+.B $XDG_CONFIG_DIRS
+is a colon
+.B ':'
+delimited listed of configuration base directories, such as
+.BR /etc/xdg-foo:/etc/xdg .
.PP
The
.I weston.ini
* OF THIS SOFTWARE.
*/
+#define _GNU_SOURCE /* for stchrnul() */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "config-parser.h"
}
int
-parse_config_file(const char *path,
+parse_config_file(int fd,
const struct config_section *sections, int num_sections,
void *data)
{
const struct config_section *current = NULL;
int i;
- fp = fopen(path, "r");
+ if (fd == -1)
+ return -1;
+
+ fp = fdopen(dup(fd), "r");
if (fp == NULL) {
- fprintf(stderr, "couldn't open %s\n", path);
+ perror("couldn't open config file");
return -1;
}
+ rewind(fp);
+
while (fgets(line, sizeof line, fp)) {
if (line[0] == '#' || line[0] == '\n') {
continue;
return 0;
}
-char *
-config_file_path(const char *name)
+int
+open_config_file(const char *name)
{
- const char dotconf[] = "/.config/";
- const char *config_dir;
- const char *home_dir;
- char *path;
- size_t size;
-
- config_dir = getenv("XDG_CONFIG_HOME");
- if (!config_dir) {
- home_dir = getenv("HOME");
- if (!home_dir) {
- fprintf(stderr, "HOME is not set, using cwd.\n");
- return strdup(name);
- }
+ const char *config_dir = getenv("XDG_CONFIG_HOME");
+ const char *home_dir = getenv("HOME");
+ const char *config_dirs = getenv("XDG_CONFIG_DIRS");
+ char path[PATH_MAX];
+ const char *p, *next;
+ int fd;
+
+ /* Precedence is given to config files in the home directory,
+ * and then to directories listed in XDG_CONFIG_DIRS and
+ * finally to the current working directory. */
+
+ /* $XDG_CONFIG_HOME */
+ if (config_dir) {
+ snprintf(path, sizeof path, "%s/%s", config_dir, name);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd >= 0)
+ return fd;
+ }
+
+ /* $HOME/.config */
+ if (home_dir) {
+ snprintf(path, sizeof path, "%s/.config/%s", home_dir, name);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd >= 0)
+ return fd;
+ }
- size = strlen(home_dir) + sizeof dotconf + strlen(name);
- path = malloc(size);
- if (!path)
- return NULL;
+ /* For each $XDG_CONFIG_DIRS: weston/<config_file> */
+ if (!config_dirs)
+ config_dirs = "/etc/xdg"; /* See XDG base dir spec. */
- snprintf(path, size, "%s%s%s", home_dir, dotconf, name);
- return path;
+ for (p = config_dirs; *p != '\0'; p = next) {
+ next = strchrnul(p, ':');
+ snprintf(path, sizeof path,
+ "%.*s/weston/%s", (int)(next - p), p, name);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd >= 0)
+ return fd;
+
+ if (*next == ':')
+ next++;
}
- size = strlen(config_dir) + 1 + strlen(name) + 1;
- path = malloc(size);
- if (!path)
- return NULL;
+ /* Current working directory. */
+ snprintf(path, sizeof path, "./%s", name);
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+
+ if (fd >= 0)
+ fprintf(stderr,
+ "using config in current working directory: %s\n",
+ path);
+ else
+ fprintf(stderr, "config file \"%s\" not found.\n", name);
- snprintf(path, size, "%s/%s", config_dir, name);
- return path;
+ return fd;
}
#ifndef CONFIGPARSER_H
#define CONFIGPARSER_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
enum config_key_type {
CONFIG_KEY_INTEGER, /* typeof data = int */
CONFIG_KEY_UNSIGNED_INTEGER, /* typeof data = unsigned int */
};
int
-parse_config_file(const char *path,
+parse_config_file(int config_fd,
const struct config_section *sections, int num_sections,
void *data);
-char *
-config_file_path(const char *name);
+int
+open_config_file(const char *name);
enum weston_option_type {
WESTON_OPTION_INTEGER,
parse_options(const struct weston_option *options,
int count, int argc, char *argv[]);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* CONFIGPARSER_H */
static struct weston_compositor *
android_compositor_create(struct wl_display *display, int argc, char *argv[],
- const char *config_file)
+ int config_fd)
{
struct android_compositor *compositor;
struct android_output *output;
return NULL;
if (weston_compositor_init(&compositor->base, display, argc, argv,
- config_file) < 0)
+ config_fd) < 0)
goto err_free;
compositor->base.destroy = android_compositor_destroy;
WL_EXPORT struct weston_compositor *
backend_init(struct wl_display *display, int argc, char *argv[],
- const char *config_file)
+ int config_fd)
{
- return android_compositor_create(display, argc, argv, config_file);
+ return android_compositor_create(display, argc, argv, config_fd);
}
static struct weston_compositor *
drm_compositor_create(struct wl_display *display,
int connector, const char *seat, int tty,
- int argc, char *argv[], const char *config_file)
+ int argc, char *argv[], int config_fd)
{
struct drm_compositor *ec;
struct udev_device *drm_device;
ec->sprites_are_broken = 1;
if (weston_compositor_init(&ec->base, display, argc, argv,
- config_file) < 0) {
+ config_fd) < 0) {
weston_log("weston_compositor_init failed\n");
goto err_base;
}
WL_EXPORT struct weston_compositor *
backend_init(struct wl_display *display, int argc, char *argv[],
- const char *config_file)
+ int config_fd)
{
int connector = 0, tty = 0;
const char *seat = default_seat;
ARRAY_LENGTH(drm_config_keys), output_section_done },
};
- parse_config_file(config_file, config_section,
+ parse_config_file(config_fd, config_section,
ARRAY_LENGTH(config_section), NULL);
return drm_compositor_create(display, connector, seat, tty, argc, argv,
- config_file);
+ config_fd);
}
static struct weston_compositor *
wayland_compositor_create(struct wl_display *display,
int width, int height, const char *display_name,
- int argc, char *argv[], const char *config_file)
+ int argc, char *argv[], int config_fd)
{
struct wayland_compositor *c;
struct wl_event_loop *loop;
memset(c, 0, sizeof *c);
if (weston_compositor_init(&c->base, display, argc, argv,
- config_file) < 0)
+ config_fd) < 0)
goto err_free;
c->parent.wl_display = wl_display_connect(display_name);
WL_EXPORT struct weston_compositor *
backend_init(struct wl_display *display, int argc, char *argv[],
- const char *config_file)
+ int config_fd)
{
int width = 1024, height = 640;
char *display_name = NULL;
ARRAY_LENGTH(wayland_options), argc, argv);
return wayland_compositor_create(display, width, height, display_name,
- argc, argv, config_file);
+ argc, argv, config_fd);
}
x11_compositor_create(struct wl_display *display,
int fullscreen,
int no_input,
- int argc, char *argv[], const char *config_file)
+ int argc, char *argv[], int config_fd)
{
struct x11_compositor *c;
struct x11_configured_output *o;
memset(c, 0, sizeof *c);
if (weston_compositor_init(&c->base, display, argc, argv,
- config_file) < 0)
+ config_fd) < 0)
goto err_free;
c->dpy = XOpenDisplay(NULL);
WL_EXPORT struct weston_compositor *
backend_init(struct wl_display *display, int argc, char *argv[],
- const char *config_file)
+ int config_fd)
{
int fullscreen = 0;
int no_input = 0;
ARRAY_LENGTH(x11_config_keys), output_section_done },
};
- parse_config_file(config_file, config_section,
+ parse_config_file(config_fd, config_section,
ARRAY_LENGTH(config_section), NULL);
return x11_compositor_create(display,
fullscreen,
no_input,
- argc, argv, config_file);
+ argc, argv, config_fd);
}
struct wl_display *display,
int argc,
char *argv[],
- const char *config_file)
+ int config_fd)
{
struct wl_event_loop *loop;
struct xkb_rule_names xkb_names;
};
memset(&xkb_names, 0, sizeof(xkb_names));
- parse_config_file(config_file, cs, ARRAY_LENGTH(cs), ec);
+
+ ec->config_fd = config_fd;
+ parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), ec);
ec->wl_display = display;
wl_signal_init(&ec->destroy_signal);
wl_array_release(&ec->vtxcnt);
wl_event_loop_destroy(ec->input_loop);
+
+ close(ec->config_fd);
}
WL_EXPORT void
struct sigaction segv_action;
struct weston_compositor
*(*backend_init)(struct wl_display *display,
- int argc, char *argv[], const char *config_file);
- int i;
+ int argc, char *argv[], int config_fd);
+ int i, config_fd;
char *backend = NULL;
const char *modules = "desktop-shell.so", *option_modules = NULL;
char *log = NULL;
int32_t help = 0;
char *socket_name = "wayland-0";
int32_t version = 0;
- char *config_file;
const struct config_key core_config_keys[] = {
{ "modules", CONFIG_KEY_STRING, &modules },
backend = "drm-backend.so";
}
- config_file = config_file_path("weston.ini");
- parse_config_file(config_file, cs, ARRAY_LENGTH(cs), NULL);
+ config_fd = open_config_file("weston.ini");
+ parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), NULL);
backend_init = load_module(backend, "backend_init");
if (!backend_init)
exit(EXIT_FAILURE);
- ec = backend_init(display, argc, argv, config_file);
+ ec = backend_init(display, argc, argv, config_fd);
if (ec == NULL) {
weston_log("fatal: failed to create compositor\n");
exit(EXIT_FAILURE);
goto out;
}
- free(config_file);
-
ec->option_idle_time = idle_time;
ec->idle_time = idle_time;
struct xkb_rule_names xkb_names;
struct xkb_context *xkb_context;
struct weston_xkb_info xkb_info;
+
+ int config_fd;
};
struct weston_region {
int
weston_compositor_init(struct weston_compositor *ec, struct wl_display *display,
- int argc, char *argv[], const char *config_file);
+ int argc, char *argv[], int config_fd);
void
weston_compositor_shutdown(struct weston_compositor *ec);
void
struct weston_compositor *
backend_init(struct wl_display *display, int argc, char *argv[],
- const char *config_file);
+ int config_fd);
int
module_init(struct weston_compositor *compositor);
static void
shell_configuration(struct desktop_shell *shell)
{
- char *config_file;
+ int config_fd;
char *path = NULL;
int duration = 60;
unsigned int num_workspaces = DEFAULT_NUM_WORKSPACES;
{ "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
};
- config_file = config_file_path("weston.ini");
- parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
- free(config_file);
+ config_fd = open_config_file("weston.ini");
+ parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), shell);
+ close(config_fd);
shell->screensaver.path = path;
shell->screensaver.duration = duration;