mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-06-06 07:37:21 +02:00
Provide a cascaded merge-overwrite config approach for #6
gamemoded will now load and merge settings from the following locations - arrays will merge and single settings will overwrite. 1. /usr/share/gamemode/ 2. /etc/ 3. $XDG_CONFIG_HOME or $HOME/.config/ 4. $PWD
This commit is contained in:
parent
9359a8551c
commit
808f5c9159
@ -79,7 +79,13 @@ Or, distribute `libgamemodeauto.so` and either add `-lgamemodeauto` to your link
|
||||
---
|
||||
## Configuration
|
||||
|
||||
The daemon can currently be configured using a `gamemode.ini` file in `/usr/share/gamemode/`. [gamemode.ini](https://github.com/FeralInteractive/gamemode/blob/master/example/gamemode.ini) is an example of what this file would look like, with explanations for all the variables.
|
||||
The daemon can currently be configured using a `gamemode.ini` file. [gamemode.ini](https://github.com/FeralInteractive/gamemode/blob/master/example/gamemode.ini) is an example of what this file would look like, with explanations for all the variables.
|
||||
|
||||
Config files are loaded and merged from the following directories, in order:
|
||||
1. `/usr/share/gamemode/`
|
||||
2. `/etc/`
|
||||
3. `$XDG_CONFIG_HOME` or `$HOME/.config/`
|
||||
4. `$PWD`
|
||||
|
||||
The file parsing uses [inih](https://github.com/benhoyt/inih).
|
||||
|
||||
|
@ -38,12 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <linux/limits.h>
|
||||
#include <pthread.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Name and possible location of the config file */
|
||||
#define CONFIG_NAME "gamemode.ini"
|
||||
#define CONFIG_DIR "/usr/share/gamemode/"
|
||||
|
||||
/* Default value for the reaper frequency */
|
||||
#define DEFAULT_REAPER_FREQ 5
|
||||
@ -160,8 +161,32 @@ static int inih_handler(void *user, const char *section, const char *name, const
|
||||
/*
|
||||
* Load the config file
|
||||
*/
|
||||
static void load_config_file(GameModeConfig *self)
|
||||
static void load_config_files(GameModeConfig *self)
|
||||
{
|
||||
/* grab the current dir */
|
||||
char *config_location_local = get_current_dir_name();
|
||||
|
||||
/* Get home config location */
|
||||
char *config_location_home = NULL;
|
||||
const char *cfg = getenv("XDG_CONFIG_HOME");
|
||||
if (cfg) {
|
||||
config_location_home = realpath(cfg, NULL);
|
||||
} else {
|
||||
cfg = getenv("HOME");
|
||||
if (cfg) {
|
||||
char *cfg_full = NULL;
|
||||
if (asprintf(&cfg_full, "%s/.config", cfg) > 0) {
|
||||
config_location_home = realpath(cfg_full, NULL);
|
||||
free(cfg_full);
|
||||
}
|
||||
} else {
|
||||
struct passwd *p = getpwuid(getuid());
|
||||
if (p) {
|
||||
config_location_home = realpath(p->pw_dir, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Take the write lock for the internal data */
|
||||
pthread_rwlock_wrlock(&self->rwlock);
|
||||
|
||||
@ -172,28 +197,38 @@ static void load_config_file(GameModeConfig *self)
|
||||
memset(self->endscripts, 0, sizeof(self->endscripts));
|
||||
self->reaper_frequency = DEFAULT_REAPER_FREQ;
|
||||
|
||||
/* try locally first */
|
||||
FILE *f = fopen(CONFIG_NAME, "r");
|
||||
if (!f) {
|
||||
f = fopen(CONFIG_DIR CONFIG_NAME, "r");
|
||||
if (!f) {
|
||||
/* Failure here isn't fatal */
|
||||
LOG_ERROR("Note: No config file found [%s] in working directory or in [%s]\n",
|
||||
CONFIG_NAME,
|
||||
CONFIG_DIR);
|
||||
/*
|
||||
* Locations to load, in order
|
||||
* Arrays merge and values overwrite
|
||||
*/
|
||||
const char *locations[] = {
|
||||
"/usr/share/gamemode", /* shipped default config */
|
||||
"/etc", /* administrator config */
|
||||
config_location_home, /* user defined config eg. $XDG_CONFIG_HOME or $HOME/.config/ */
|
||||
config_location_local /* local data eg. $PWD */
|
||||
};
|
||||
|
||||
/* Load each file in order and overwrite values */
|
||||
for (unsigned int i = 0; i < sizeof(locations) / sizeof(locations[0]); i++) {
|
||||
char *path = NULL;
|
||||
if (locations[i] && asprintf(&path, "%s/" CONFIG_NAME, locations[i]) > 0) {
|
||||
FILE *f = fopen(path, "r");
|
||||
if (f) {
|
||||
LOG_MSG("Loading config file [%s]\n", path);
|
||||
int error = ini_parse_file(f, inih_handler, (void *)self);
|
||||
|
||||
/* Failure here isn't fatal */
|
||||
if (error) {
|
||||
LOG_MSG("Failed to parse config file - error on line %d!\n", error);
|
||||
}
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (f) {
|
||||
int error = ini_parse_file(f, inih_handler, (void *)self);
|
||||
|
||||
/* Failure here isn't fatal */
|
||||
if (error) {
|
||||
LOG_MSG("Failed to parse config file - error on line %d!\n", error);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
/* clean up memory */
|
||||
free(config_location_home);
|
||||
free(config_location_local);
|
||||
|
||||
/* Release the lock */
|
||||
pthread_rwlock_unlock(&self->rwlock);
|
||||
@ -217,7 +252,7 @@ void config_init(GameModeConfig *self)
|
||||
pthread_rwlock_init(&self->rwlock, NULL);
|
||||
|
||||
/* load the initial config */
|
||||
load_config_file(self);
|
||||
load_config_files(self);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -225,7 +260,7 @@ void config_init(GameModeConfig *self)
|
||||
*/
|
||||
void config_reload(GameModeConfig *self)
|
||||
{
|
||||
load_config_file(self);
|
||||
load_config_files(self);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -74,7 +74,20 @@ Or, distribute \fBlibgamemodeauto.so\fR and either link with \fB\-lgamemodeauto\
|
||||
|
||||
.SH CONFIG
|
||||
|
||||
\fBgamemoded\fR can be configured with a \fBgamemode.ini\fR file found in \fB/usr/share/gamemode/\fR. The daemon will load the config file on start-up if it exists.
|
||||
\fBgamemoded\fR will load and merge \fBgamemode.ini\fR config files from these directories in the following order:
|
||||
|
||||
.RS 4
|
||||
/usr/share/gamemode/
|
||||
.RE
|
||||
.RS 4
|
||||
/etc/
|
||||
.RE
|
||||
.RS 4
|
||||
$XDG_CONFIG_HOME or $HOME/.config/
|
||||
.RE
|
||||
.RS 4
|
||||
$PWD
|
||||
.RE
|
||||
|
||||
Behaviour of the config file can be explained by presenting a commented example:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user