The Syntax and Structure of kunf Files
Lexical Rules
The lexical rules determine how a stream of characters is resolved into
tokens. The kunf library uses a reasonably standard set of rules.
It allows shell style comments (Anything between a hash ( # )
and a newline) and allows you to escape special characters.
Here is an itemized description of the rules. Where there appears a
conflict between rules the earlier rule takes precedence:
- A sequence of characters is a single token if it delimited by
double quotes.
- Characters following a hash are ignored until a newline is encountered.
- Whitespaces, unless part of a token enclosed by double quotes, only delimit
tokens and are not tokens themselves.
- Tokens not enclosed by double quotes are delimited by whitespaces,
angle brackets ( <> , square braces ( [] ), equal
signs ( = ) and colons ( : ).
- Unless part of a token enclosed by double quotes the following characters
are separate tokens: angle brackets, square braces, equal signs and colons.
- Characters preceded by a backslash ( \ ) or a percentage
sign ( % ) have a special meaning. Backslash escapes can be used
to escape newlines and quotes, while percentage escapes can be used
to specify host, group and user specific attributes.
Percentage Escapes
These escapes are entirely transparent to the client program - in
most cases the calling program will not be able (and should not need) to
distinguish between generated and fixed values. These escapes allow
the system administrator to construct a single configuration hierarchy.
There is thus no need for the client program to explicitly parse global
(/etc/foo.conf) and per user (~/.foorc) configuration files,
since the system administrator can decide how to distribute configuration
data between system-wide configuration files (rooted at /etc/root.kunf)
and user files (such as ~/.foo.kunf).
- %%
- : Percentage Sign
- %A
- : Hardware Architecture
- %D
- : Domain Name
- %G
- : Real Group ID
- %H
- : Host Name
- %N
- : GECOS Field
- %R
- : Operating System Release
- %U
- : Real User ID
- %V
- : Operating System Version
- %d
- : Home Directory
- %g
- : Effective Group ID
- %l
- : Login Name
- %o
- : Operating System Name
- %p
- : Process ID
- %s
- : Login Shell
- %u
- : Effective User ID
Syntactic Rules
Grammar
The grammar obeys the following conventions:
- Nonterminal are UPPERCASE.
- Terminals are lowercase.
- Bold denotes a literal character.
- Optional items are [enclosed by square braces and rendered in italics].
The grammar below applies to the root configuration file
(/etc/root.kunf) and all redirected files. Included files have a
more restricted grammar which is listed in the next part.
START ::= SECTION*
SECTION ::= HEADER ENTRIES*
HEADER ::= [ NAME [= redirected_file]]
NAME ::= part [: part]*
ENTRIES ::= (INCLUDE | PROPER_ENTRY)*
INCLUDE ::= < included_file >
PROPER_ENTRY ::= label = value [: comment]
The grammar of an included file is restricted to the following (meaning that
you may not define new sections in an included file):
START ::= SECTION*
SECTION ::= ENTRIES*
ENTRIES ::= (INCLUDE | PROPER_ENTRY)*
INCLUDE ::= < include_file >
PROPER_ENTRY ::= label = value [: comment]
Redirection and Inclusion files
The kunf library stores its information in a set of files. How
and where these are located is left to the system administrator, with
only one exception: The file /etc/root.kunf is the starting point
of any lookup. It is analogous to the root directory in a file system,
where each section is a subdirectory, where the entries are regular
files, and where redirection directives are comparable to mount points
or symbolic links.
This setup makes it possible to for the system administrator to decide
where to place configuration data. On the one extreme it is possible to
keep all information in the /etc/root.kunf file, on the other it
is possible to only keep redirection directives in the
/etc/root.kunf file. The applications can be completely unaware
of the location of the data.
Example Cases
Recall the C example which made use of the following sections:
[mail:foo:interface]
fgcolor="bright yellow"
bgcolor="blue"
[mail:foo:identity]
name="J. Soap"
signature="/home/jsoap/.signature"
replyto="jsoap@frogstar5.com"
[mail:foo:backend]
mailbox="/var/spool/mail/jsoap"
tmpdir="/var/tmp"
Using percentage escapes allows one to make these sections global:
[mail:foo:interface]
fgcolor="bright yellow"
bgcolor="blue"
[mail:foo:identity]
name=%N
signature="%d/.signature"
replyto="%l@frogstar5.com"
[mail:foo:backend]
mailbox="/var/spool/mail/%l"
tmpdir="/var/tmp"
And using redirection directives makes it possible to distribute
this information over several files which can have different access
permissions, so that different classes of users can modify or
override them. In the following example the foo configuration
data has been distributed over /etc/root.kunf, /etc/foo.kunf,
/etc/foo.interface.kunf and ~/.foo.identity.
File /etc/root.kunf only redirects the lookup of mail:foo
to file /etc/foo.kunf:
[mail:foo=/etc/foo.kunf] # mail:foo redirected
[news] # other sections start here
nntpserver="nntp.frogstar.com" # proper entry (of form name=value)
File /etc/foo.kunf (Note that in this file the mail:foo
part of the header should not be used since that has already been
inherited from the header in /etc/foo.kunf):
[interface="/etc/foo.interface.kunf"]
# interface redirected
[identity]
<%d/.foo.identity> # include per user config file
name=%N # fallback settings
signature="%d/.signature"
replyto="%l@frogstar5.com"
[backend] # these are fixed
mailbox="/var/spool/mail/%l"
tmpdir="/var/tmp"
File /etc/foo.interface.kunf (here even the interface
header should be omitted):
fgcolor="bright green"
bgcolor="grey"
File /home/jsoap/.foo.identity overrides the default
settings for user jsoap:
name="Joe P Soap (Soaphead)"
signature="/home/jsoap/.funnysig"
replyto="soaphead@soapbox.net"
The net effect of distributing this configuration over several files
is:
- The master control file for foo is /etc/foo.kunf.
You could give an assistant administrator write rights to that file
without compromising other sections.
- The colour scheme is controlled from /etc/foo.interface.kunf,
which could be writable by a selected group of users known for their
ability to select esthetically pleasing colour combinations. These
users enforce a system-wide colour scheme.
- Each user can set his or her own signature file, full name and
replyto address. In the event that a user does not have a
.foo.identity file, the system selects reasonable defaults.
(This works since the function kunfig_findvalue() selects the
first matching entry, effectively ignoring subsequent matches).
And the interesting part is that the user program (foo) is
unaware of this distributed configuration. No recoding needed.
The example should not be able to
distinguish between this configuration and one stored in a single
file.
Hopefully this explanation illustrates the power and convenience
of the library. Otherwise have a look at the picture which depicts
the relationship between the files since I do not
feel like writing another thousand words.
The following image provides an indication of the internal representation
of the configuration data. The data is stored as a tree, and information
can either be looked up directly (see label Z where a single call
extracts the value of a particular entry) or the tree can be navigated
in a series of calls in a fashion similar to a normal directory structure
(see label A, B, C and D). The dotted lines
denote the effect of the function call, while solid arrows indicate the
structure of the tree.
Next: Possible extensions