Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

AnyConfig Documentation

0.1.9

Obtaining a configuration from a variety of sources.

SourceForge Logo

Table of contents.

Introduction.

One of the better know time-consuming activities for any developer is to provide the users of his programs a way to set up the configuration. Likewise, users can tell you that one of their biggest problems often is to figure out how to configure a given program. Finally, system administrators are often driven to distraction by the fact that a program they'd like to use just cannot be [easily] configured due to security or manageability issues.
As I'm one of the above developers that has to cope with both other groups, I decided to end this issues for once and for all.

The result is a library called AnyConfig. In short what it does is look for the configuration in all the likely places until it finds one that satisfies it's requirements.

Features.

New things.

Version 1.9
New in this version is the use of the excellent IDE Anjuta. This is not required to use or build AnyConfig but is advised for anybody looking for an IDE to use on Linux!
Version 1.7
From this version on the support for CORBA configurations has been added.

Download.

Download from SourceForge.

Compiling the source code.

If all goes well, autoconf should detect which libraries are available on your system and the various modules should comment themselves out if the required support is not available...

Unfortunately, there is no autoconf support for MSDEV/MFC so here you'll probably have to do some manual configuring. Also, including both MFC (for registry access) and Orbacus (for CORBA support) does not work.

If all else fails you should remove the offending modules from either Makefile.am or delete the sub-projects from the MSDEV workspace.

Do let me (Author) know if you're having difficulties and/or ideas for better solutions so I can try to fix it in future versions.

How do I use this?

See MasterConfig for a programming example.
Also see the file 'testMe.cpp' for an example of using AnyConfig::AcConfiguration::loadRedundantConfig () which supports fall-back and fail-over type configurations.

Basically all you need to do is to include "AnyConfig.h" in your program (or "anycfg.h" if you are using C instead of C++) and call AcConfiguration::findAnyConfig() (or acfOpen() for plain C).

If there is any kind of configuration lurking around on your system that looks reasonable to AnyConfig, you will obtain an initialized "parent" configuration or even a bootstrapped larger configuration.
Usually you would select the section in this configuration that corresponds to your program and you can obtain (and usually even write back) any configuration items you want.
Lets look at an example. We will assume that you have many programs that use AnyConfig so you have put all of their configurations in a parent configuration file. For each group of programs you have a separate configuration source as well:

~/anycfg/parent.ini or %SYSTEMROOT%\\anycfg.ini.

[PROGRAM-GROUP-1]
; simple file based configuration
CFGFILENAME=/home/username/.anyconfig/group1.ini
[PROGRAM-GROUP-2]
; as above for an overpriced OS
CFGFILENAME=C:\\somedir\\group2.ini
[PROGRAM-GROUP-3]
USERNAME=username
PASSWORD=password
HOSTNAME=localhost
DATABASE=config
CFGTABLE=config

Now, to load the configuration for your program:

// if we don't have/want a command line:

int argn = 0;
char *argv [] = { NULL }:

AnyConfig::AcConfiguration *pParent = AnyConfig::AcConfiguration::findAnyConfig (argn, argv);
AnyConfig::AcConfiguration *pConfig = NULL;
if (NULL != pParent) {
    pParent->SetCurrentSection ("PROGRAM-GROUP-3");
    pConfig = new MySQLConfig;
    if (!pConfig->initialize (*pParent)) {
        delete pConfig;
        pConfig = NULL;
    } else {
        pConfig->SetCurrentSection ("MYPROGRAM");
    }
}

str2cfg

This program will convert a stringified configuration to a readable one.
You can redirect the output to file or use "copy and paste".
Usage:

str2cfg
Will read the stringified configuration from standard input.
str2cfg filename
Will read the stringified configuration from the file.
str2cfg --anycfg=string
Will use string as the stringified configuration.

cfg2str

This program will convert a readable configuration to a stringified representation.
You can redirect the output to file or use "copy and paste".
Usage:

cfg2str
Will read the configuration from standard input.
cfg2str filename
Will read the configuration from the file.

Configuration source.

It is possible in some cases to indicate a specific configuration source. See AnyConfig::AcConfiguration::loadFrom() for more details.
This is done by supplying a single string in the following format:
source:bootstrap:source section:source location
Where:

source
Is one of the supported configuration sources. Currently these are FILE and MYSQL.
bootstrap
Is a boolean indicating that the specified source is only a pointer to the actual source.
source section
Is an optional section to select in the specified source.
source location
Must be a stringified configuration for the use of AnyConfig::AcConfiguration::string2cfg().
See also str2cfg and cfg2str.

Note that there exists an interaction between bootstrap and source section:

No bootstrap nor a source section
The whole of the indicated configuration is to be used.
No bootstrap but a source section
Only the indicated section is to be used, any other sections will not be available.
A bootstrap but no source section
The bootstrap will be done from the "default" section in the indicated configuration. This form is obviously not recommended nor garanteed to work (as intended).
Both a bootstrap and a source section
Use the specified section from the indicated configuration to bootstrap from.

Examples:

FILE:0:MYPROGRAM:CFGFILENAME=/home/soap2corba/myprograms.ini@
MYSQL:0:MYPROGRAM:USERNAME=soap2corba@PASSWORD=soap2corba@

Some usage notes and common pitfalls.

Ordering of keys and/or iterating a configuration.

As the underlaying configuration sources have different characteristics, keys might be ordered differently. Therefore there are no intrinsic Next/Previous key methods or indeed any other method to iterate through a configuration.
One possible but not recommended work-around is to copy an AnyConfig to an AnyConfig::AcMemConfig, which does support various forms of iteration, using the AnyConfig::AcConfiguration::copyTo() or AnyConfig::AcConfiguration::copyFrom() methods.
The reason this practice is not recommended is that not all configuration sources support the copy methods, for the same reason there is no global iteration facility. Also, this practice might hide changes that were made to the original configuration after the program started, which might not have been your intent.

If you need a sequence in your configuration, like the supplied MasterConfig program for instance, you will have to define your own. Using the CString implementation you will find in the AnyConfig library as well, this can be easily done as follows:

CString key;
int iter;
AnyConfig::AcConfiguration *pCfg = AnyConfig::AcConfiguration::findAnyConfig (argn, argv);

for (iter = 0; iter < 100; iter ++) {
    key.Format ("CMD_%02d", iter);
    if (!pCfg->keyExists (key)) break;

    // use the key here
}

Manually entering stringified representations of a configuration.

It is very easy to make errors when typing the stringified representation of a configuration by hand.
You should use the supplied utility programs (cfg2str and str2cfg) instead.

Typed configuration items.

You might wonder how AnyConfig determines the type (Long, Number, Boolean, String) of a configuration item. The answer is simple, it doesn't. Nor is this capability specifically useful.
After all, the program obtaining the configuration defines the type of the configuration item, not the person entering the configuration. If the program expects a Boolean, entering the string "I have no idea" in the configuration does not grant it sudden AI capabilities (AnyConfig would return true for this, by the way, as it is not a number and does not start with either a N or a F).
Nor is it the task of the configuration reading functions to do type checking. Even though the configuration yields a number as expected, the program must still contain code to reject 1E300 or -20000 as being valid percentages...

Limits of section names, key names and configuration values.

There are no fixed limits for any of these as again they are mostly defined by the underlaying configuration source.
The default table as created by the AcMySQLConfig class, for instance, limits the names to 40 characters and the value to 255. Copying strings that long to an environment based configuration, however, has a good chance of not working as expected.

You might have noticed that the AnyConfig::AcRegConfig in particular is not very concerned about the length of the section names... About the only target that would accept such long names is the file based configuration class. That one as a limit of 4095 bytes per line, by the way.

Error handling.

AnyConfig is based on the philosophy of allowing as much as possible while doing things as strict as possible itself. In short, any reasonable inputs (and even some debatable ones) are accepted while obvious errors are silently ignored.

A few rudimentary debugging options exist, you can set AnyConfig::acfThrowExceptions which will cause AnyConfig to throw an AnyConfig::AcException for some glaring errors.
Another way of finding out what went wrong is by invoking the AnyConfig::AcConfiguration::display() method.

But mostly, the task of validating a configuration falls to the program itself. Again, generic routines have no way or knowning what is acceptable input for your program.

MasterConfig

This program allows starting other, non AnyConfig aware, programs by first creating their native configuration before starting them.

See also: AnyConfig::MasterConfig()

Building a command line.

A MasterConfig AnyConfig section can contain either a single command line or a compound one with keyword substitution.
Keywords are only substituted if they start with an At sign (@). The whole string is considered to be the keyword to substitute.
This works as follows:

USERNAME=me
PASSWORD=mine
PROGRAM=/bin/mysql
CMD_00=-u
CMD_01=@+@username
CMD_02=-p
CMD_03=@+@password

This would build the following command line:

mysql -ume -pmine

The command line normally has spaces inserted between each CMD_xx part, to avoid this start the argument with @+. You can use @@ if you need an At sign at the beginning of a command line part.
Lines that do not start with an At sign are not parsed so E-mail addresses can be inserted as usual.
Remember that everything after the At sign is considered the keyword.
This will not work:

GIVENNAME=Second
SURNAME=Lady
PROGRAM=mail
CMD_00=-s"To the attention of Mr.
CMD_01=@surname,
CMD_02=@givenname" office@company.domain

The trailing text will cause the lookup to fail. Use this instead:

GIVENNAME=Second
SURNAME=Lady
PROGRAM=mail
CMD_00=-s"To the attention of Mr.
CMD_01=@surname
CMD_02=@+,
CMD_03=@givenname
CMD_04=" office@company.domain

The result, will be:

mail -s"To the attention of Mr. Lady, Second" office@company.domain

Which is still nonsense but no longer due to a bad configuration.

Entering values in the environment.

Building environment strings for a program is rather simular to building a command line.
The main difference is that there is only one commandline but there can be multiple environment strings. Therefore you must start an environment string definition by specifiying the environment key, prefixed with an At sign (@) followed by an Equals sign (=). The following example should clarify this.

PROTOCOL=1
ENV_00=@=CVS_RSH
ENV_01=ssh -
ENV_02=@+@protocol
ENV_03=@=CVSROOT
ENV_04=:ext:soap2corba@cvs.anyconfig.sourceforge.net:/cvsroot/anyconfig checkout anyconfig

Example of using MasterConfig.

On a UN*X system, there is a file in the home directory of the user called '.anycfg.ini'. The MasterConfig will find and load this file automatically.
For this example, we will suppose it has the following content:

[CVS-ANYCONFIG]
PROGRAM=/bin/cvs
ENV_00=@=CVS_RSH
ENV_01=ssh
CMDLINE=-d:ext:soap2corba@cvs.anyconfig.sourceforge.net:/cvsroot/anyconfig checkout anyconfig
STARTDIR=//e/sf

Or, alternatively and yielding the same result:

PROGRAM=/bin/cvs
ENVIRON=CVS_RSH=ssh
CMD_00=-d:ext:
CMD_01=@+@username
CMD_02=@+@@cvs.
CMD_03=@+@project
CMD_04=@+.sourceforge.net:/cvsroot/
CMD_05=@+@project
CMD_06=checkout
CMD_07=@project
USERNAME=soap2corba
PROJECT=anyconfig
STARTDIR=//e/sf

We call MasterConfig as follows:

MasterConfig cvs-anyconfig

And, after entering CVS_RSH=ssh in the environment, it will execute in the "//e/sf" directory the following command:

/bin/cvs -d:ext:soap2corba@cvs.anyconfig.sourceforge.net:/cvsroot/anyconfig checkout anyconfig

Author

Walter Stroebel.
LifeLine Networks bv.
soap2corba@lifeline.nl
More about me.


Generated at Wed Nov 21 11:34:17 2001 for AnyConfig by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001