From ab3dbb68ff59032ac7fc2669b9b5ac9860f8a00f Mon Sep 17 00:00:00 2001 From: Michael Skec Date: Fri, 1 Dec 2023 20:22:51 +1100 Subject: [PATCH 1/2] XDG base directory: read fdm.conf from XDG_CONFIG_HOME Implements https://github.com/nicm/fdm/issues/96 https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html If no configuration file is specified on the command-line, $XDG_CONFIG_HOME/fdm.conf is now the first file checked, then $HOME/.fdm.conf, and finally the system-wide /etc/fdm.conf. This allows the user to specify where they would like the configuration file to be stored. E.g. many users like to set XDG_CONFIG_HOME to $HOME/.config so that all their XDG-compliant programs have their configuration files stored there rather than in their home directory (or other arbitrary locations). --- fdm.c | 21 +++++++++++++++------ fdm.h | 8 +++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/fdm.c b/fdm.c index 7b21d7d..e37450b 100644 --- a/fdm.c +++ b/fdm.c @@ -445,11 +445,20 @@ main(int argc, char **argv) /* Find the config file. */ if (conf.conf_file == NULL) { - /* If no file specified, try ~ then /etc. */ - xasprintf(&conf.conf_file, "%s/%s", conf.user_home, CONFFILE); - if (access(conf.conf_file, R_OK) != 0) { - xfree(conf.conf_file); - conf.conf_file = xstrdup(SYSCONFFILE); + /* If no file specified, try $XDG_CONFIG_HOME, then ~ then /etc. */ + if ((s = getenv("XDG_CONFIG_HOME")) != NULL) { + xasprintf(&conf.conf_file, "%s/%s", s, CONFFILE); + if (access(conf.conf_file, R_OK) != 0) { + xfree(conf.conf_file); + conf.conf_file = NULL; + } + } + if (conf.conf_file == NULL) { + xasprintf(&conf.conf_file, "%s/%s", conf.user_home, CONFFILE_HOME); + if (access(conf.conf_file, R_OK) != 0) { + xfree(conf.conf_file); + conf.conf_file = xstrdup(SYSCONFFILE); + } } } log_debug2("loading configuration from %s", conf.conf_file); @@ -702,7 +711,7 @@ main(int argc, char **argv) if (geteuid() == 0) lock = xstrdup(SYSLOCKFILE); else - xasprintf(&lock, "%s/%s", conf.user_home, LOCKFILE); + xasprintf(&lock, "%s/%s", conf.user_home, LOCKFILE_HOME); } retry: if (*lock != '\0' && !conf.allow_many) { diff --git a/fdm.h b/fdm.h index 0d63e34..e63ff3f 100644 --- a/fdm.h +++ b/fdm.h @@ -52,9 +52,11 @@ #include #include -#define CHILDUSER "_fdm" -#define CONFFILE ".fdm.conf" -#define LOCKFILE ".fdm.lock" +#define CHILDUSER "_fdm" +#define CONFFILE "fdm.conf" +#define LOCKFILE "fdm.lock" +#define CONFFILE_HOME "." CONFFILE +#define LOCKFILE_HOME "." LOCKFILE #define DEFLOCKTIMEOUT 10 #define MAXQUEUEVALUE 50 #define DEFMAILQUEUE 2 From 677e19100ff95bd64c11d22401a5c639b6e9b2c0 Mon Sep 17 00:00:00 2001 From: Michael Skec Date: Sat, 2 Dec 2023 10:37:15 +1100 Subject: [PATCH 2/2] XDG base directory: lock file in XDG_RUNTIME_DIR Continuation of https://github.com/nicm/fdm/issues/96 implementation. From https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html: > There is a single base directory relative to which user-specific > runtime files and other file objects should be placed. This directory > is defined by the environment variable $XDG_RUNTIME_DIR. This also may provide slight performance benefits to this as XDG_RUNTIME_DIR is often set to a directory under /tmp which some systems configure to be mounted as tmpfs. If XDG_RUNTIME_DIR is not set or is an empty string, the old behaviour of the user's home directory is used. --- fdm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fdm.c b/fdm.c index e37450b..37c910a 100644 --- a/fdm.c +++ b/fdm.c @@ -446,7 +446,8 @@ main(int argc, char **argv) /* Find the config file. */ if (conf.conf_file == NULL) { /* If no file specified, try $XDG_CONFIG_HOME, then ~ then /etc. */ - if ((s = getenv("XDG_CONFIG_HOME")) != NULL) { + s = getenv("XDG_CONFIG_HOME"); + if (s != NULL && *s != '\0') { xasprintf(&conf.conf_file, "%s/%s", s, CONFFILE); if (access(conf.conf_file, R_OK) != 0) { xfree(conf.conf_file); @@ -711,7 +712,15 @@ main(int argc, char **argv) if (geteuid() == 0) lock = xstrdup(SYSLOCKFILE); else - xasprintf(&lock, "%s/%s", conf.user_home, LOCKFILE_HOME); + { + /* Lockfile is stored in XDG_RUNTIME_DIR if provided. + * If not, we store it in the user's home directory. */ + s = getenv("XDG_RUNTIME_DIR"); + if (s != NULL && *s != '\0') + xasprintf(&lock, "%s/%s", s, LOCKFILE); + else + xasprintf(&lock, "%s/%s", conf.user_home, LOCKFILE_HOME); + } } retry: if (*lock != '\0' && !conf.allow_many) {