config: Add test utility for configuration system

When compiled with CONFIG_TEST, the config code will include a little
main() function to read configuration from stdin, and print parsed
config to stdout.

This allows the configuration system to be easily used with a testuite
or fuzzer.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/Makefile.am b/Makefile.am
index d7272a6..a06e29d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,6 +3,8 @@
 sbin_PROGRAMS = console-server
 bin_PROGRAMS = console-client
 
+check_PROGRAMS = config-test
+
 AM_CFLAGS = -Wall -Wextra -Werror
 
 EXTRA_DIST = openbmc-console.conf.sample
@@ -22,3 +24,7 @@
 	 console-client.c \
 	 console-server.h \
 	 util.c
+
+config_test_CPPFLAGS = -DCONFIG_TEST -DSYSCONFDIR=\"\"
+config_test_SOURCES = \
+	config.c
diff --git a/config.c b/config.c
index ee820db..02bc735 100644
--- a/config.c
+++ b/config.c
@@ -70,31 +70,23 @@
 	}
 }
 
-struct config *config_init(const char *filename)
+static struct config *config_init_fd(int fd, const char *filename)
 {
 	struct config *config;
 	size_t size, len;
-	int fd, rc;
 	char *buf;
-
-	if (!filename)
-		filename = config_default_filename;
-
-	fd = open(filename, O_RDONLY);
-	if (fd < 0) {
-		warn("Can't open configuration file %s", filename);
-		return NULL;
-	}
+	int rc;
 
 	size = 4096;
 	len = 0;
 	buf = malloc(size + 1);
+	config = NULL;
 
 	for (;;) {
 		rc = read(fd, buf + len, size - len);
 		if (rc < 0) {
-			warn("Can't read configuration file %s", filename);
-			goto err_free;
+			warn("Can't read from configuration file %s", filename);
+			goto out_free;
 
 		} else if (!rc) {
 			break;
@@ -108,22 +100,35 @@
 	}
 	buf[len] = '\0';
 
-	close(fd);
-
 	config = malloc(sizeof(*config));
 	config->items = NULL;
 
 	config_parse(config, buf);
 
+out_free:
 	free(buf);
+	return config;
+}
+
+struct config *config_init(const char *filename)
+{
+	struct config *config;
+	int fd;
+
+	if (!filename)
+		filename = config_default_filename;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		warn("Can't open configuration file %s", filename);
+		return NULL;
+	}
+
+	config = config_init_fd(fd, filename);
+
+	close(fd);
 
 	return config;
-
-err_free:
-	free(buf);
-err_close:
-	close(fd);
-	return NULL;
 }
 
 void config_fini(struct config *config)
@@ -139,3 +144,23 @@
 
 	free(config);
 }
+
+#ifdef CONFIG_TEST
+int main(void)
+{
+	struct config_item *item;
+	struct config *config;
+
+	config = config_init_fd(STDIN_FILENO, "<stdin>");
+	if (!config)
+		return EXIT_FAILURE;
+
+	for (item = config->items; item; item = item->next)
+		printf("%s: %s\n", item->name, item->value);
+
+	config_fini(config);
+
+	return EXIT_SUCCESS;
+
+}
+#endif