use iniparser dependency for config file parsing

For the config file, we do not need the custom handwritten parser.

Thanks to Andrew for this command, we can now search for an alternative

$ git grep -lw INI -- :/:*.bb
meta-openembedded/meta-oe/recipes-support/inih/libinih_58.bb
meta-openembedded/meta-oe/recipes-support/iniparser/iniparser_4.1.bb
meta-openembedded/meta-oe/recipes-support/minini/minini_1.2.b.bb
poky/meta/recipes-devtools/python/python3-iniconfig_2.0.0.bb
poky/meta/recipes-devtools/python/python3-iniparse_0.5.bb

For the ini parser we have following requirements

- small API
- easy to use
- compiles fast
- has tests, examples, docs
- support for sections

- minini [1]

  can be dropped from the list since it also supports colon
  ':' instead of '=' for separating key and value, creating 2 ways of
  doing something. This makes it harder to swap out the ini parser in
  the future.

- libinih [2]

  uses SAX-style parsing of .ini files and thus does not provide
  a DOM of the .ini. This is a break from the previous parser which
  stored everything in struct config. To use this library would require
  to create a struct to store all the possible configuration, then fill
  that struct in one pass. Essentially wrapping that library to have
  DOM capability. That would be possible, but not ideal. libinih is also
  highly configurable with lots of config options.

- iniparser [3]

  has all the required features and stores the results of its
  parsing for later use. It is a seamless upgrade from the previous
  parser. The call sites do not have to be modified and we can read the
  config as before. A downside is that we have to provide our own wrap
  file.

For our purposes, iniparser is a good choice.

Using this dependency allows us to drop the custom parser and all the
tests that go along with it.

If sections are required in future config files, iniparser can also
support that.

References:

[1] https://github.com/compuphase/minIni
[2] https://github.com/benhoyt/inih
[3] https://gitlab.com/iniparser/iniparser

Change-Id: Ie2b57171ec1f8cb6b1b80ca1d9e6c112bedc1195
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/config.c b/config.c
index 5f5edaf..121425f 100644
--- a/config.c
+++ b/config.c
@@ -29,127 +29,37 @@
 
 #include <sys/mman.h>
 #include <sys/stat.h>
-#include "console-server.h"
+
+#include <iniparser/iniparser.h>
+
+#include "config.h"
+#include "config-internal.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 static const char *config_default_filename = SYSCONFDIR "/obmc-console.conf";
 
-struct config_item {
-	char *name;
-	char *value;
-	struct config_item *next;
-};
-
-struct config {
-	struct config_item *items;
-};
-
 const char *config_get_value(struct config *config, const char *name)
 {
-	struct config_item *item;
+	int rc;
+	char buf[CONFIG_MAX_KEY_LENGTH];
+	rc = snprintf(buf, CONFIG_MAX_KEY_LENGTH, ":%s", name);
 
-	if (!config) {
+	if (rc < 0) {
 		return NULL;
 	}
 
-	for (item = config->items; item; item = item->next) {
-		if (!strcasecmp(item->name, name)) {
-			return item->value;
-		}
+	if ((size_t)rc >= sizeof(buf)) {
+		return NULL;
 	}
 
-	return NULL;
-}
+	const char *value = iniparser_getstring(config->dict, buf, NULL);
 
-static void config_parse(struct config *config, char *buf)
-{
-	struct config_item *item;
-	char *name;
-	char *value;
-	char *p;
-	char *line;
-
-	for (p = NULL, line = strtok_r(buf, "\n", &p); line;
-	     line = strtok_r(NULL, "\n", &p)) {
-		char *end;
-		int rc;
-
-		/* trim leading space */
-		while (isspace(*line)) {
-			line++;
-		}
-
-		/* skip comments */
-		if (*line == '#') {
-			continue;
-		}
-
-		name = malloc(strlen(line));
-		value = malloc(strlen(line));
-		if (name && value) {
-			rc = sscanf(line, "%[^ =] = %[^#]s", name, value);
-		} else {
-			rc = -ENOMEM;
-		}
-
-		if (rc != 2) {
-			free(name);
-			free(value);
-			continue;
-		}
-
-		/* trim trailing space */
-		end = value + strlen(value) - 1;
-		while (isspace(*end)) {
-			*end-- = '\0';
-		}
-
-		/* create a new item and add to our list */
-		item = malloc(sizeof(*item));
-		item->name = name;
-		item->value = value;
-		item->next = config->items;
-		config->items = item;
+	if (value && strlen(value) == 0) {
+		return NULL;
 	}
-}
 
-static struct config *config_init_fd(int fd, const char *filename)
-{
-	struct config *config;
-	size_t size;
-	size_t len;
-	ssize_t rc;
-	char *buf;
-
-	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 from configuration file %s", filename);
-			goto out_free;
-
-		} else if (!rc) {
-			break;
-		}
-		len += rc;
-		if (len == size) {
-			size <<= 1;
-			buf = realloc(buf, size + 1);
-		}
-	}
-	buf[len] = '\0';
-
-	config = malloc(sizeof(*config));
-	config->items = NULL;
-
-	config_parse(config, buf);
-
-out_free:
-	free(buf);
-	return config;
+	return value;
 }
 
 struct config *config_init(const char *filename)
@@ -166,28 +76,30 @@
 		warn("Can't open configuration file %s", filename);
 		return NULL;
 	}
-
-	config = config_init_fd(fd, filename);
-
 	close(fd);
 
+	dictionary *dict = iniparser_load(filename);
+
+	if (dict == NULL) {
+		return NULL;
+	}
+
+	config = malloc(sizeof(*config));
+	if (config) {
+		config->dict = dict;
+	}
+
 	return config;
 }
 
 void config_fini(struct config *config)
 {
-	struct config_item *item;
-	struct config_item *next;
-
 	if (!config) {
 		return;
 	}
 
-	for (item = config->items; item; item = next) {
-		next = item->next;
-		free(item->name);
-		free(item->value);
-		free(item);
+	if (config->dict) {
+		iniparser_freedict(config->dict);
 	}
 
 	free(config);
@@ -357,22 +269,3 @@
 
 	return DEFAULT_CONSOLE_ID;
 }
-
-#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