Blame SOURCES/libcgroup-0.41-loading-configuration-files-from-etc-cgconfig.d-dire.patch

308897
From 7b1b0409f5fc1828f0feb2086fe5b8184f7eb2c6 Mon Sep 17 00:00:00 2001
308897
From: Jan Chaloupka <jchaloup@redhat.com>
308897
Date: Sat, 20 Sep 2014 20:02:13 +0200
308897
Subject: [PATCH] loading configuration files from /etc/cgconfig.d/ directory
308897
308897
---
308897
 Makefile.in                |   2 +-
308897
 doc/man/cgconfig.conf.5    |   7 +-
308897
 doc/man/cgrulesengd.8      |   8 +-
308897
 include/libcgroup/config.h |  21 ++++++
308897
 src/config.c               | 181 +++++++++++++++++++++++++++++++++++++++++++--
308897
 src/daemon/Makefile.am     |   4 +-
308897
 src/daemon/Makefile.in     |  25 ++++++-
308897
 src/daemon/cgrulesengd.c   |  51 +++++++++++--
308897
 src/libcgroup-internal.h   |   3 +
308897
 src/libcgroup.map          |   5 ++
308897
 src/tools/tools-common.h   |   2 +-
308897
 11 files changed, 286 insertions(+), 23 deletions(-)
308897
308897
diff --git a/Makefile.in b/Makefile.in
308897
index af6e89c..0349c93 100644
308897
--- a/Makefile.in
308897
+++ b/Makefile.in
308897
@@ -84,7 +84,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
308897
 	$(srcdir)/config.h.in $(top_srcdir)/scripts/init.d/cgconfig.in \
308897
 	$(top_srcdir)/scripts/init.d/cgred.in \
308897
 	$(srcdir)/libcgroup.pc.in COPYING INSTALL README config.guess \
308897
-	config.sub install-sh missing ltmain.sh
308897
+	config.sub depcomp install-sh missing ylwrap ltmain.sh
308897
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
308897
 am__aclocal_m4_deps = $(top_srcdir)/configure.in
308897
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
308897
diff --git a/doc/man/cgconfig.conf.5 b/doc/man/cgconfig.conf.5
308897
index be80e4e..a7d9935 100644
308897
--- a/doc/man/cgconfig.conf.5
308897
+++ b/doc/man/cgconfig.conf.5
308897
@@ -251,6 +251,9 @@ Templates does not use
308897
 .B default
308897
 section settings.
308897
 
308897
+.I /etc/cgconfig.d/
308897
+directory can be used for additional configuration files. cgrulesengd searches this directory for additional templates.
308897
+
308897
 .\"********************************************"
308897
 .SH EXAMPLES
308897
 .LP
308897
@@ -783,10 +786,12 @@ related to them.
308897
 .SH FILES
308897
 .LP
308897
 .PD .1v
308897
-.TP 20
308897
+.TP
308897
 .B /etc/cgconfig.conf
308897
 .TP
308897
 default libcgroup configuration file
308897
+.B /etc/cgconfig.d/
308897
+default libcgroup configuration files directory
308897
 .PD 
308897
 
308897
 .SH SEE ALSO
308897
diff --git a/doc/man/cgrulesengd.8 b/doc/man/cgrulesengd.8
308897
index 2e89c5b..749b6fc 100644
308897
--- a/doc/man/cgrulesengd.8
308897
+++ b/doc/man/cgrulesengd.8
308897
@@ -65,10 +65,16 @@ controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
308897
 .SH FILES
308897
 .LP
308897
 .PD .1v
308897
-.TP 20
308897
+.TP
308897
 .B /etc/cgrules.conf
308897
 .TP
308897
 the default libcgroup configuration file
308897
+.TP
308897
+.B /etc/cgconfig.conf
308897
+the default templates file
308897
+.TP
308897
+.B /etc/cgconfig.d/
308897
+the default templates directory
308897
 
308897
 .SH SEE ALSO
308897
 cgrules.conf (5)
308897
diff --git a/include/libcgroup/config.h b/include/libcgroup/config.h
308897
index 43568e1..9aaa390 100644
308897
--- a/include/libcgroup/config.h
308897
+++ b/include/libcgroup/config.h
308897
@@ -84,11 +84,32 @@ int cgroup_init_templates_cache(char *pathname);
308897
 int cgroup_reload_cached_templates(char *pathname);
308897
 
308897
 /**
308897
+ * Load the templates cache from files. Before calling this function,
308897
+ * cgroup_templates_cache_set_source_files has to be called first.
308897
+ * @param file_index index of file which was unable to be parsed
308897
+ * @return 0 on success, > 0 on error
308897
+ */
308897
+int cgroup_load_templates_cache_from_files(int *file_index);
308897
+
308897
+/**
308897
+ * Setting source files of templates. This function has to be called before
308897
+ * any call of cgroup_load_templates_cache_from_files.
308897
+ * @param tmpl_files
308897
+ */
308897
+struct cgroup_string_list;
308897
+void cgroup_templates_cache_set_source_files(
308897
+	struct cgroup_string_list *tmpl_files);
308897
+
308897
+/**
308897
  * Physically create a new control group in kernel, based on given control
308897
  * group template and configuration file. If given template is not set in
308897
  * configuration file, then the procedure works create the control group
308897
  * using  cgroup_create_cgroup() function
308897
  *
308897
+ * Templates are loaded using cgroup_load_templates_cache_from_files
308897
+ * function, which must be preceded by cgroup_templates_cache_set_source_files
308897
+ * call.
308897
+ *
308897
  * The flags can alter the behavior of this function:
308897
  * CGFLAG_USE_TEMPLATE_CACHE: Use cached templates instead of
308897
  * parsing the config file
308897
diff --git a/src/config.c b/src/config.c
308897
index e1ee0a8..1c5fc14 100644
308897
--- a/src/config.c
308897
+++ b/src/config.c
308897
@@ -41,6 +41,8 @@
308897
 #include <sys/stat.h>
308897
 #include <sys/types.h>
308897
 
308897
+#include "tools/tools-common.h"
308897
+
308897
 unsigned int MAX_CGROUPS = 64;	/* NOTE: This value changes dynamically */
308897
 unsigned int MAX_TEMPLATES = 64;
308897
 				/* NOTE: This value changes dynamically */
308897
@@ -89,6 +91,7 @@ static int config_template_table_index;
308897
  */
308897
 static struct cgroup *template_table;
308897
 static int template_table_index;
308897
+static struct cgroup_string_list *template_files;
308897
 
308897
 
308897
 /*
308897
@@ -1572,6 +1575,161 @@ int cgroup_init_templates_cache(char *pathname)
308897
 
308897
 }
308897
 
308897
+/**
308897
+ * Setting source files of templates. This function has to be called before
308897
+ * any call of cgroup_load_templates_cache_from_files.
308897
+ * @param tmpl_files
308897
+ */
308897
+void cgroup_templates_cache_set_source_files(
308897
+	struct cgroup_string_list *tmpl_files)
308897
+{
308897
+	template_files = tmpl_files;
308897
+}
308897
+
308897
+/**
308897
+ * Appending cgroup templates parsed by parser to template_table
308897
+ * @param offset number of templates already in the table
308897
+ */
308897
+int cgroup_add_cgroup_templates(int offset)
308897
+{
308897
+	int i, ti, ret;
308897
+
308897
+	for (i = 0; i < config_template_table_index; i++) {
308897
+		ti = i + offset;
308897
+		ret = cgroup_copy_cgroup(&template_table[ti],
308897
+			&config_template_table[i]);
308897
+		if (ret)
308897
+			return ret;
308897
+
308897
+		strcpy((template_table[ti]).name,
308897
+			(config_template_table[i]).name);
308897
+		template_table[ti].tasks_uid =
308897
+			config_template_table[i].tasks_uid;
308897
+		template_table[ti].tasks_gid =
308897
+			config_template_table[i].tasks_gid;
308897
+		template_table[ti].task_fperm =
308897
+			config_template_table[i].task_fperm;
308897
+		template_table[ti].control_uid =
308897
+			config_template_table[i].control_uid;
308897
+		template_table[ti].control_gid =
308897
+			config_template_table[i].control_gid;
308897
+		template_table[ti].control_fperm =
308897
+			config_template_table[i].control_fperm;
308897
+		template_table[ti].control_dperm =
308897
+			config_template_table[i].control_dperm;
308897
+	}
308897
+
308897
+	return 0;
308897
+}
308897
+
308897
+/**
308897
+ * Expand template table based on new number of parsed templates, i.e.
308897
+ * on value of config_template_table_index.
308897
+ * Change value of template_table_index.
308897
+ * @return 0 on success, < 0 on error
308897
+ */
308897
+int cgroup_expand_template_table(void)
308897
+{
308897
+	int i;
308897
+
308897
+	template_table = realloc(template_table,
308897
+		(template_table_index + config_template_table_index)
308897
+		*sizeof(struct cgroup));
308897
+
308897
+	if (template_table == NULL)
308897
+		return -ECGOTHER;
308897
+
308897
+	for (i = 0; i < config_template_table_index; i++)
308897
+		template_table[i + template_table_index].index = 0;
308897
+
308897
+	template_table_index += config_template_table_index;
308897
+
308897
+	return 0;
308897
+}
308897
+
308897
+/**
308897
+ * Load the templates cache from files. Before calling this function,
308897
+ * cgroup_templates_cache_set_source_files has to be called first.
308897
+ * @param file_index index of file which was unable to be parsed
308897
+ * @return 0 on success, > 0 on error
308897
+ */
308897
+int cgroup_load_templates_cache_from_files(int *file_index)
308897
+{
308897
+	int ret;
308897
+	int i, j;
308897
+	int template_table_last_index;
308897
+	char *pathname;
308897
+
308897
+	if (!template_files) {
308897
+		/* source files has not been set */
308897
+		cgroup_dbg("Template source files have not been set. ");
308897
+		cgroup_dbg("Using only %s\n", CGCONFIG_CONF_FILE);
308897
+
308897
+		if (template_table_index == 0)
308897
+			/* the rules cache is empty */
308897
+			return cgroup_init_templates_cache(
308897
+				CGCONFIG_CONF_FILE);
308897
+		else
308897
+			/* cache is not empty */
308897
+			return cgroup_reload_cached_templates(
308897
+				CGCONFIG_CONF_FILE);
308897
+	}
308897
+
308897
+	if (template_table) {
308897
+		/* template structures have to be free */
308897
+		for (i = 0; i < template_table_index; i++)
308897
+			cgroup_free_controllers(&template_table[i]);
308897
+		free(template_table);
308897
+		template_table = NULL;
308897
+	}
308897
+	template_table_index = 0;
308897
+
308897
+	if ((config_template_table_index != 0) || (config_table_index != 0)) {
308897
+		/* config structures have to be clean before parsing */
308897
+		cgroup_free_config();
308897
+	}
308897
+
308897
+	for (j = 0; j < template_files->count; j++) {
308897
+		pathname = template_files->items[j];
308897
+
308897
+		cgroup_dbg("Parsing templates from %s.\n", pathname);
308897
+		/* Attempt to read the configuration file
308897
+		 * and cache the rules. */
308897
+		ret = cgroup_parse_config(pathname);
308897
+		if (ret) {
308897
+			cgroup_dbg("Could not initialize rule cache, ");
308897
+			cgroup_dbg("error was: %d\n", ret);
308897
+			*file_index = j;
308897
+			return ret;
308897
+		}
308897
+
308897
+		if (config_template_table_index > 0) {
308897
+			template_table_last_index = template_table_index;
308897
+			ret = cgroup_expand_template_table();
308897
+			if (ret) {
308897
+				cgroup_dbg("Could not expand template table, ");
308897
+				cgroup_dbg("error was: %d\n", -ret);
308897
+				*file_index = j;
308897
+				return -ret;
308897
+			}
308897
+
308897
+			/* copy template data to templates cache structures */
308897
+			cgroup_dbg("Copying templates to template table ");
308897
+			cgroup_dbg("from %s.\n", pathname);
308897
+			ret = cgroup_add_cgroup_templates(
308897
+				template_table_last_index);
308897
+			if (ret) {
308897
+				cgroup_dbg("Unable to copy cgroup\n");
308897
+				*file_index = j;
308897
+				return ret;
308897
+			}
308897
+			cgroup_dbg("Templates to template table copied\n");
308897
+		}
308897
+	}
308897
+
308897
+	return 0;
308897
+}
308897
+
308897
 /*
308897
  * Create a given cgroup, based on template configuration if it is present
308897
  * if the template is not present cgroup is creted using cgroup_create_cgroup
308897
@@ -1593,13 +1751,22 @@ int cgroup_config_create_template_group(struct cgroup *cgroup,
308897
 	 * use CGCONFIG_CONF_FILE by default
308897
 	 */
308897
 	if (!(flags & CGFLAG_USE_TEMPLATE_CACHE)) {
308897
-		if (template_table_index == 0)
308897
-			/* the rules cache is empty */
308897
-			ret = cgroup_init_templates_cache(CGCONFIG_CONF_FILE);
308897
-		else
308897
-			/* cache is not empty */
308897
-			ret = cgroup_reload_cached_templates(
308897
-				CGCONFIG_CONF_FILE);
308897
+		int fileindex;
308897
+
308897
+		/* the rules cache is empty */
308897
+		ret = cgroup_load_templates_cache_from_files(
308897
+			&fileindex);
308897
+		if (ret != 0) {
308897
+			if (fileindex < 0) {
308897
+				cgroup_dbg("Error: Template source files ");
308897
+				cgroup_dbg("have not been set\n");
308897
+			} else {
308897
+			    cgroup_dbg("Error: Failed to load template");
308897
+			    cgroup_dbg("rules from %s. ",
308897
+				    template_files->items[fileindex]);
308897
+			}
308897
+		}
308897
+
308897
 		if (ret != 0) {
308897
 			cgroup_dbg("Failed initialize templates cache.\n");
308897
 			return ret;
308897
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
308897
index f3100ed..abbbe30 100644
308897
--- a/src/daemon/Makefile.am
308897
+++ b/src/daemon/Makefile.am
308897
@@ -1,9 +1,9 @@
308897
-INCLUDES = -I $(top_srcdir)/include
308897
+INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/include
308897
 
308897
 if WITH_DAEMON
308897
 
308897
 sbin_PROGRAMS = cgrulesengd
308897
-cgrulesengd_SOURCES = cgrulesengd.c cgrulesengd.h
308897
+cgrulesengd_SOURCES = cgrulesengd.c cgrulesengd.h ../tools/tools-common.h ../tools/tools-common.c
308897
 cgrulesengd_LDADD = $(top_builddir)/src/.libs/libcgroup.la -lrt
308897
 cgrulesengd_LDFLAGS = -L$(top_builddir)/src/.libs
308897
 
308897
diff --git a/src/daemon/Makefile.in b/src/daemon/Makefile.in
308897
index 76f7e07..f3efc65 100644
308897
--- a/src/daemon/Makefile.in
308897
+++ b/src/daemon/Makefile.in
308897
@@ -92,8 +92,10 @@ CONFIG_CLEAN_FILES =
308897
 CONFIG_CLEAN_VPATH_FILES =
308897
 am__installdirs = "$(DESTDIR)$(sbindir)"
308897
 PROGRAMS = $(sbin_PROGRAMS)
308897
-am__cgrulesengd_SOURCES_DIST = cgrulesengd.c cgrulesengd.h
308897
-@WITH_DAEMON_TRUE@am_cgrulesengd_OBJECTS = cgrulesengd.$(OBJEXT)
308897
+am__cgrulesengd_SOURCES_DIST = cgrulesengd.c cgrulesengd.h \
308897
+	../tools/tools-common.h ../tools/tools-common.c
308897
+@WITH_DAEMON_TRUE@am_cgrulesengd_OBJECTS = cgrulesengd.$(OBJEXT) \
308897
+@WITH_DAEMON_TRUE@	tools-common.$(OBJEXT)
308897
 cgrulesengd_OBJECTS = $(am_cgrulesengd_OBJECTS)
308897
 @WITH_DAEMON_TRUE@cgrulesengd_DEPENDENCIES =  \
308897
 @WITH_DAEMON_TRUE@	$(top_builddir)/src/.libs/libcgroup.la
308897
@@ -294,8 +296,8 @@ target_alias = @target_alias@
308897
 top_build_prefix = @top_build_prefix@
308897
 top_builddir = @top_builddir@
308897
 top_srcdir = @top_srcdir@
308897
-INCLUDES = -I $(top_srcdir)/include
308897
-@WITH_DAEMON_TRUE@cgrulesengd_SOURCES = cgrulesengd.c cgrulesengd.h
308897
+INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/include
308897
+@WITH_DAEMON_TRUE@cgrulesengd_SOURCES = cgrulesengd.c cgrulesengd.h ../tools/tools-common.h ../tools/tools-common.c
308897
 @WITH_DAEMON_TRUE@cgrulesengd_LDADD = $(top_builddir)/src/.libs/libcgroup.la -lrt
308897
 @WITH_DAEMON_TRUE@cgrulesengd_LDFLAGS = -L$(top_builddir)/src/.libs
308897
 all: all-am
308897
@@ -393,6 +395,7 @@ distclean-compile:
308897
 	-rm -f *.tab.c
308897
 
308897
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgrulesengd.Po@am__quote@
308897
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools-common.Po@am__quote@
308897
 
308897
 .c.o:
308897
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
308897
@@ -415,6 +418,20 @@ distclean-compile:
308897
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
308897
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
308897
 
308897
+tools-common.o: ../tools/tools-common.c
308897
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tools-common.o -MD -MP -MF $(DEPDIR)/tools-common.Tpo -c -o tools-common.o `test -f '../tools/tools-common.c' || echo '$(srcdir)/'`../tools/tools-common.c
308897
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tools-common.Tpo $(DEPDIR)/tools-common.Po
308897
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../tools/tools-common.c' object='tools-common.o' libtool=no @AMDEPBACKSLASH@
308897
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
308897
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tools-common.o `test -f '../tools/tools-common.c' || echo '$(srcdir)/'`../tools/tools-common.c
308897
+
308897
+tools-common.obj: ../tools/tools-common.c
308897
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tools-common.obj -MD -MP -MF $(DEPDIR)/tools-common.Tpo -c -o tools-common.obj `if test -f '../tools/tools-common.c'; then $(CYGPATH_W) '../tools/tools-common.c'; else $(CYGPATH_W) '$(srcdir)/../tools/tools-common.c'; fi`
308897
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tools-common.Tpo $(DEPDIR)/tools-common.Po
308897
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../tools/tools-common.c' object='tools-common.obj' libtool=no @AMDEPBACKSLASH@
308897
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
308897
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tools-common.obj `if test -f '../tools/tools-common.c'; then $(CYGPATH_W) '../tools/tools-common.c'; else $(CYGPATH_W) '$(srcdir)/../tools/tools-common.c'; fi`
308897
+
308897
 mostlyclean-libtool:
308897
 	-rm -f *.lo
308897
 
308897
diff --git a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c
308897
index 170837a..d959eff 100644
308897
--- a/src/daemon/cgrulesengd.c
308897
+++ b/src/daemon/cgrulesengd.c
308897
@@ -34,6 +34,7 @@
308897
 #include "libcgroup.h"
308897
 #include "cgrulesengd.h"
308897
 #include "../libcgroup-internal.h"
308897
+#include "../tools/tools-common.h"
308897
 
308897
 #include <errno.h>
308897
 #include <stdarg.h>
308897
@@ -59,6 +60,9 @@
308897
 
308897
 #define NUM_PER_REALLOCATIOM	(100)
308897
 
308897
+/* list of config files from CGCONFIG_CONF_FILE and CGCONFIG_CONF_DIR */
308897
+static struct cgroup_string_list template_files;
308897
+
308897
 /* Log file, NULL if logging to file is disabled */
308897
 FILE* logfile;
308897
 
308897
@@ -936,6 +940,8 @@ void cgre_flash_rules(int signum)
308897
 	/* Current time */
308897
 	time_t tm = time(0);
308897
 
308897
+	int fileindex;
308897
+
308897
 	flog(LOG_INFO, "Reloading rules configuration\n");
308897
 	flog(LOG_DEBUG, "Current time: %s\n", ctime(&tm));
308897
 
308897
@@ -949,7 +955,7 @@ void cgre_flash_rules(int signum)
308897
 	}
308897
 
308897
 	/* Ask libcgroup to reload the template rules table. */
308897
-	cgroup_reload_cached_templates(CGCONFIG_CONF_FILE);
308897
+	cgroup_load_templates_cache_from_files(&fileindex);
308897
 }
308897
 
308897
 /**
308897
@@ -962,11 +968,13 @@ void cgre_flash_templates(int signum)
308897
 	/* Current time */
308897
 	time_t tm = time(0);
308897
 
308897
+	int fileindex;
308897
+
308897
 	flog(LOG_INFO, "Reloading templates configuration.\n");
308897
 	flog(LOG_DEBUG, "Current time: %s\n", ctime(&tm));
308897
 
308897
 	/* Ask libcgroup to reload the templates table. */
308897
-	cgroup_reload_cached_templates(CGCONFIG_CONF_FILE);
308897
+	cgroup_load_templates_cache_from_files(&fileindex);
308897
 }
308897
 
308897
 /**
308897
@@ -1069,6 +1077,8 @@ int main(int argc, char *argv[])
308897
 		{NULL, 0, NULL, 0}
308897
 	};
308897
 
308897
+	int fileindex;
308897
+
308897
 	/* Make sure the user is root. */
308897
 	if (getuid() != 0) {
308897
 		fprintf(stderr, "Error: Only root can start/stop the control"
308897
@@ -1180,6 +1190,25 @@ int main(int argc, char *argv[])
308897
 	}
308897
 
308897
 	/* Ask libcgroup to load the configuration rules. */
308897
+	ret = cgroup_string_list_init(&template_files,
308897
+		CGCONFIG_CONF_FILES_LIST_MINIMUM_SIZE);
308897
+	if (ret) {
308897
+		fprintf(stderr, "%s: cannot init file list, out of memory?\n",
308897
+			argv[0]);
308897
+		goto finished_without_temp_files;
308897
+	}
308897
+	/* first add CGCONFIG_CONF_FILE into file list */
308897
+	ret = cgroup_string_list_add_item(&template_files, CGCONFIG_CONF_FILE);
308897
+	if (ret) {
308897
+		fprintf(stderr, "%s: cannot add file to list, out of memory?\n"
308897
+			, argv[0]);
308897
+		goto finished;
308897
+	}
308897
+
308897
+	/* then read CGCONFIG_CONF_DIR directory for additional config files */
308897
+	cgroup_string_list_add_directory(&template_files, CGCONFIG_CONF_DIR,
308897
+		argv[0]);
308897
+
308897
 	if ((ret = cgroup_init_rules_cache()) != 0) {
308897
 		fprintf(stderr, "Error: libcgroup failed to initialize rules"
308897
 				"cache from %s. %s\n", CGRULES_CONF_FILE,
308897
@@ -1188,11 +1217,18 @@ int main(int argc, char *argv[])
308897
 	}
308897
 
308897
 	/* ask libcgroup to load template rules as well */
308897
-	ret = cgroup_init_templates_cache(CGCONFIG_CONF_FILE);
308897
+	cgroup_templates_cache_set_source_files(&template_files);
308897
+	ret = cgroup_load_templates_cache_from_files(&fileindex);
308897
 	if (ret != 0) {
308897
-		fprintf(stderr, "Error: libcgroup failed to initialize teplate"\
308897
-				"rules from %s. %s\n", CGCONFIG_CONF_FILE,
308897
-				cgroup_strerror(ret));
308897
+		if (fileindex < 0) {
308897
+			fprintf(stderr, "Error: Template source files ");
308897
+			fprintf(stderr, "have not been set\n");
308897
+		} else {
308897
+			fprintf(stderr, "Error: Failed to initialize template");
308897
+			fprintf(stderr, "rules from %s. ",
308897
+				template_files.items[fileindex]);
308897
+			fprintf(stderr, "%s\n", cgroup_strerror(-ret));
308897
+		}
308897
 		goto finished;
308897
 	}
308897
 
308897
@@ -1259,6 +1295,9 @@ int main(int argc, char *argv[])
308897
 	ret =  cgre_create_netlink_socket_process_msg();
308897
 
308897
 finished:
308897
+	cgroup_string_list_free(&template_files);
308897
+
308897
+finished_without_temp_files:
308897
 	if (logfile && logfile != stdout)
308897
 		fclose(logfile);
308897
 
308897
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
308897
index 4c0f46c..c128788 100644
308897
--- a/src/libcgroup-internal.h
308897
+++ b/src/libcgroup-internal.h
308897
@@ -48,6 +48,9 @@ __BEGIN_DECLS
308897
 
308897
 
308897
 #define CGCONFIG_CONF_FILE		"/etc/cgconfig.conf"
308897
+/* Minimum number of file in template file list for cgrulesengd */
308897
+#define CGCONFIG_CONF_FILES_LIST_MINIMUM_SIZE   4
308897
+#define CGCONFIG_CONF_DIR               "/etc/cgconfig.d"
308897
 
308897
 #define CGRULES_CONF_FILE       "/etc/cgrules.conf"
308897
 #define CGRULES_MAX_FIELDS_PER_LINE		3
308897
diff --git a/src/libcgroup.map b/src/libcgroup.map
308897
index b0c162c..f8b0fb9 100644
308897
--- a/src/libcgroup.map
308897
+++ b/src/libcgroup.map
308897
@@ -117,3 +117,8 @@ CGROUP_0.39 {
308897
 	cgroup_log;
308897
 	cgroup_parse_log_level_str;
308897
 } CGROUP_0.38;
308897
+
308897
+CGROUP_0.40 {
308897
+	cgroup_templates_cache_set_source_files;
308897
+	cgroup_load_templates_cache_from_files;
308897
+} CGROUP_0.39;
308897
diff --git a/src/tools/tools-common.h b/src/tools/tools-common.h
308897
index e05465f..c723eb4 100644
308897
--- a/src/tools/tools-common.h
308897
+++ b/src/tools/tools-common.h
308897
@@ -20,7 +20,7 @@
308897
 
308897
 #include "config.h"
308897
 #include <libcgroup.h>
308897
-#include <libcgroup-internal.h>
308897
+#include "../libcgroup-internal.h"
308897
 
308897
 #define cgroup_err(x...) cgroup_log(CGROUP_LOG_ERROR, x)
308897
 #define cgroup_warn(x...) cgroup_log(CGROUP_LOG_WARNING, x)
308897
-- 
308897
1.9.3
308897