The CONF library.

The CONF library is a simple set of routines that can be used to configure
programs.  It is a superset of the genenv() function with some extra
structure.

The library consists of 5 functions.

LHASH *CONF_load(LHASH *config,char *file);
This function is called to load in a configuration file.  Multiple
configuration files can be loaded, with each subsequent 'load' overwriting
any already defined 'variables'.  If there is an error, NULL is returned.
If config is NULL, a new LHASH structure is created and returned, otherwise
the new data in the 'file' is loaded into the 'config' structure.

void CONF_free(LHASH *config);
This function free()s the data in config.

char *CONF_get_string(LHASH *config,char *section,char *name);
This function returns the string found in 'config' that corresponds to the
'section' and 'name' specified.  Classes and the naming system used will be
discussed later in this document.  If the variable is not defined, an NULL
is returned.

long CONF_get_long(LHASH *config,char *section, char *name);
This function is the same as CONF_get_string() except that it converts the
string to an long and returns it.  If variable is not a number or the
variable does not exist, 0 is returned.  This is a little problematic but I
don't know of a simple way around it.

STACK *CONF_get_section(LHASH *config, char *section);
This function returns a 'stack' of CONF_VALUE items that are all the
items defined in a particular section.  DO NOT free() any of the
variable returned.  They will disappear when CONF_free() is called.

The 'lookup' model.
The configuration file is divided into 'sections'.  Each section is started by
a line of the form '[ section ]'.  All subsequent variable definitions are
of this section.  A variable definition is a simple alpha-numeric name
followed by an '=' and then the data.  A section or variable name can be
described by a regular expression of the following form '[A-Za-z0-9_]+'.
The value of the variable is the text after the '=' until the end of the
line, stripped of leading and trailing white space.
At this point I should mention that a '#' is a comment character, \ is the
escape character, and all three types of quote can be used to stop any
special interpretation of the data.
Now when the data is being loaded, variable expansion can occur.  This is
done by expanding any $NAME sequences into the value represented by the
variable NAME.  If the variable is not in the current section, the different
section can be specified by using the $SECTION::NAME form.  The ${NAME} form
also works and is very useful for expanding variables inside strings.

When a variable is looked up, there are 2 special section. 'default', which
is the initial section, and 'ENV' which is the processes environment
variables (accessed via getenv()).  When a variable is looked up, it is
first 'matched' with it's section (if one was specified), if this fails, the
'default' section is matched.
If the 'lhash' variable passed was NULL, the environment is searched.

Now why do we bother with sections?  So we can have multiple programs using
the same configuration file, or multiple instances of the same program
using different variables.  It also provides a nice mechanism to override
the processes environment variables (eg ENV::HOME=/tmp).  If there is a
program specific variable missing, we can have default values.
Multiple configuration files can be loaded, with each new value clearing
any predefined values.  A system config file can provide 'default' values,
and application/usr specific files can provide overriding values.

Examples

# This is a simple example
SSLEAY_HOME	= /usr/local/ssl
ENV::PATH	= $SSLEAY_HOME/bin:$PATH	# override my path

[X509]
cert_dir	= $SSLEAY_HOME/certs	# /usr/local/ssl/certs

[SSL]
CIPHER		= DES-EDE-MD5:RC4-MD5
USER_CERT	= $HOME/${USER}di'r 5'	# /home/eay/eaydir 5
USER_CERT	= $HOME/\${USER}di\'r	# /home/eay/${USER}di'r
USER_CERT	= "$HOME/${US"ER}di\'r	# $HOME/${USER}di'r

TEST		= 1234\
5678\
9ab					# TEST=123456789ab
TTT		= 1234\n\n		# TTT=1234