libconfig may be yet another configuration library, but I gave it a once- over anyway, and it is good. libconfig calls itself “a simple library for processing structured configuration files”, with a “file format which is much more readable than XML”. The file format really is readable, as the following short example shows:

# authenticator
name = "JP";
enabled = false;
length = 186;
ldap = {
	host = "";
    	base = "ou=usr,";  /* adapt this */
    	retries = [10, 15, 20, 60];	// Use more than 2

Comments within the configuration file can be placed anywhere, and libconfig knows three comment formats: a hash (#) as in the UNIX shells, the double slash (//) and the C-style /* ... */.

libconfig knows about scalar values (integer, 64-bit integer, floating point, boolean and string), arrays of scalar values of the same type, so- called groups (collections of settings), and lists, which are sequences of values of any type, including lists. Configuration files can become quite complex, as this example shows shows.

Even so, libconfig is compact, and easy to use. I whipped up a small example – one that reads values from the sample configuration file above:

#include <stdio.h>
#include <stdlib.h>
#include <libconfig.h>

int main(int argc, char **argv)
	config_t cfg, *cf;
	const config_setting_t *retries;
	const char *base = NULL;
	int count, n, enabled;

	cf = &cfg;

	if (!config_read_file(cf, "ldap.cfg")) {
		fprintf(stderr, "%s:%d - %s\n",

	if (config_lookup_bool(cf, "enabled", &enabled))
		printf("Enabled: %s\n", enabled ? "Yep" : "Nope");
		printf("Enabled is not defined\n");

	if (config_lookup_string(cf, "ldap.base", &base))
		printf("Host: %s\n", base);

	retries = config_lookup(cf, "ldap.retries");
	count = config_setting_length(retries);

	printf("I have %d retries:\n", count);
	for (n = 0; n < count; n++) {
		printf("\t#%d. %d\n", n + 1,
			config_setting_get_int_elem(retries, n));

	return 0;

When I run this program, libconfig validates the syntax of the configuration file (giving errors and line numbers on which the errors occur – very useful!), and slurps it in. By using the config_* routines, I can access individual configuration items. Note how nested elements such as the base value in the ldap group can be accessed by specifying "ldap.base" as the name of the nested configuration variable; that makes the code easy to read.

When I run the above program it outputs this:

Enabled: Nope
Host: ou=usr,
I have 4 retries:
    #1. 10
    #2. 15
    #3. 20
    #4. 60

libconfig can also write configuration files. You could have an application which reads a config file, lets a user change preferences and rewrite that file for later use. libconfig is well documented and has been released by Mark Lindner under the LGPL. If you need a small, yet powerful library for reading configuration files for your application (and don’t want to use Lua), libconfig is worth much more than a cursory glance.

As you probably all know by now because I’ve frequently mentioned it, my book Alternative DNS Servers discusses, well, a great number of Open Source DNS servers. One of them is PowerDNS Recursor, a caching recursive DNS server written by Bert Hubert.

In Appendix H I discuss scripting of PowerDNS Recursor with the Lua programming language, an embeddable script language. As an introduction to Lua, I create an expandable configuration function which reads a Lua script to determine the path to a variable called spoolfile.

Using a Lua script as a configuration file is extremely flexible, because you can augment that “configuration file” with Lua functions which produce settings or data dynamically. I discuss this in quite a bit more detail in my book, and the source code for the Lua bits is here.

I mention this here as it is relevant to the topic on hand.

Software, Linux, MacOSX, dnsbook, DNS, Lua, C, API, and configuration :: 17 Sep 2009 :: e-mail