#ifndef DOTCONF_H #define DOTCONF_H #ifdef __cplusplus extern "C" { #endif /* stdio.h should be included by the application - as the manual page says */ #ifndef _STDIO_H #include /* needed for FILE* */ #endif #ifdef WIN32 # ifndef R_OK #define R_OK 0 # endif #endif /* some buffersize definitions */ #define CFG_BUFSIZE 4096 /* max length of one line */ #define CFG_MAX_OPTION 32 /* max length of any option name */ #define CFG_MAX_VALUE 4064 /* max length of any options value */ #define CFG_MAX_FILENAME 256 /* max length of a filename */ #define CFG_VALUES 16 /* max # of arguments an option takes */ #define CFG_INCLUDEPATH_ENV "DC_INCLUDEPATH" #define WILDCARDS "*?" /* list of supported wild-card characters */ /* constants for type of option */ #define ARG_TOGGLE 0 /* TOGGLE on,off; yes,no; 1, 0; */ #define ARG_INT 1 /* callback wants an integer */ #define ARG_STR 2 /* callback expects a \0 terminated str */ #define ARG_LIST 3 /* wants list of strings */ #define ARG_NAME 4 /* wants option name plus ARG_LIST stuff */ #define ARG_RAW 5 /* wants raw argument data */ #define ARG_NONE 6 /* does not expect ANY args */ #define CTX_ALL 0 /* context: option can be used anywhere */ /* for convenience of terminating the dotconf_options list */ #define LAST_OPTION { "", 0, NULL, NULL } #define LAST_CONTEXT_OPTION { "", 0, NULL, NULL, 0 } #define DOTCONF_CB(__name) const char *__name(command_t *cmd, \ context_t *ctx) #define FUNC_ERRORHANDLER(_name) int _name(configfile_t * configfile, \ int type, long dc_errno, const char *msg) /* some flags that change the runtime behaviour of dotconf */ #define NONE 0 #define CASE_INSENSITIVE 1<<0 /* match option names case insensitive */ #define DONT_SUBSTITUTE 1<<1 /* do not call substitute_env after read_arg */ /* syslog style errors as suggested by Sander Steffann */ #ifdef HAVE_SYSLOG #include #define DCLOG_EMERG LOG_EMERG /* system is unusable */ #define DCLOG_ALERT LOG_ALERT /* action must be taken immediately */ #define DCLOG_CRIT LOG_CRIT /* critical conditions */ #define DCLOG_ERR LOG_ERR /* error conditions */ #define DCLOG_WARNING LOG_WARNING /* warning conditions */ #define DCLOG_NOTICE LOG_NOTICE /* normal but significant condition */ #define DCLOG_INFO LOG_INFO /* informational */ #define DCLOG_DEBUG LOG_DEBUG /* debug-level messages */ #define DCLOG_LEVELMASK LOG_PRIMASK /* mask off the level value */ #else /* HAVE_SYSLOG */ #define DCLOG_EMERG 0 /* system is unusable */ #define DCLOG_ALERT 1 /* action must be taken immediately */ #define DCLOG_CRIT 2 /* critical conditions */ #define DCLOG_ERR 3 /* error conditions */ #define DCLOG_WARNING 4 /* warning conditions */ #define DCLOG_NOTICE 5 /* normal but significant condition */ #define DCLOG_INFO 6 /* informational */ #define DCLOG_DEBUG 7 /* debug-level messages */ #define DCLOG_LEVELMASK 7 /* mask off the level value */ #endif /* HAVE_SYSLOG */ /* callback types for dotconf_callback */ /* error constants */ #define ERR_NOERROR 0x0000 #define ERR_PARSE_ERROR 0x0001 #define ERR_UNKNOWN_OPTION 0x0002 #define ERR_WRONG_ARG_COUNT 0x0003 #define ERR_INCLUDE_ERROR 0x0004 #define ERR_NOACCESS 0x0005 #define ERR_USER 0x1000 /* base for userdefined errno's */ /* i needed this to check an ARG_LIST entry if it's toggled in one of my apps; maybe you do too */ #define CFG_TOGGLED(_val) ( (_val[0] == 'Y' \ || _val[0] == 'y') \ || (_val[0] == '1') \ || ((_val[0] == 'o' \ || _val[0] == 'O') \ && (_val[1] == 'n' \ || _val[1] == 'N'))) enum callback_types { ERROR_HANDLER = 1, CONTEXT_CHECKER }; typedef enum callback_types callback_types; typedef struct configfile_t configfile_t; typedef struct configoption_t configoption_t; typedef struct configoption_t ConfigOption; typedef struct command_t command_t; typedef void context_t; typedef void info_t; typedef const char *(*dotconf_callback_t)(command_t *, context_t *); typedef int (*dotconf_errorhandler_t)(configfile_t *, int, unsigned long, const char *); typedef const char *(*dotconf_contextchecker_t)(command_t *, unsigned long); struct configfile_t { /* ------ the fields in configfile_t are provided to the app via command_t's ; READ ONLY! --- */ FILE *stream; char eof; /* end of file reached ? */ size_t size; /* file size; cached on-demand for here-documents */ context_t *context; configoption_t const **config_options; int config_option_count; /* ------ misc read-only fields ------------------------------------------------------------- */ char *filename; /* name of file this option was found in */ unsigned long line; /* line number we're currently at */ unsigned long flags; /* runtime flags given to dotconf_open */ char *includepath; /* ------ some callbacks for interactivity -------------------------------------------------- */ dotconf_errorhandler_t errorhandler; dotconf_contextchecker_t contextchecker; int (*cmp_func)(const char *, const char *, size_t); }; struct configoption_t { const char *name; /* name of configuration option */ int type; /* for possible values, see above */ dotconf_callback_t callback; /* callback function */ info_t *info; /* additional info for multi-option callbacks */ unsigned long context; /* context sensitivity flags */ }; struct command_t { const char *name; /* name of the command */ configoption_t *option; /* the option as given in the app; READ ONLY */ /* ------ argument data filled in for each line / command ----------------------------------- */ struct { long value; /* ARG_INT, ARG_TOGGLE */ char *str; /* ARG_STR */ char **list; /* ARG_LIST */ } data; int arg_count; /* number of arguments (in data.list) */ /* ------ misc context information ---------------------------------------------------------- */ configfile_t *configfile; context_t *context; }; /* ------ dotconf_create() - create the configfile_t needed for further dot.conf fun ------------ */ configfile_t *dotconf_create(char *, const configoption_t *, context_t *, unsigned long); /* ------ dotconf_cleanup() - tidy up behind dotconf_create and the parser dust ----------------- */ void dotconf_cleanup(configfile_t *configfile); /* ------ dotconf_command_loop() - iterate through each line of file and handle the commands ---- */ int dotconf_command_loop(configfile_t *configfile); /* ------ dotconf_command_loop_until_error() - like continue_line but return on the first error - */ const char *dotconf_command_loop_until_error(configfile_t *configfile); /* ------ dotconf_continue_line() - check if line continuation is to be handled ----------------- */ int dotconf_continue_line(char *buffer, size_t length); /* ------ dotconf_get_next_line() - read in the next line of the configfile_t ------------------- */ int dotconf_get_next_line(char *buffer, size_t bufsize, configfile_t *configfile); /* ------ dotconf_get_here_document() - read the here document until delimit is found ----------- */ char *dotconf_get_here_document(configfile_t *configfile, const char *delimit); /* ------ dotconf_invoke_command() - call the callback for command_t ---------------------------- */ const char *dotconf_invoke_command(configfile_t *configfile, command_t *cmd); /* ------ dotconf_find_command() - iterate through all registered options trying to match ------- */ configoption_t *dotconf_find_command(configfile_t *configfile, const char *command); /* ------ dotconf_read_arg() - read one argument from the line handling quoting and escaping ---- */ /* side effects: the char* returned by dotconf_read_arg is malloc() before, hence that pointer will have to be free()ed later. */ char *dotconf_read_arg(configfile_t *configfile, char **line); /* ------ dotconf_handle_command() - parse, substitute, find, invoke the command found in buffer */ const char *dotconf_handle_command(configfile_t *configfile, char *buffer); /* ------ dotconf_register_option() - add a new option table to the list of commands ------------ */ void dotconf_register_options(configfile_t *configfile, const configoption_t *options); /* ------ dotconf_warning() - handle the dispatch of error messages of various levels ----------- */ int dotconf_warning(configfile_t *configfile, int level, unsigned long errnum, const char *, ...); /* ------ dotconf_callback() - register a special callback -------------------------------------- */ void dotconf_callback(configfile_t *configfile, callback_types type, dotconf_callback_t); /* ------ dotconf_substitute_env() - handle the substitution on environment variables ----------- */ char *dotconf_substitute_env(configfile_t *, char *); /* ------ internal utility function that verifies if a character is in the WILDCARDS list -- */ int dotconf_is_wild_card(char value); /* ------ internal utility function that calls the appropriate routine for the wildcard passed in -- */ int dotconf_handle_wild_card(command_t* cmd, char wild_card, char* path, char* pre, char* ext); /* ------ internal utility function that frees allocated memory from dotcont_find_wild_card -- */ void dotconf_wild_card_cleanup(char* path, char* pre); /* ------ internal utility function to check for wild cards in file path -- */ /* ------ path and pre must be freed by the developer ( dotconf_wild_card_cleanup) -- */ int dotconf_find_wild_card(char* filename, char* wildcard, char** path, char** pre, char** ext); /* ------ internal utility function that compares two stings from back to front -- */ int dotconf_strcmp_from_back(const char* s1, const char* s2); /* ------ internal utility function that determins if a string matches the '?' criteria -- */ int dotconf_question_mark_match(char* dir_name, char* pre, char* ext); /* ------ internal utility function that determins if a string matches the '*' criteria -- */ int dotconf_star_match(char* dir_name, char* pre, char* ext); /* ------ internal utility function that determins matches for filenames with -- */ /* ------ a '?' in name and calls the Internal Include function on that filename -- */ int dotconf_handle_question_mark(command_t* cmd, char* path, char* pre, char* ext); /* ------ internal utility function that determins matches for filenames with -- */ /* ------ a '*' in name and calls the Internal Include function on that filename -- */ int dotconf_handle_star(command_t* cmd, char* path, char* pre, char* ext); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* DOTCONF_H */