aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sh/openrc-run.sh.in6
-rw-r--r--src/librc/librc-misc.c103
-rw-r--r--src/librc/rc.h.in1
3 files changed, 110 insertions, 0 deletions
diff --git a/sh/openrc-run.sh.in b/sh/openrc-run.sh.in
index 8aba4e0e..749af2cc 100644
--- a/sh/openrc-run.sh.in
+++ b/sh/openrc-run.sh.in
@@ -184,6 +184,12 @@ unset _conf_d
# Load any system overrides
sourcex -e "@SYSCONFDIR@/rc.conf"
+if [ -d "@SYSCONFDIR@/rc.conf.d" ]; then
+ for _f in "@SYSCONFDIR@"/rc.conf.d/*.conf; do
+ sourcex -e "$_f"
+ done
+fi
+
# load service supervisor functions
sourcex "@LIBEXECDIR@/sh/s6.sh"
diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c
index 2e9de801..1eedc968 100644
--- a/src/librc/librc-misc.c
+++ b/src/librc/librc-misc.c
@@ -28,6 +28,8 @@
* SUCH DAMAGE.
*/
+#include <fnmatch.h>
+
#include "queue.h"
#include "librc.h"
@@ -214,6 +216,69 @@ rc_config_list(const char *file)
}
librc_hidden_def(rc_config_list)
+static void rc_config_set_value(RC_STRINGLIST *config, char *value)
+{
+ RC_STRING *cline;
+ char *entry;
+ size_t i = 0;
+ char *newline;
+ char *p = value;
+ bool replaced;
+ char *token;
+
+ if (! p)
+ return;
+ if (strncmp(p, "export ", 7) == 0)
+ p += 7;
+ if (! (token = strsep(&p, "=")))
+ return;
+
+ entry = xstrdup(token);
+ /* Preserve shell coloring */
+ if (*p == '$')
+ token = value;
+ else
+ do {
+ /* Bash variables are usually quoted */
+ token = strsep(&p, "\"\'");
+ } while (token && *token == '\0');
+
+ /* Drop a newline if that's all we have */
+ if (token) {
+ i = strlen(token) - 1;
+ if (token[i] == '\n')
+ token[i] = 0;
+
+ i = strlen(entry) + strlen(token) + 2;
+ newline = xmalloc(sizeof(char) * i);
+ snprintf(newline, i, "%s=%s", entry, token);
+ } else {
+ i = strlen(entry) + 2;
+ newline = xmalloc(sizeof(char) * i);
+ snprintf(newline, i, "%s=", entry);
+ }
+
+ replaced = false;
+ /* In shells the last item takes precedence, so we need to remove
+ any prior values we may already have */
+ TAILQ_FOREACH(cline, config, entries) {
+ i = strlen(entry);
+ if (strncmp(entry, cline->value, i) == 0 && cline->value[i] == '=') {
+ /* We have a match now - to save time we directly replace it */
+ free(cline->value);
+ cline->value = newline;
+ replaced = true;
+ break;
+ }
+ }
+
+ if (!replaced) {
+ rc_stringlist_add(config, newline);
+ free(newline);
+ }
+ free(entry);
+}
+
/*
* Override some specific rc.conf options on the kernel command line
*/
@@ -272,6 +337,42 @@ static RC_STRINGLIST *rc_config_override(RC_STRINGLIST *config)
}
#endif
+static RC_STRINGLIST * rc_config_directory(RC_STRINGLIST *config)
+{
+ DIR *dp;
+ struct dirent *d;
+ RC_STRINGLIST *rc_conf_d_files = rc_stringlist_new();
+ RC_STRING *fname;
+ RC_STRINGLIST *rc_conf_d_list;
+ char path[PATH_MAX];
+ RC_STRING *line;
+
+ if ((dp = opendir(RC_CONF_D)) != NULL) {
+ while ((d = readdir(dp)) != NULL) {
+ if (fnmatch("*.conf", d->d_name, FNM_PATHNAME) == 0) {
+ rc_stringlist_addu(rc_conf_d_files, d->d_name);
+ }
+ }
+ closedir(dp);
+
+ if (rc_conf_d_files) {
+ rc_stringlist_sort(&rc_conf_d_files);
+ TAILQ_FOREACH(fname, rc_conf_d_files, entries) {
+ if (! fname->value)
+ continue;
+ sprintf(path, "%s/%s", RC_CONF_D, fname->value);
+ rc_conf_d_list = rc_config_list(path);
+ TAILQ_FOREACH(line, rc_conf_d_list, entries)
+ if (line->value)
+ rc_config_set_value(config, line->value);
+ rc_stringlist_free(rc_conf_d_list);
+ }
+ rc_stringlist_free(rc_conf_d_files);
+ }
+ }
+ return config;
+}
+
RC_STRINGLIST *
rc_config_load(const char *file)
{
@@ -401,6 +502,8 @@ rc_conf_value(const char *setting)
#endif
}
+ rc_conf = rc_config_directory(rc_conf);
+
/* Convert old uppercase to lowercase */
TAILQ_FOREACH(s, rc_conf, entries) {
p = s->value;
diff --git a/src/librc/rc.h.in b/src/librc/rc.h.in
index 13e1b5b9..e3a586f6 100644
--- a/src/librc/rc.h.in
+++ b/src/librc/rc.h.in
@@ -56,6 +56,7 @@ extern "C" {
#define RC_SYS_WHITELIST RC_LIBEXECDIR "/conf.d/env_whitelist"
#define RC_USR_WHITELIST RC_SYSCONFDIR "/conf.d/env_whitelist"
#define RC_CONF RC_SYSCONFDIR "/rc.conf"
+#define RC_CONF_D RC_SYSCONFDIR "/rc.conf.d"
#define RC_CONF_OLD RC_SYSCONFDIR "/conf.d/rc"
#define RC_PATH_PREFIX RC_LIBEXECDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin"