Reputation: 10268
In C, how to configure the initial settings for some program, using key-value pairs, with any or all of: a plain text configuration file, environment variables, and options on the command line. Also, how to decide which method's values overide those from either of the other two. Then if values have been changed, to optionally update the configuration file.
What's the simplest way to do this, and what if any, are the most accepted methods? Is there a, preferably small, open source program that gives a good example of how this can be done?
Upvotes: 5
Views: 6959
Reputation: 81645
The basics:
Which settings source should override each other depends on the application, but in my opinion generally commandline argument > environment variable > configuration file makes most sense.
Here is an example of getting configuration from environment and commandline, with commandline overriding environment:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char* const* argv) {
int i;
const char* myConfigVar;
// get default setting from environment
myConfigVar = getenv("MY_CONFIG_VAR");
// if the variable wasn't defined, initialize to hardcoded default
if (!myConfigVar)
myConfigVar = "default value";
// parse commandline arguments
// start at 1, because argv[0] contains the name of the program
for (i = 1; i < argc; ++i) {
if (strcmp("--my-config-var", argv[i]) == 0) {
if (i + 1 < argc)
myConfigVar = argv[i + 1];
else
printf("missing value for my-config-var argument\n");
}
}
printf("myConfigVar = '%s'\n", myConfigVar);
return 0;
}
You already see it becomes very long and tedious very soon, so better use an existing library if one exists for your desired target platform(s), or at least factor this kind of code into a number of functions.
Another interesting option is to bind a scripting language to your application, then you could make your application only read and "execute" your settings file, and the user could configure the settings file to read some settings from the environment and some from the commandline, for example. It really depends on type and size of the application and your target audience whether this is worth doing though.
Upvotes: 6
Reputation: 6424
Eric Raymond covers a lot of this in Section 10 of The Art of Unix Programming Obviously this is Unix centric, but most of the principles can be applied in any OS.
Upvotes: 6
Reputation: 43286
The Lua language partly got its start motivated by the need to have a well-defined configuration language for a collection of tools. It remains quite easy to integrate Lua as a configuration language. A fairly complete example is in the book Programming in Lua, an older edition of which is available online. Chapter 25 describes using the Lua C API to embed Lua as a configuration language, and reasons why you might want to do this.
Upvotes: 1
Reputation: 753525
For Unix-like design patterns in this area, look at Raymond's "The Art of Unix Programming". It discusses the prioritization of command line arguments over environment variables and configuration files, and so on.
Upvotes: 1
Reputation: 101171
The question is not terribly clear. Is the question "what mechanisms exist?", "what are the conventions for arguments and formats?", or "how you should I mix and match?"?
There are several pretty standard ways (at least in the unix world):
To choose what methods to use for your own program, examine many programs from the canon of accepted practice before you freeze your own choices, read some blogs, read some books...
Configuration files are probably the most portable across operating systems.
The treatment can get fairly complicated. If the command line arguments might affect the interpretation of config files or environment variable, but you still want the command line to overrule the other mechanisms (a good idea) you may need three passes:
In the unix tradition look at getopt
and getopt_long
. Also consider tools like gengetopt
You can simplify you config file problem by making them shell scripts that set environment variables (but this locks you into a unix model). Parsing plain text is easy and cross platform, but makes more code to write. Using a standard format and a library puts requirements on your user's build environment, but should save on bugs and confusion.
If your configuration environment is complicated, it is very helpful to encapsulate the configuration state in a structure which can be passed around as needed. This is the approach taken by gengetopt
, and I have found it to be useful.
Upvotes: 2
Reputation: 399753
There are tons of libraries for dealing with configuration file parsing, for various formats. Look for XML and INI formats, for two popular choices. Writing a custom parser is probably a bad idea, since it can be a lot of work for little or no gain. Here is a random C library for parsing INI files, XML is left as an exercise.
The priority between settings is usually such that command line options override any "environmental" settings. I would suggest priorities like this, in falling order of importance:
But the 2 and 3 might well be flipped.
Upvotes: 2