NAME

     configfile,  config_read,   config_delete,   config_renewed,
     config_length,  config_issub, config_isatom, config_isstring
     - generic configuration file functions


SYNOPSIS

     #include <configfile.h>

     config_t *config_read(const char *file, int flags, config_t *cfg)
     void config_delete(config_t *cfg)
     int config_renewed(config_t *cfg)
     size_t config_length(config_t *cfg)
     int config_issub(config_t *cfg)
     int config_isatom(config_t *cfg)
     int config_isstring(config_t *cfg)


DESCRIPTION

     The configfile routines operate on a  generic  configuration
     file that follows the syntax described in configfile(5).

     The interface presented by the functions above uses the fol-
     lowing type and definitions from <configfile.h>:

       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;

       #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 \. */

     In memory a configuration file is represented as a  list  of
     config_t  cells  linked  together with the next field ending
     with a null pointer.  A sublist between braces  is  attached
     to  a  cell at the list field.  Words and strings are put in
     the word field, a null terminated string.  The  flags  field
     records  the  type  and  features  of a cell.  The CFG_*LONG
     flags are set if a word is a number according to one of  the
     strtol  or  strtoul  calls.   Purely  a number, no quotes or
     trailing garbage.  The CFG_STRING flag is set if the  object
     was  enclosed in double quotes.  Lastly CFG_SUBLIST tells if
     the cell is only a pointer to a sublist in braces.

     Characters in a word or string may have been formed with the
     \ escape character.  They have been parsed and expanded, but
     the \ is still present if  CFG_ESCAPED  is  set.   The  word
     array  may be changed, as long as it doesn't grow longer, so
     one may remove the \s like this:

          if (cfg->flags & CFG_ESCAPED) {
              char *p, *q;
              p= q= cfg->word;
              for (;;) {
                  if ((*q = *p) == '\\') *q = *++p;
                  if (*q == 0) break;
                  p++;
                  q++;
              }
          }

     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 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 include.  Unless the name of the
     file starts with a /, it is sought relative to the directory
     the current file is found in.  Nonexistent files are treated
     as being empty.

     The file and line fields in each cell tell  where  the  cell
     was read.

  Functions
     A configuration file is read with  config_read.   The  first
     argument  is  the  file  to read.  The second is either 0 or
     CFG_ESCAPED to  tell  whether  \  escapes  should  be  fully
     expanded without leaving a trace, or if they should still be
     marked with a \ so that the caller knows where  the  excapes
     are.   The  third argument, cfg, should be a null pointer on
     the first call.  If you want to reread a  config  file  that
     may  have  changed  then  cfg  should be what you previously
     read.

     With config_delete one can free up the memory that has  been
     acquired  with  malloc(3) to hold the contents of the confi-
     guration file.


     To determine if  the  contents  of  configuration  file  has
     changed   when   reread   one   uses   config_renewed  after
     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 config_read,
     not delete and reread.

     The length of a series  of  config  structures  is  told  by
     config_length.   It  follows  the  next fields, so a sublist
     between braces counts as one extra.

     The config_issub, config_isatom  and  config_isstring  func-
     tions  are just pretty macros to test if a cell references a
     sublist, is a word/string, or is just a string.  CFG_SUBLIST
     and CFG_STRING tell the same story.


FILES

     */etc/*.conf    Several files in several etc directories.


SEE ALSO

     configfile(5).


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.)

     The struct config shown above is not exactly proper C to aid
     readability, read <configfile.h> itself to see why.


AUTHOR

     Kees J. Bot (kjb@cs.vu.nl)