From 5a460b4f95627f9f0b111a7082a544f4d3e3864f Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sat, 21 Sep 2024 20:07:28 +0200 Subject: [PATCH] librc: Overlay user configs. Add a new function to librc, `rc_usrconfdir()`, whick returns the location where user-made rc.conf exists. The user-made configuration is loaded first over the global config, so it takes priority when resolving variables, thus "overriding" global configs. --- src/librc/librc-misc.c | 33 ++++++++++++++++++++++++++------- src/librc/librc.c | 9 +++++++++ src/librc/rc.h.in | 6 ++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c index d096baebd..13f43b411 100644 --- a/src/librc/librc-misc.c +++ b/src/librc/librc-misc.c @@ -409,28 +409,47 @@ _free_rc_conf(void) rc_stringlist_free(rc_conf); } +static void +rc_conf_append(const char *file) +{ + RC_STRINGLIST *conf = rc_config_load(file); + TAILQ_CONCAT(rc_conf, conf, entries); + rc_stringlist_free(conf); +} + char * rc_conf_value(const char *setting) { const char *sysconfdir = rc_sysconfdir(); + const char *usrconfdir = rc_usrconfdir(); RC_STRING *s; char *conf; if (rc_conf) return rc_config_value(rc_conf, setting); - xasprintf(&conf, "%s/%s", sysconfdir, "rc.conf"); - rc_conf = rc_config_load(conf); + rc_conf = rc_stringlist_new(); atexit(_free_rc_conf); + /* Load user configurations first, as they should override + * system wide configs. */ + if (usrconfdir) { + xasprintf(&conf, "%s/%s", usrconfdir, "rc.conf"); + rc_conf_append(conf); + free(conf); + + xasprintf(&conf, "%s/%s", usrconfdir, "rc.conf.d"); + rc_conf = rc_config_directory(rc_conf, conf); + free(conf); + } + + xasprintf(&conf, "%s/%s", sysconfdir, "rc.conf"); + rc_conf_append(sysconfdir); free(conf); /* Support old configs. */ - if (exists(RC_CONF_OLD)) { - RC_STRINGLIST *old_conf = rc_config_load(RC_CONF_OLD); - TAILQ_CONCAT(rc_conf, old_conf, entries); - rc_stringlist_free(old_conf); - } + if (exists(RC_CONF_OLD)) + rc_conf_append(RC_CONF_OLD); xasprintf(&conf, "%s/%s", sysconfdir, "rc.conf.d"); rc_conf = rc_config_directory(rc_conf, conf); diff --git a/src/librc/librc.c b/src/librc/librc.c index 854ef4344..1d241c715 100644 --- a/src/librc/librc.c +++ b/src/librc/librc.c @@ -660,6 +660,15 @@ rc_sysconfdir(void) return RC_SYSCONFDIR; } +const char * +rc_usrconfdir(void) +{ + if (!is_user) + return NULL; + + return RC_SYSCONFDIR "/user.d"; +} + const char * rc_runleveldir(void) { diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in index 5ed3649cb..2a54da98f 100644 --- a/src/librc/rc.h.in +++ b/src/librc/rc.h.in @@ -142,6 +142,12 @@ const char * const *rc_scriptdirs(void); * @return Path to the system configuration directory */ const char *rc_sysconfdir(void); +/*! The user configuration directory is where rc.conf + * will be located for user-mode openrc. It is meant to + * override the system wide configs where applicable. + * @return Path to the user configuration directory, or NULL if in system mode */ +const char *rc_usrconfdir(void); + /*! @return Path to runlevel directory */ const char *rc_runleveldir(void);