/* silcconfig.h Author: Johnny Mnemonic Copyright (C) 1997 - 2002 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ /****h* silcutil/SilcConfigAPI * * DESCRIPTION * * The SILC Config util library is based on two main objects, SilcConfigFile * (or File object) and SilcConfigEntity (or Entity). The File objects are * structs directly corresponding to the real files in the filesystem, while * Entities are a little more abstract. * * An Entity is composed by delimited area on a File object (it can take the * whole File object or just part of it), plus a group of known options. * In order to parse this file, first you need to create a File object with * the silc_config_open() function, and then you need to create the Entity * with the silc_config_init() function. * * Now you can use the newly created Entity to register a group of expected * known options and sub-blocks, and then you can call the main parsing loop * with the silc_config_main() function. When silc_config_main() will * return, if some error encoured the object file will point to the file * that caused this error (this can be different from the originally * opened file if it contained `Include' directives). If no errors * encoured then the File objects will still point to the original file. * * While silc_config_main() will take care of destroying Entities before * returning, you need to take care that the File object you created is freed * with the silc_config_close() function. * * The SILC Config library won't take care about storing the values contained * in the config file. You must take care about it with the callback * functions. * * The config file syntax is pretty straightforward. All lines starting * with `#' will be skipped, while sub-blocks are delimited by braces (see * the example below). * * Options with argument must have the `=' character between the option * name and the value. Simple words and numbers does not require quoting. * There is a special built-in directive "Include" which allows you to include * another config file in the point the directive is. You can also Include * inside a sub-block body, in this case when parsing the included config file * it will be assumed that we are within this block, and the included file * won't be allowed to close his root block. * * Example: * * cipher { * name = aes-256-cbc; * module = "aes.sim.so"; * key_length = 32; # usually the default is just fine * block_length = 16; * }; * Include "/etc/silc/hash_funcs.conf"; * ***/ #ifndef SILCCONFIG_H #define SILCCONFIG_H /****d* silcutil/SilcConfigAPI/errno * * NAME * * enum { ... } - describe a SILC Config error * * DESCRIPTION * * The virtual integer `errno' is returned by the silc_config_main() * function and indicates what went wrong. * You can convert it to the corresponding error string with the function * silc_config_strerror(). * * SOURCE */ enum { SILC_CONFIG_OK, /* OK */ SILC_CONFIG_ESILENT, /* Error defined by callback function */ SILC_CONFIG_EGENERIC, /* Invalid syntax */ SILC_CONFIG_EINTERNAL, /* Internal Error (caused by developer) */ SILC_CONFIG_ECANTOPEN, /* Can't open specified file */ SILC_CONFIG_EOPENBRACE, /* Expected open-brace '{' */ SILC_CONFIG_ECLOSEBRACE, /* Missing close-brace '}' */ SILC_CONFIG_ETYPE, /* Invalid data type */ SILC_CONFIG_EBADOPTION, /* Unknown option */ SILC_CONFIG_EINVALIDTEXT, /* Invalid text */ SILC_CONFIG_EDOUBLE, /* Double option specification */ SILC_CONFIG_EEXPECTED, /* Expected data but not found */ SILC_CONFIG_EEXPECTEDEQUAL, /* Expected '=' */ SILC_CONFIG_EUNEXPECTED, /* Unexpected data */ SILC_CONFIG_EMISSFIELDS, /* Missing mandatory fields */ SILC_CONFIG_EMISSCOLON, /* Missing ';' */ }; /***/ /****d* silcutil/SilcConfigAPI/SilcConfigType * * NAME * * typedef enum { ... } SilcConfigType; * * DESCRIPTION * * This identifies the parameter type that an option has. This parameter * is very important because the callback's *val pointer points to a * memory location containing the previously specified data type. * For example, if you specified an option with an integer parameter * callback's *val will be a pointer to an integer. * * SOURCE */ typedef enum { SILC_CONFIG_ARG_TOGGLE, /* TOGGLE on,off; yes,no; true, false; */ SILC_CONFIG_ARG_INT, /* callback wants an integer */ SILC_CONFIG_ARG_STR, /* callback expects \0-terminated str */ SILC_CONFIG_ARG_STRE, /* same as above, but can also be empty */ SILC_CONFIG_ARG_BLOCK, /* this is a sub-block */ SILC_CONFIG_ARG_SIZE, /* like int, but accepts suffixes kMG */ SILC_CONFIG_ARG_NONE, /* does not expect any args */ } SilcConfigType; /***/ /****f* silcutil/SilcConfigAPI/SilcConfigCallback * * SYNOPSIS * * typedef int (*SilcConfigCallback)(SilcConfigType type, const char *name, * SilcUInt32 line, void *val, void *context); * DESCRIPTION * * This is the callback prototype for the options handler. The pointer * `val' points to a location of type described by `type'. `name' points * to a null-terminated string with the name of the option which triggered * this callback, that is stated at line `line'. `context' is the * user-specified context provided when this option was registered. * ***/ typedef int (*SilcConfigCallback)(SilcConfigType type, const char *name, SilcUInt32 line, void *val, void *context); /****s* silcutil/SilcConfigAPI/SilcConfigTable * * SYNOPSIS * * typedef struct { ... } SilcConfigTable; * * DESCRIPTION * * SILC Config table defines an easy and quick way of registering options * in an entity. The function silc_config_register_table() will take as * argument a SilcConfigTable array terminated by a NULL struct, it is * important thus, that the `name' field of the terminating struct is set * to NULL. * * char *name * * The option name lowercase. The matching is always case-insensitive, * but for convention the option specification must always be lowercase. * * SilcConfigType type * * This specifies what kind of parameter this option expects. The * special cases SILC_CONFIG_ARG_BLOCK tells SILC Config that this is * not a normal option but the name of a sub-block of the current * block (there is no limit to the number of nested blocks allowed). * * SilcConfigCallback callback * * Normally this is the value handler of the current option. If this * field is set to NULL then the value is silently discarded. Useful * for example to support deprecated options. * * SilcConfigTable *subtable * * If the `type' field is set to SILC_CONFIG_ARG_BLOCK, then this field * must point to a valid sub-table NULL-terminated array. If `type' is * something else, this valued is unused. * ***/ typedef struct SilcConfigTableStruct { char *name; SilcConfigType type; SilcConfigCallback callback; const struct SilcConfigTableStruct *subtable; } SilcConfigTable; /****s* silcutil/SilcConfigAPI/SilcConfigFile * * SYNOPSIS * * typedef struct { ... } SilcConfigFile; * * DESCRIPTION * * A File object holds the data contained in a previously loaded file by * the silc_config_open() function. * This is an internally allocated struct and must be used only with the * helper functions. * ***/ typedef struct SilcConfigFileObject SilcConfigFile; /****s* silcutil/SilcConfigAPI/SilcConfigEntity * * SYNOPSIS * * typedef struct { ... } SilcConfigEntity; * * DESCRIPTION * * The SILC Config is based on config entities. An entity contains the * SilcConfigFile object we are parsing and the registered options. * ***/ typedef struct SilcConfigEntityObject *SilcConfigEntity; /* Macros */ /****d* silcutil/SilcConfigAPI/SILC_CONFIG_CALLBACK * * NAME * * #define SILC_CONFIG_CALLBACK ... * * DESCRIPTION * * Generic macro to define SilcConfigCallback functions. This defines a * static function with name `func' as a config callback function. * * SOURCE */ #define SILC_CONFIG_CALLBACK(func) \ static int func(SilcConfigType type, const char *name, \ SilcUInt32 line, void *val, void *context) /***/ /* Prototypes */ /****f* silcutil/SilcConfigAPI/silc_config_open * * SYNOPSIS * * SilcConfigFile *silc_config_open(char *configfile); * * DESCRIPTION * * Tries to open the config file `configfile' and returns a valid File * object on success, or NULL on failure. * An File object created this way must be destroyed with the function * silc_config_close(). * ***/ SilcConfigFile *silc_config_open(char *configfile); /****f* silcutil/SilcConfigAPI/silc_config_close * * SYNOPSIS * * void silc_config_close(SilcConfigFile *file); * * DESCRIPTION * * Closes and frees the File object `file', which must have been returned * by a previous call to silc_config_open(). Otherwise, or if * this function has already been called before for the same File object, * undefined behaviour occurs. * If `file' is NULL, no operation is performed. * ***/ void silc_config_close(SilcConfigFile *file); /****f* silcutil/SilcConfigAPI/silc_config_init * * SYNOPSIS * * SilcConfigEntity silc_config_init(SilcConfigFile *file); * * DESCRIPTION * * Creates an Entity pointing to the valid File object `file', which must * be returned by a previous call to silc_config_open(), otherwise NULL * is returned. * Entities will be automatically destroyed after the call to the * silc_config_main() function, because of this no uninit functions are * provided. * ***/ SilcConfigEntity silc_config_init(SilcConfigFile *file); /****f* silcutil/SilcConfigAPI/silc_config_strerror * * SYNOPSIS * * char *silc_config_strerror(int errnum); * * DESCRIPTION * * The silc_config_strerror() function returns a string describing the * error code passed in the argument `errnum'. * ***/ char *silc_config_strerror(int errnum); /****f* silcutil/SilcConfigAPI/silc_config_get_filename * * SYNOPSIS * * char *silc_config_get_filename(SilcConfigFile *file); * * DESCRIPTION * * Returns the original filename of the object file. * The returned pointer points to internally allocated storage and must * not be freed, modified or stored. * ***/ char *silc_config_get_filename(SilcConfigFile *file); /****f* silcutil/SilcConfigAPI/silc_config_get_line * * SYNOPSIS * * SilcUInt32 silc_config_get_line(SilcConfigFile *file); * * DESCRIPTION * * Returns the current line that file parsing arrived at. * ***/ SilcUInt32 silc_config_get_line(SilcConfigFile *file); /****f* silcutil/SilcConfigAPI/silc_config_read_line * * SYNOPSIS * * char *silc_config_read_line(SilcConfigFile *file, SilcUInt32 line); * * DESCRIPTION * * Returns a dynamically allocated null-terminated buffer containing the * line `line' of `file'. * The returned pointer must be freed when it's not needed any longer. * * SEE ALSO * silc_config_read_current_line * ***/ char *silc_config_read_line(SilcConfigFile *file, SilcUInt32 line); /****f* silcutil/SilcConfigAPI/silc_config_read_current_line * * SYNOPSIS * * char *silc_config_read_current_line(SilcConfigFile *file); * * DESCRIPTION * * Returns a dynamically allocated buffer containing the line that the * parser stopped at. This is a convenience function for * silc_config_read_line. * The returned pointer must be freed when it's not needed any longer. * ***/ char *silc_config_read_current_line(SilcConfigFile *file); /****f* silcutil/SilcConfigAPI/silc_config_register * * SYNOPSIS * * bool silc_config_register(SilcConfigEntity ent, const char *name, * SilcConfigType type, SilcConfigCallback cb, * const SilcConfigTable *subtable, * void *context); * * DESCRIPTION * * Register option `name' in the entity `ent'. If `cb' is not NULL, it * will be called with the *val pointer pointing to an internally * allocated storage of type described by `type'. * If `type' is SILC_CONFIG_ARG_BLOCK, then `subtable' must be a valid * pointer to a SilcConfigTable array specifying the options in the * sub-block. * If the option `name' was already registered in this sub-block or it * matches the reserved word "Include", then this function returns FALSE, * otherwise it returns TRUE. * * SEE ALSO * silc_config_register_table * ***/ bool silc_config_register(SilcConfigEntity ent, const char *name, SilcConfigType type, SilcConfigCallback cb, const SilcConfigTable *subtable, void *context); /****f* silcutil/SilcConfigAPI/silc_config_register_table * * SYNOPSIS * * bool silc_config_register_table(SilcConfigEntity ent, * const SilcConfigTable table[], * void *context); * * DESCRIPTION * * Register the tableset of options `table' automatically in the entity * `ent'. If defined in the table, the callback functions will be called * all with the same context `context'. * The `table' array must be terminated with an entry with the name field * set to NULL. * If the table contains invalid data this function returns FALSE, otherwise * it returns TRUE. If a calling to this function failed, you must destroy * and recreate the entity before retrying, as it's impossible to detect * the point at the function stopped the registering process. * * SEE ALSO * SilcConfigTable * ***/ bool silc_config_register_table(SilcConfigEntity ent, const SilcConfigTable table[], void *context); /****f* silcutil/SilcConfigAPI/silc_config_main * * SYNOPSIS * * int silc_config_main(SilcConfigEntity ent); * * DESCRIPTION * * Enter the main parsing loop. When this function returns the parsing * is finished in the current block (and sub-blocks). * When this function exits, the entity is already destroyed, because * of this you should set it to NULL right after the function call. * ***/ int silc_config_main(SilcConfigEntity ent); #endif /* !SILCCONFIG_H */