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);
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);
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 size = 32;
unsigned int i, j;
{ "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, size, 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;
}
};
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,
WL_EXPORT int
module_init(struct weston_compositor *ec,
- int *argc, char *argv[], const char *config_file)
+ int *argc, char *argv[])
{
struct cms_static *cms;
struct weston_output *output;
ARRAY_LENGTH(drm_config_keys), output_section_done },
};
- parse_config_file(config_file, config_section,
+ parse_config_file(ec->config_fd, config_section,
ARRAY_LENGTH(config_section), cms);
cms->destroy_listener.notify = cms_notifier_destroy;
static struct weston_compositor *
drm_compositor_create(struct wl_display *display,
int connector, const char *seat, int tty, int pixman,
- 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->use_pixman = pixman;
if (weston_compositor_init(&ec->base, display, argc, argv,
- config_file) < 0) {
+ config_fd) < 0) {
weston_log("%s failed\n", __func__);
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, use_pixman = 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, use_pixman,
- argc, argv, config_file);
+ argc, argv, config_fd);
}
static struct weston_compositor *
fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[],
- const char *config_file, struct fbdev_parameters *param)
+ int config_fd, struct fbdev_parameters *param)
{
struct fbdev_compositor *compositor;
const char *seat = default_seat;
return NULL;
if (weston_compositor_init(&compositor->base, display, argc, argv,
- config_file) < 0)
+ config_fd) < 0)
goto out_free;
compositor->udev = udev_new();
WL_EXPORT struct weston_compositor *
backend_init(struct wl_display *display, int *argc, char *argv[],
- const char *config_file)
+ int config_fd)
{
/* TODO: Ideally, available frame buffers should be enumerated using
* udev, rather than passing a device node in as a parameter. */
parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
- return fbdev_compositor_create(display, argc, argv, config_file,
+ return fbdev_compositor_create(display, argc, argv, config_fd,
¶m);
}
static struct weston_compositor *
headless_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 headless_compositor *c;
memset(c, 0, sizeof *c);
if (weston_compositor_init(&c->base, display, argc, argv,
- config_file) < 0)
+ config_fd) < 0)
goto err_free;
weston_seat_init(&c->fake_seat, &c->base);
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(headless_options), argc, argv);
return headless_compositor_create(display, width, height, display_name,
- argc, argv, config_file);
+ argc, argv, config_fd);
}
static struct weston_compositor *
rdp_compositor_create(struct wl_display *display,
struct rdp_compositor_config *config,
- int *argc, char *argv[], const char *config_file)
+ int *argc, char *argv[], int config_fd)
{
struct rdp_compositor *c;
char *fd_str;
memset(c, 0, sizeof *c);
if (weston_compositor_init(&c->base, display, argc, argv,
- config_file) < 0)
+ config_fd) < 0)
goto err_free;
weston_seat_init(&c->main_seat, &c->base);
static struct weston_compositor *
rpi_compositor_create(struct wl_display *display, int *argc, char *argv[],
- const char *config_file, struct rpi_parameters *param)
+ int config_fd, struct rpi_parameters *param)
{
struct rpi_compositor *compositor;
const char *seat = default_seat;
return NULL;
if (weston_compositor_init(&compositor->base, display, argc, argv,
- config_file) < 0)
+ config_fd) < 0)
goto out_free;
compositor->udev = udev_new();
WL_EXPORT struct weston_compositor *
backend_init(struct wl_display *display, int *argc, char *argv[],
- const char *config_file)
+ int config_fd)
{
struct rpi_parameters param = {
.tty = 0, /* default to current tty */
parse_options(rpi_options, ARRAY_LENGTH(rpi_options), argc, argv);
- return rpi_compositor_create(display, argc, argv, config_file, ¶m);
+ return rpi_compositor_create(display, argc, argv, config_fd, ¶m);
}
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);
}
int fullscreen,
int no_input,
int use_pixman,
- 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,
use_pixman,
- argc, argv, config_file);
+ argc, argv, config_fd);
}
weston_compositor_init(struct weston_compositor *ec,
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);
weston_plane_release(&ec->primary_plane);
wl_event_loop_destroy(ec->input_loop);
+
+ close(ec->config_fd);
}
WL_EXPORT void
static int
load_modules(struct weston_compositor *ec, const char *modules,
- int *argc, char *argv[], const char *config_file)
+ int *argc, char *argv[])
{
const char *p, *end;
char buffer[256];
int (*module_init)(struct weston_compositor *ec,
- int *argc, char *argv[], const char *config_file);
+ int *argc, char *argv[]);
if (modules == NULL)
return 0;
snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
module_init = load_module(buffer, "module_init");
if (module_init)
- module_init(ec, argc, argv, config_file);
+ module_init(ec, argc, argv);
p = end;
while (*p == ',')
p++;
struct wl_event_loop *loop;
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 = WESTON_NATIVE_BACKEND;
}
- 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);
setenv("WAYLAND_DISPLAY", socket_name, 1);
- if (load_modules(ec, modules, &argc, argv, config_file) < 0)
+ if (load_modules(ec, modules, &argc, argv) < 0)
goto out;
- if (load_modules(ec, option_modules, &argc, argv, config_file) < 0)
+ if (load_modules(ec, option_modules, &argc, argv) < 0)
goto out;
- free(config_file);
-
for (i = 1; i < argc; i++)
weston_log("fatal: unhandled option: %s\n", argv[i]);
if (argc > 1) {
struct xkb_rule_names xkb_names;
struct xkb_context *xkb_context;
struct weston_xkb_info xkb_info;
+
+ int config_fd;
};
struct weston_buffer_reference {
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,
- int *argc, char *argv[], const char *config_file);
+ int *argc, char *argv[]);
void
weston_transformed_coord(int width, int height,
}
static void
-shell_configuration(struct desktop_shell *shell, const char *config_file)
+shell_configuration(struct desktop_shell *shell, int config_fd)
{
char *path = NULL;
int duration = 60;
{ "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
};
- parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
+ parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), shell);
shell->screensaver.path = path;
shell->screensaver.duration = duration * 1000;
WL_EXPORT int
module_init(struct weston_compositor *ec,
- int *argc, char *argv[], const char *config_file)
+ int *argc, char *argv[])
{
struct weston_seat *seat;
struct desktop_shell *shell;
wl_array_init(&shell->workspaces.array);
wl_list_init(&shell->workspaces.client_list);
- shell_configuration(shell, config_file);
+ shell_configuration(shell, ec->config_fd);
for (i = 0; i < shell->workspaces.num; i++) {
pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
WL_EXPORT int
module_init(struct weston_compositor *compositor,
- int *argc, char *argv[], const char *config_file)
+ int *argc, char *argv[])
{
struct tablet_shell *shell;
struct wl_event_loop *loop;
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "compositor.h"
#include "text-server-protocol.h"
static void
text_backend_configuration(struct text_backend *text_backend)
{
- char *config_file;
+ int config_fd;
char *path = NULL;
struct config_key input_method_keys[] = {
{ "input-method", input_method_keys, ARRAY_LENGTH(input_method_keys), NULL }
};
- config_file = config_file_path("weston.ini");
- parse_config_file(config_file, cs, ARRAY_LENGTH(cs), text_backend);
- free(config_file);
+ config_fd = open_config_file("weston.ini");
+ parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), text_backend);
+ close(config_fd);
if (path)
text_backend->input_method.path = path;
WL_EXPORT int
module_init(struct weston_compositor *compositor,
- int *argc, char *argv[], const char *config_file)
+ int *argc, char *argv[])
{
struct wl_display *display = compositor->wl_display;
WL_EXPORT int
module_init(struct weston_compositor *ec,
- int *argc, char *argv[], const char *config_file)
+ int *argc, char *argv[])
{
struct weston_test *test;
struct wl_event_loop *loop;