diff options
authorvenaas <venaas>2008-12-04 13:56:08 +0000
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>2008-12-04 13:56:08 +0000
commite27f064917ced2a96199c738435ea5fe96c0ea8e (patch)
parent013224404c50da993cece7db726027d1746b6668 (diff)
adding gconfig doc
git-svn-id: e88ac4ed-0b26-0410-9574-a7f39faa03bf
1 files changed, 160 insertions, 0 deletions
diff --git a/gconfig.txt b/gconfig.txt
new file mode 100644
index 0000000..ec77545
--- /dev/null
+++ b/gconfig.txt
@@ -0,0 +1,160 @@
+Documentation for gconfig
+gconfig is a configuration file parser. It is generic in the sense that it can
+be used for different applications that need different configuration keywords
+and value. There is however a fixed syntax.
+The basic syntax is
+option-name value
+option-name = value
+where white space is used as delimiters, where you can have any amount of
+whitespace (spaces and tabs) where there is a space above. option-name cannot
+contain spaces. A value can contain spaces if the value is quoted. E.g.
+option-name = "option value"
+There is a special keyword "include" used for including config files.
+Anywhere in a config file one can write "include filespec". At that
+point the entire content of a file pointed to by filespec will be
+inserted. When the end of the file is read, the config parser will
+continue with whatever is after include. "filespec" can use UNIX
+shell type globbing, so you may do e.g. "include /etc/gconf.d/*" to
+include everything in that directory. This will behave exactly like
+including each of the files separately (in alphabetic order).
+In addition to this, one may also group options together into
+blocks, where blocks also have names.
+A block has the syntax
+type name {
+ option-name value
+ option-name value
+ ...
+The application specifies which block types are valid, and which
+option-names and syntaxes can be used for each of the types.
+The available option syntaxes (or types) are String, Integer and
+Usually the same option-name cannot be repeated (unless in different
+blocks). For Strings one can specify whether it is allowed or not.
+Also, for strings one can use hex notation for bytes. This works
+similar to URL hex escaping. E.g. a space can be written as "%20".
+radsecproxy uses gconfig and shows what is possible. Here is an
+example extracted from getmainconfig() from radsecproxy.
+struct gconffile *cfs;
+cfs = openconfigfile(configfile);
+ if (!getgenericconfig(&cfs, NULL,
+ "ListenUDP", CONF_MSTR, &listenudp,
+ "LogDestination", CONF_STR, &logdestination,
+ "LogLevel", CONF_LINT, &loglevel,
+ "LoopPrevention", CONF_BLN, &loopprevention,
+ "Client", CONF_CBK, confclient_cb, NULL,
+ ))
+ debugx(1, DBG_ERR, "configuration error"); /* exit */
+ /* parsing successful, continue normal operations */
+The arguments to getgenericconfig are as follows. First there is a
+gconffile struct, this is normally a single file, but as we discuss later,
+it can also be a list of files (or data). The second parameter should be
+NULL when not in a block, or the block name if inside one. This is only
+used for logging.
+After this one lists all the legal option and block names that are allowed.
+For each option one specifies a name followed by a syntax type and a pointer to
+the variable that will hold the value. The syntax types are CONF_STR for a
+string, CONF_MSTR for string when the option can be used multiple times,
+CONF_LINT for Integer (long int), CONF_BLN for Boolean ("on" or "off"). For
+blocks one uses CONF_CBK followed by a callback function for handling the
+block, and a pointer to userdata that can be passed to the callback. Normally
+this would just be set to NULL.
+We will now discuss each of the syntax types and blocks in more detail.
+This is used for strings. The value argument must be of type "char **". If
+the option is found in the config, it will allocate memory for a null-terminated
+copy of the string and return a pointer to this. The value argument is not
+modified if the option is not used. In the example above, one might do
+"char *logdestination = NULL". One then uses &logdestination for the
+argument, and can check for NULL to see whether the option was present.
+This is used for strings when the option can be used multiple times. It
+will return an array of strings in the order they are found in the config.
+The value argument must be of type "char ***". One might do
+"char **listenudp = NULL", and use &listenudp for the argument. Memory will
+be allocated for the array and the strings if the option is used. If no
+options are found, the value is unchanged. If there is at least one value,
+one will get an array of strings, and the last element of the array will be
+set to NULL.
+The option value argument must be of type "long int *". If the option is
+present, the value will be set, else it will not be modified.
+The option value argument must be of type "uint8_t *". It is set to 0 or 1
+for "off" or "on" resp. It is only modified if the option is found.
+This is a block where one uses a call back. Here is an example callback:
+int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
+ *val) {
+ char *type = NULL, *host = NULL;
+ debug(DBG_DBG, "confclient_cb called for %s", block);
+ if (!getgenericconfig(cf, block,
+ "type", CONF_STR, &type,
+ "host", CONF_STR, &host,
+ ))
+ debugx(1, DBG_ERR, "configuration error"); /* exit */
+ /* parsing successful, continue normal operations */
+Here cf is the list of config files we're using, arg is a pointer to
+userdata (the parameter after the name of the callback function, often
+this is just set to NULL). opt is the type of block, in this case it will
+be set to "client". val is the value of the block. E.g. if the config said
+client example {
+ type udp
+ host
+then val will be set to "example". The string block is set to
+"client example" (opt val) and is normally just used for logging.
+Note that the opt, val and optval parameters to the callback will all be
+freed when the callback function exits.
+The gconffile struct can hold a list of config files. Typically one would
+just use cfs = openconfigfile(configfile) as above. But one can use any of
+the ones below. It can be used to create a new struct (a pointer to NULL),
+or a pointer to an existing struct where new files are pushed (as a stack).
+The latest pushed is used first, when that is used it continues reading
+from the next.
+int pushgconfdata(struct gconffile **cf, const char *data);
+This can be used to read config stored in memory
+FILE *pushgconfpath(struct gconffile **cf, const char *path);
+Here one specifies a file path (no globbing)
+FILE *pushgconfpaths(struct gconffile **cf, const char *path);
+Here one specifies a filespec with globbing. In case of multiple files,
+they are pushed in reverse alphabetical order so that the alphabetically
+first file is read first.
+FILE *pushgconffile(struct gconffile **cf, FILE *file, const char *description);
+This can be used for reading config from an already open file descriptor.
+For a complete example, see radsecproxy.