195 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
.TH CONFIGFILE 3
 | 
						|
.SH NAME
 | 
						|
configfile, config_read, config_delete, config_renewed, config_length, config_issub, config_isatom, config_isstring \- generic configuration file functions
 | 
						|
.SH SYNOPSIS
 | 
						|
.ft B
 | 
						|
.nf
 | 
						|
#include <configfile.h>
 | 
						|
 | 
						|
config_t *config_read(const char *\fIfile\fP, int \fIflags\fP, config_t *\fIcfg\fP)
 | 
						|
void config_delete(config_t *\fIcfg\fP)
 | 
						|
int config_renewed(config_t *\fIcfg\fP)
 | 
						|
size_t config_length(config_t *\fIcfg\fP)
 | 
						|
int config_issub(config_t *\fIcfg\fP)
 | 
						|
int config_isatom(config_t *\fIcfg\fP)
 | 
						|
int config_isstring(config_t *\fIcfg\fP)
 | 
						|
.fi
 | 
						|
.ft P
 | 
						|
.SH DESCRIPTION
 | 
						|
The
 | 
						|
.B configfile
 | 
						|
routines operate on a generic configuration file that follows the syntax
 | 
						|
described in
 | 
						|
.BR configfile (5).
 | 
						|
.PP
 | 
						|
The interface presented by the functions above uses the following type and
 | 
						|
definitions from <configfile.h>:
 | 
						|
.PP
 | 
						|
.if n .in +2
 | 
						|
.if t .RS
 | 
						|
.nf
 | 
						|
.ta +\w'type'u +\w'const charmm'u +\w'word[];mm'u
 | 
						|
typedef const struct config {
 | 
						|
	config_t	*next;	/* Next configuration file thing. */
 | 
						|
	config_t	*list;	/* For a { sublist }. */
 | 
						|
	const char	*file;	/* File and line where this is found. */
 | 
						|
	unsigned	line;
 | 
						|
	int	flags;	/* Special flags. */
 | 
						|
	char	word[];	/* Payload. */
 | 
						|
} config_t;
 | 
						|
 | 
						|
.ta +\w'#definem'u +\w'CFG_SUBLISTm'u +\w'0x0000mm'u
 | 
						|
#define	CFG_CLONG	0x0001	/* strtol(word, &end, 0) is valid. */
 | 
						|
#define	CFG_OLONG	0x0002	/* strtol(word, &end, 010). */
 | 
						|
#define	CFG_DLONG	0x0004	/* strtol(word, &end, 10). */
 | 
						|
#define	CFG_XLONG	0x0008	/* strtol(word, &end, 0x10). */
 | 
						|
#define	CFG_CULONG	0x0010	/* strtoul(word, &end, 0). */
 | 
						|
#define	CFG_OULONG	0x0020	/* strtoul(word, &end, 010). */
 | 
						|
#define	CFG_DULONG	0x0040	/* strtoul(word, &end, 10). */
 | 
						|
#define	CFG_XULONG	0x0080	/* strtoul(word, &end, 0x10). */
 | 
						|
#define	CFG_STRING	0x0100	/* The word is enclosed in quotes. */
 | 
						|
#define	CFG_SUBLIST	0x0200	/* This is a sublist, so no word. */
 | 
						|
#define	CFG_ESCAPED	0x0400	/* Escapes are still marked with \e. */
 | 
						|
.fi
 | 
						|
.if n .in -2
 | 
						|
.if t .RE
 | 
						|
.PP
 | 
						|
In memory a configuration file is represented as a list of
 | 
						|
.B config_t
 | 
						|
cells linked together with the
 | 
						|
.B next
 | 
						|
field ending with a null pointer.  A sublist between braces is attached to a
 | 
						|
cell at the
 | 
						|
.B list
 | 
						|
field.
 | 
						|
Words and strings are put in the
 | 
						|
.B word
 | 
						|
field, a null terminated string.  The
 | 
						|
.B flags
 | 
						|
field records the type and features of a cell.  The
 | 
						|
.B CFG_*LONG
 | 
						|
flags are set if a word is a number according to one of the
 | 
						|
.B strtol
 | 
						|
or
 | 
						|
.B strtoul
 | 
						|
calls.  Purely a number, no quotes or trailing garbage.  The
 | 
						|
.B CFG_STRING
 | 
						|
flag is set if the object was enclosed in double quotes.  Lastly
 | 
						|
.B CFG_SUBLIST
 | 
						|
tells if the cell is only a pointer to a sublist in braces.
 | 
						|
.PP
 | 
						|
Characters in a word or string may have been formed with the
 | 
						|
.B \e
 | 
						|
escape character.  They have been parsed and expanded, but the \e is still
 | 
						|
present if
 | 
						|
.B CFG_ESCAPED
 | 
						|
is set.  The
 | 
						|
.B word
 | 
						|
array may be changed, as long as it doesn't grow longer, so one may remove
 | 
						|
the \es like this:
 | 
						|
.PP
 | 
						|
.RS
 | 
						|
.ta +4n +4n
 | 
						|
.nf
 | 
						|
if (cfg->flags & CFG_ESCAPED) {
 | 
						|
	char *p, *q;
 | 
						|
	p= q= cfg->word;
 | 
						|
	for (;;) {
 | 
						|
		if ((*q = *p) == '\e\e') *q = *++p;
 | 
						|
		if (*q == 0) break;
 | 
						|
		p++;
 | 
						|
		q++;
 | 
						|
	}
 | 
						|
}
 | 
						|
.fi
 | 
						|
.RE
 | 
						|
.PP
 | 
						|
The low level syntax of a config file is checked when it is read.  If an
 | 
						|
error is encountered a message is printed and the program exits with exit
 | 
						|
code 1.  What the data means is not checked, that
 | 
						|
should be done by the program using the data.  Only the atom
 | 
						|
.B include
 | 
						|
at the beginning of a list is special.  It should be followed by a string.
 | 
						|
The string is seen as the name of a file, that is opened, read, and inserted
 | 
						|
in place of the
 | 
						|
.BR include .
 | 
						|
Unless the name of the file starts with a
 | 
						|
.BR / ,
 | 
						|
it is sought relative to the directory the current file is found in.
 | 
						|
Nonexistent files are treated as being empty.
 | 
						|
.PP
 | 
						|
The
 | 
						|
.B file
 | 
						|
and
 | 
						|
.B line
 | 
						|
fields in each cell tell where the cell was read.
 | 
						|
.SS Functions
 | 
						|
A configuration file is read with
 | 
						|
.BR config_read .
 | 
						|
The first argument is the file to read.  The second is either
 | 
						|
.B 0
 | 
						|
or
 | 
						|
.B CFG_ESCAPED
 | 
						|
to tell whether \e escapes should be fully expanded without leaving a trace,
 | 
						|
or if they should still be marked with a \e so that the caller knows where
 | 
						|
the excapes are.
 | 
						|
The third argument,
 | 
						|
.IR cfg ,
 | 
						|
should be a null pointer on the first call.  If you want to reread a config
 | 
						|
file that may have changed then
 | 
						|
.I cfg
 | 
						|
should be what you previously read.
 | 
						|
.PP
 | 
						|
With
 | 
						|
.B config_delete
 | 
						|
one can free up the memory that has been acquired with
 | 
						|
.BR malloc (3)
 | 
						|
to hold the contents of the configuration file.
 | 
						|
.PP
 | 
						|
To determine if the contents of configuration file has changed when reread
 | 
						|
one uses
 | 
						|
.BR config_renewed
 | 
						|
after
 | 
						|
.BR config_read .
 | 
						|
It returns a "changed" flag that is set when the configuration file changed
 | 
						|
and then clears that flag.  It returns true on the very first call.  For the
 | 
						|
function to work you need to feed the old data back into
 | 
						|
.BR config_read ,
 | 
						|
not delete and reread.
 | 
						|
.PP
 | 
						|
The length of a series of config structures is told by
 | 
						|
.BR config_length .
 | 
						|
It follows the
 | 
						|
.B next
 | 
						|
fields, so a sublist between braces counts as one extra.
 | 
						|
.PP
 | 
						|
The
 | 
						|
.BR config_issub ,
 | 
						|
.BR config_isatom
 | 
						|
and
 | 
						|
.BR config_isstring
 | 
						|
functions are just pretty macros to test if a cell references a sublist, is
 | 
						|
a word/string, or is just a string.
 | 
						|
.B CFG_SUBLIST
 | 
						|
and
 | 
						|
.B CFG_STRING
 | 
						|
tell the same story.
 | 
						|
.SH FILES
 | 
						|
.TP \w'*/etc/*.confmmmm'u
 | 
						|
.B */etc/*.conf
 | 
						|
Several files in several
 | 
						|
.B etc
 | 
						|
directories.
 | 
						|
.SH "SEE ALSO"
 | 
						|
.BR configfile (5).
 | 
						|
.SH NOTES
 | 
						|
The syntax of a config file puts some constraints on what you find in memory.
 | 
						|
The top level list consists entirely of sublist cells.  These point to lists
 | 
						|
that start with at least an atom, followed by a mix of atoms and sublist cells.
 | 
						|
These sublists in turn point to a list of only sublist cells (recurse now.)
 | 
						|
.PP
 | 
						|
The struct config shown above is not exactly proper C to aid
 | 
						|
readability, read <configfile.h> itself to see why.
 | 
						|
.SH AUTHOR
 | 
						|
Kees J. Bot (kjb@cs.vu.nl)
 |