diff --git a/cli.c b/cli.c
index c1846ed5b449632fa9100c3b10f8ffdf4cc5fb7d..21b28b4b0674c6843728d11d23d4783466aa669b 100755
--- a/cli.c
+++ b/cli.c
@@ -337,7 +337,7 @@ static int handle_modlist(int fd, int argc, char *argv[])
 	ast_mutex_lock(&climodentrylock);
 	climodentryfd = fd;
 	ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
-	ast_update_module_list(modlist_modentry);
+	ast_cli(fd,"%d modules loaded\n",ast_update_module_list(modlist_modentry));
 	climodentryfd = -1;
 	ast_mutex_unlock(&climodentrylock);
 	return RESULT_SUCCESS;
diff --git a/config.c b/config.c
index 817d6c9b6df1ad1bec82d97a088a95612207ff54..111145c7bbdafa378913c38e0da7cb320cd146a2 100755
--- a/config.c
+++ b/config.c
@@ -431,6 +431,21 @@ struct ast_variable *ast_load_realtime(const char *family, ...)
 	return res;
 }
 
+struct ast_config *ast_load_realtime_multientry(const char *family, ...)
+{
+	struct ast_config_reg *reg;
+	char db[256]="";
+	char table[256]="";
+	struct ast_config *res=NULL;
+	va_list ap;
+	va_start(ap, family);
+	reg = get_ast_cust_config_keyword(family, db, sizeof(db), table, sizeof(table));
+	if (reg && reg->realtime_multi_func) 
+		res = reg->realtime_multi_func(db, table, ap);
+	va_end(ap);
+	return res;
+}
+
 int ast_update_realtime(const char *family, const char *keyfield, const char *lookup, ...)
 {
 	struct ast_config_reg *reg;
diff --git a/include/asterisk/config.h b/include/asterisk/config.h
index e377f7ce6095893ae69b713d4d190ea0b777b8a5..0812b98c9ebc7286a3e727f31733a330bb80885e 100755
--- a/include/asterisk/config.h
+++ b/include/asterisk/config.h
@@ -116,6 +116,19 @@ int ast_category_exist(struct ast_config *config, char *category_name);
  */
 struct ast_variable *ast_load_realtime(const char *family, ...);
 
+//! Retrieve realtime configuration
+/*!
+ * \param family which family/config to lookup
+ * \param keyfield which field to use as the key
+ * \param lookup which value to look for in the key field to match the entry.
+ * This will use builtin configuration backends to look up a particular 
+ * entity in realtime and return a variable list of its parameters. Unlike
+ * the ast_load_realtime, this function can return more than one entry and
+ * is thus stored inside a taditional ast_config structure rather than 
+ * just returning a linked list of variables.
+ */
+struct ast_config *ast_load_realtime_multientry(const char *family, ...);
+
 //! Update realtime configuration
 /*!
  * \param family which family/config to be updated
diff --git a/include/asterisk/config_pvt.h b/include/asterisk/config_pvt.h
index 1e7238e7c9695b8e3582de1ef33daaf177f6b538..c79c26e19b5b3a591514422baf3243a2766e4db2 100755
--- a/include/asterisk/config_pvt.h
+++ b/include/asterisk/config_pvt.h
@@ -31,6 +31,7 @@ struct ast_config_reg {
 	char name[CONFIG_KEYWORD_STRLEN];
 	struct ast_config *(*static_func)(const char *database, const char *table, const char *, struct ast_config *,struct ast_category **,struct ast_variable **,int);
 	struct ast_variable *(*realtime_func)(const char *database, const char *table, va_list ap);
+	struct ast_config *(*realtime_multi_func)(const char *database, const char *table, va_list ap);
 	int (*update_func)(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
 	struct ast_config_reg *next;
 };
diff --git a/loader.c b/loader.c
index 2a539f30c538cd1f0399585ea6d647dbf0dc82d1..09d406541a7403d2d6b5f5c2fd07ae497e820665 100755
--- a/loader.c
+++ b/loader.c
@@ -464,16 +464,18 @@ int ast_update_module_list(int (*modentry)(char *module, char *description, int
 {
 	struct module *m;
 	int unlock = -1;
+	int total_mod_loaded = 0;
 	if (ast_mutex_trylock(&modlock))
 		unlock = 0;
 	m = module_list;
 	while(m) {
 		modentry(m->resource, m->description(), m->usecount());
 		m = m->next;
+		total_mod_loaded++;
 	}
 	if (unlock)
 		ast_mutex_unlock(&modlock);
-	return 0;
+	return total_mod_loaded;
 }
 
 int ast_loader_register(int (*v)(void))