public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/openrc:master commit in: sh/, src/librc/
@ 2015-11-05 18:53 William Hubbs
  0 siblings, 0 replies; only message in thread
From: William Hubbs @ 2015-11-05 18:53 UTC (permalink / raw
  To: gentoo-commits

commit:     c09eeca49145b034df6527c500099ba22f28e824
Author:     William Hubbs <w.d.hubbs <AT> gmail <DOT> com>
AuthorDate: Fri Oct 30 17:32:32 2015 +0000
Commit:     William Hubbs <williamh <AT> gentoo <DOT> org>
CommitDate: Thu Nov  5 16:40:24 2015 +0000
URL:        https://gitweb.gentoo.org/proj/openrc.git/commit/?id=c09eeca4

Add rc.conf.d support

This makes it possible to override settings in rc.conf by adding a
directory @SYSCONFDIR <AT> /rc.conf.d and putting files in this directory.
The files will be processed in lexical order, and the last setting in
these files will be used.

 sh/openrc-run.sh.in    |   6 +++
 src/librc/librc-misc.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/librc/rc.h.in      |   1 +
 3 files changed, 110 insertions(+)

diff --git a/sh/openrc-run.sh.in b/sh/openrc-run.sh.in
index 8aba4e0..749af2c 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 2e9de80..1eedc96 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 13e1b5b..e3a586f 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"


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-11-05 18:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-05 18:53 [gentoo-commits] proj/openrc:master commit in: sh/, src/librc/ William Hubbs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox