Index: ossp-pkg/lmtp2nntp/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Makefile.in,v rcsdiff -q -kk '-r1.35' '-r1.36' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Makefile.in,v' 2>/dev/null --- Makefile.in 2002/01/09 13:54:25 1.35 +++ Makefile.in 2002/01/10 10:37:38 1.36 @@ -44,9 +44,9 @@ POD2MAN = pod2man PROG = lmtp2nntp -HDRS = lmtp2nntp_global.h lmtp2nntp_daemon.h lmtp2nntp_lmtp.h lmtp2nntp_nntp.h lmtp2nntp_argz.h lmtp2nntp_shpat.h lmtp2nntp_msg.h lmtp2nntp_popt.h lmtp2nntp_dotconf.h lmtp2nntp_config.h -SRCS = lmtp2nntp_main.c lmtp2nntp_daemon.c lmtp2nntp_lmtp.c lmtp2nntp_nntp.c lmtp2nntp_argz.c lmtp2nntp_shpat.c lmtp2nntp_msg.c lmtp2nntp_popt.c lmtp2nntp_dotconf.c lmtp2nntp_config.c lmtp2nntp_version.c -OBJS = lmtp2nntp_main.o lmtp2nntp_daemon.o lmtp2nntp_lmtp.o lmtp2nntp_nntp.o lmtp2nntp_argz.o lmtp2nntp_shpat.o lmtp2nntp_msg.o lmtp2nntp_popt.o lmtp2nntp_dotconf.o lmtp2nntp_config.o lmtp2nntp_version.o +HDRS = lmtp2nntp_global.h lmtp2nntp_daemon.h lmtp2nntp_lmtp.h lmtp2nntp_nntp.h lmtp2nntp_argz.h lmtp2nntp_shpat.h lmtp2nntp_msg.h lmtp2nntp_popt.h lmtp2nntp_config.h +SRCS = lmtp2nntp_main.c lmtp2nntp_daemon.c lmtp2nntp_lmtp.c lmtp2nntp_nntp.c lmtp2nntp_argz.c lmtp2nntp_shpat.c lmtp2nntp_msg.c lmtp2nntp_popt.c lmtp2nntp_config.c lmtp2nntp_version.c +OBJS = lmtp2nntp_main.o lmtp2nntp_daemon.o lmtp2nntp_lmtp.o lmtp2nntp_nntp.o lmtp2nntp_argz.o lmtp2nntp_shpat.o lmtp2nntp_msg.o lmtp2nntp_popt.o lmtp2nntp_config.o lmtp2nntp_version.o SUBDIRS = @SUBDIR_STR@ @SUBDIR_L2@ @SUBDIR_SA@ @SUBDIR_VAR@ Index: ossp-pkg/lmtp2nntp/example.conf RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/example.conf,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/example.conf,v' 2>/dev/null --- example.conf 2002/01/09 13:54:25 1.2 +++ example.conf 2002/01/10 10:37:38 1.3 @@ -9,13 +9,13 @@ childsmax 10 #see -C aka --childsmax daemonize yes #see -D aka --daemonize # -K aka --kill is not available in the configfile - pidfile "/tmp/pid" #see -P aka --pidfile + pidfile /tmp/pid #see -P aka --pidfile acl 10/8 #see -a aka --acl acl 172.16/12 acl 192.168/16 acl 127.0.0.1/32 bind 127.0.0.1:12345 #see -b aka --bind, use IPv4:port - #bind "/tmp/uds:600" # UNIX domain socket path:permissions + #bind /tmp/uds:600 # UNIX domain socket path:permissions #LMTP @@ -23,8 +23,8 @@ timeoutread 10 timeoutwrite 10 size 555000 #see -s aka --size - mailfrom "any.*@example\.org" #see -m aka --mailfrom - nodename "gateway.example.com" #see -n aka --nodename + mailfrom any.*@example\.org #see -m aka --mailfrom + nodename gateway.example.com #see -n aka --nodename #NNTP, multiple sections allowed @@ -41,15 +41,15 @@ # -l is obsolete since v1.2, see l2spec # -V is obsolete since v1.2; remove the "buffer" channel from l2spec - l2spec prefix(prefix="%%b %%d %%H:%%M:%%S <%%L> lmtp2nntp[%%P]: ",timezone=local) \ + l2spec "prefix(prefix="%%b %%d %%H:%%M:%%S <%%L> lmtp2nntp[%%P]: ",timezone=local) \ -> buffer(size=65536) \ - -> file(path=%s,append=1,perm=%d) \ + -> file(path=%s,append=1,perm=%d)" \ # -l aka --l2spec uid gate #see -u aka --uid # -v aka --version is not available in the configfile - newsgroup "test" - newsgroup "alt.test" #see man page for information about newsgroup + newsgroup test + newsgroup alt.test #see man page for information about newsgroup Index: ossp-pkg/lmtp2nntp/lmtp2nntp_config.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.c,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.c,v' 2>/dev/null --- lmtp2nntp_config.c 2002/01/09 13:54:25 1.1 +++ lmtp2nntp_config.c 2002/01/10 10:37:38 1.2 @@ -26,6 +26,7 @@ #include #include +#include // #include // #include // #include @@ -43,10 +44,9 @@ // #include "lmtp2nntp_shpat.h" // #include "lmtp2nntp_daemon.h" // #include "lmtp2nntp_popt.h" -#include "lmtp2nntp_dotconf.h" /* third party (linked in) */ -// #include "str.h" +#include "str.h" // #include "l2.h" // #include "var.h" @@ -93,52 +93,16 @@ #define NUL '\0' #endif -const char *foo(command_t *, context_t *); -int bar(configfile_t *, int, long, const char *); -const char *quux(command_t *, unsigned long); - -const char *foo(command_t *cmd, context_t *_ctx) -{ - int *foodata = (int *)_ctx; - int i; - printf("DEBUG: callbck %s:%ld: %s:", cmd->configfile->filename, cmd->configfile->line, cmd->name); - for (i = 0; i < cmd->arg_count; i++) - ;//printf("[%d=***%s***] ", i, cmd->data.list[i]); - printf("---%lx---%d---", foodata, (*foodata)++); - printf("\n"); - return NULL; -} - -int bar(configfile_t *configfile, int type, long dc_errno, const char *msg) -{ - printf("DEBUG: handler type=%d, dc_errno=%ld, msg=***%s***\n", type, dc_errno, msg); - return 0; /* 0=continue, 1=abort */ -} - -const char *quux(command_t *cmd, unsigned long mask) +void die(char *); //FIXME +void die(char *msg) { - printf("DEBUG: checker %s:%ld: %s: ", cmd->configfile->filename, cmd->configfile->line, cmd->name); - printf("[mask=%lx]", mask); - printf("\n"); - if ((strcmp(cmd->name, "client") == 0) && (mask = 4)) - return "Nasenbaer!"; - return NULL; + printf("ERROR: %s", msg); + exit(-1); } -enum configcontext -{ - CTX_DAEMON = 1<<0, - CTX_SERVER = 1<<1, - CTX_CLIENT = 1<<2, - CTX_GATEWAY = 1<<3, - CTX_MESSAGE = 1<<4 -}; - - void dotconftest(void) { - configfile_t *configfile; - static int foodata; +#if 0 static const configoption_t options[] = { { "", ARG_NONE, foo, NULL, CTX_ALL }, { "childsmax", ARG_STR, foo, NULL, CTX_DAEMON }, @@ -175,21 +139,94 @@ { "", ARG_NONE, foo, NULL, CTX_MESSAGE }, LAST_OPTION }; +#endif - foodata = 1000; - printf("---%lx---%d---", &foodata, foodata); + const char *filename = "example.conf"; + char *cpBuf; - configfile = dotconf_create("example.conf", options, &foodata, CASE_INSENSITIVE); - if (!configfile) { - fprintf(stderr, "Error opening config file\n"); - return; + { + struct stat sb; + int fd; + + if (stat(filename, &sb) == -1) + die("stat"); + if ((cpBuf = (char *)malloc((size_t)sb.st_size + 1)) == NULL) + die("malloc"); + if ((fd = open(filename, O_RDONLY)) == -1) + die("open"); + if (read(fd, (void *)cpBuf, (size_t)sb.st_size) != (ssize_t)sb.st_size) + die("read"); + cpBuf[(int)sb.st_size] = '\0'; + if (close(fd) == -1) + die("close"); } - configfile->errorhandler = (dotconf_errorhandler_t)bar; - configfile->contextchecker = (dotconf_contextchecker_t)quux; - - if (dotconf_command_loop(configfile) == 0) - fprintf(stderr, "Error reading config file\n"); + //FIXME printf("DEBUG: *** 1 *** file as it was just read in ***\n%s***\n", cpBuf); - dotconf_cleanup(configfile); + { + char *cpI; /* pointer to next character to be read */ + char *cpO; /* pointer to next character to be written when eliminating backslash+newline at a line continuation */ + char *cpL; /* pointer to start of line */ + int pline; /* current physical (disregarding line continuation) line number */ + int lline; /* current logical lines first physical line number */ + int eline; /* flag signaling empty or just whitespace-filled line */ + char c; /* current character */ + char p; /* previous character */ + int eof; /* flag signaling end of file detected */ + + cpI = cpBuf; + cpO = cpBuf; + eof = FALSE; + pline = 1; + p = NUL; /* prefill previous character with fake value to avoid false + line continuation detection when a newline is seen as the first + character in the buffer */ + + cpL = cpO; + lline = pline; + eline = TRUE; + while(!eof) { + c = *cpI++; + *cpO++ = c; + if (c == NUL) + eof = TRUE; + else + if (!isspace(c)) + eline = FALSE; + if (eof || (c == '\n')) { + pline++; + if (!eof && (p == '\\')) { /* line continuation situation */ + cpO-=2; /* need to remove both backslash+newline */ + } + else { + if (!eline) { /* process logical line unless it's empty */ + *(cpO-1) = NUL; + if (lline == (pline-1)) + printf("DEBUG: line[%3d] = ***%s***\n", lline, cpL); + else + printf("DEBUG: [%3d-%3d] = ***%s***\n", lline, pline-1, cpL); + { + char *cp = cpL; + char *token; + char *value; + + if ((token = str_token(&cp, " ", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL) + printf("DEBUG: no token - comment only\n"); + else { + printf("DEBUG: token = ***%s***\n", token); + if ((value = str_token(&cp, "", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL) + printf("DEBUG: no value - section\n"); + else + printf("DEBUG: value = ***%s***\n", value); + } + } + } + cpL = cpO; + lline = pline; + eline = TRUE; + } + } + p = c; + } + } } Index: ossp-pkg/lmtp2nntp/lmtp2nntp_dotconf.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp_dotconf.c,v co -q -kk -p'1.2' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp_dotconf.c,v' | diff -u - /dev/null -L'ossp-pkg/lmtp2nntp/lmtp2nntp_dotconf.c' 2>/dev/null --- ossp-pkg/lmtp2nntp/lmtp2nntp_dotconf.c +++ /dev/null 2024-04-26 12:11:00.000000000 +0200 @@ -1,1311 +0,0 @@ -/* dot.conf - configuration file parser library - * Copyright (C) 1999,2000,2001 Lukas Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -/* -- dotconf.c - this code is responsible for the input, parsing and dispatching of options */ - -#include -#include -#include - -/* Added by Stephen W. Boyer - * for wildcard support in Include file paths - */ -#include -#include -#include -#include - -/* -- AIX 4.3 compile time fix - * by Eduardo Marcel Macan - * - * modified by Stephen W. Boyer - * for Unixware and OpenServer - */ - -#if defined (_AIX43) || defined(UNIXWARE) || defined(OSR5) -#include -#endif - -#include -#include -#include - -#ifndef WIN32 - -#include -#include - -#else /* ndef WIN32 */ - -#include "readdir.h" /* WIN32 fix by Robert J. Buck */ - -#define strncasecmp strnicmp -typedef unsigned long ulong; -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#endif /* !WIN32 */ - -#include -#include "lmtp2nntp_dotconf.h" - -static char name[CFG_MAX_OPTION + 1]; /* option name */ - -/* - * some 'magic' options that are predefined by dot.conf itself for - * advanced functionality - */ -static DOTCONF_CB(dotconf_cb_include); /* internal 'Include' */ -static DOTCONF_CB(dotconf_cb_includepath); /* internal 'IncludePath' */ - -static configoption_t dotconf_options[] = -{ - { "Include", ARG_STR, dotconf_cb_include, NULL, CTX_ALL }, - { "IncludePath", ARG_STR, dotconf_cb_includepath, NULL, CTX_ALL }, - LAST_CONTEXT_OPTION -}; - -char *dotconf_substitute_env(configfile_t *configfile, char *str) -{ - char *cp1, *cp2, *cp3, *eos, *eob; - char *env_value; - char env_name[CFG_MAX_VALUE + 1]; - char env_default[CFG_MAX_VALUE + 1]; - char tmp_value[CFG_MAX_VALUE + 1]; - - memset(env_name, 0, CFG_MAX_VALUE + 1); - memset(env_default, 0, CFG_MAX_VALUE + 1); - memset(tmp_value, 0, CFG_MAX_VALUE + 1); - - cp1 = str; - eob = cp1 + strlen(str) + 1; - cp2 = tmp_value; - eos = cp2 + CFG_MAX_VALUE + 1; - - while ((cp1 < eob) && (cp2 < eos) && (*cp1 != '\0')) - { - /* substitution needed ?? */ - if (*cp1 == '$' && *(cp1 + 1) == '{') - { - cp1 += 2; /* skip ${ */ - cp3 = env_name; - while ((cp1 < eob) && !(*cp1 == '}' || *cp1 == ':')) - *cp3++ = *cp1++; - *cp3 = '\0'; /* terminate */ - - /* default substitution */ - if (*cp1 == ':' && *(cp1 + 1) == '-') - { - cp1 += 2; /* skip :- */ - cp3 = env_default; - while ((cp1 < eob) && (*cp1 != '}')) - *cp3++ = *cp1++; - *cp3 = '\0'; /* terminate */ - } - else - { - while ((cp1 < eob) && (*cp1 != '}')) - cp1++; - } - - if (*cp1 != '}') - { - dotconf_warning(configfile, DCLOG_WARNING, ERR_PARSE_ERROR, - "Unbalanced '{'"); - } - else - { - cp1++; /* skip } */ - if ((env_value = getenv(env_name)) != NULL) - { - strncat(cp2, env_value, eos - cp2); - cp2 += strlen(env_value); - } - else - { - strncat(cp2, env_default, eos - cp2); - cp2 += strlen(env_default); - } - } - - } - - *cp2++ = *cp1++; - } - *cp2 = '\0'; /* terminate buffer */ - - free(str); - return strdup(tmp_value); -} - -int dotconf_warning(configfile_t *configfile, int type, unsigned long errnum, const char *fmt, ...) -{ - va_list args; - int retval = 0; - - va_start(args, fmt); - if (configfile->errorhandler != 0) /* an errorhandler is registered */ - { - char msg[CFG_BUFSIZE]; - vsnprintf(msg, CFG_BUFSIZE, fmt, args); - retval = configfile->errorhandler(configfile, type, errnum, msg); - } - else /* no errorhandler, do-it-yourself */ - { - retval = 0; - fprintf(stderr, "%s:%ld: ", configfile->filename, configfile->line); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - } - va_end(args); - - return retval; -} - -void dotconf_register_options(configfile_t *configfile, const configoption_t * options) -{ - int num = configfile->config_option_count; - -#define GROW_BY 10 - - /* resize memoryblock for options blockwise */ - if (configfile->config_options == NULL) - { - configfile->config_options = malloc(sizeof(void *) * (GROW_BY + 1)); - } - else - { - if ( !(num % GROW_BY) ) - configfile->config_options = realloc(configfile->config_options, - sizeof(void *) * (num + GROW_BY)); - } - -#undef GROW_BY - - /* append new options */ - configfile->config_options[configfile->config_option_count] = options; - configfile->config_options[ ++configfile->config_option_count ] = 0; - -} - -void dotconf_callback(configfile_t *configfile, callback_types type, dotconf_callback_t callback) -{ - switch(type) - { - case ERROR_HANDLER: - configfile->errorhandler = (dotconf_errorhandler_t) callback; - break; - case CONTEXT_CHECKER: - configfile->contextchecker = (dotconf_contextchecker_t) callback; - break; - default: - break; - } -} - -int dotconf_continue_line(char *buffer, size_t length) -{ - /* ------ match [^\\]\\[\r]\n ------------------------------ */ - char *cp1 = buffer + length - 1; - - if (length < 2) - return 0; - - if (*cp1-- != '\n') - return 0; - - if (*cp1 == '\r') - cp1--; - - if (*cp1-- != '\\') - return 0; - - cp1[1] = 0; /* strip escape character and/or newline */ - return (*cp1 != '\\'); -} - -int dotconf_get_next_line(char *buffer, size_t bufsize, configfile_t *configfile) -{ - char *cp1, *cp2; - char buf2[CFG_BUFSIZE]; - int length; - - if (configfile->eof) - return 1; - - cp1 = fgets(buffer, CFG_BUFSIZE, configfile->stream); - - if (!cp1) - { - configfile->eof = 1; - return 1; - } - - configfile->line++; - length = strlen(cp1); - while ( dotconf_continue_line(cp1, length) ) - { - cp2 = fgets(buf2, CFG_BUFSIZE, configfile->stream); - if (!cp2) - { - fprintf(stderr, "[dotconf] Parse error. Unexpected end of file at " - "line %ld in file %s\n", configfile->line, configfile->filename); - configfile->eof = 1; - return 1; - } - configfile->line++; - strcpy(cp1 + length - 2, cp2); - length = strlen(cp1); - } - - return 0; -} - -char *dotconf_get_here_document(configfile_t *configfile, const char *delimit) -{ - /* it's a here-document: yeah, what a cool feature ;) */ - unsigned int limit_len; - char here_string; - char buffer[CFG_BUFSIZE]; - char *here_doc = 0; - char here_limit[9]; /* max length for here-document delimiter: 8 */ - struct stat finfo; - int offset = 0; - - if (configfile->size <= 0) - { - if (stat(configfile->filename, &finfo)) - { - dotconf_warning(configfile, DCLOG_EMERG, ERR_NOACCESS, - "[emerg] could not stat currently read file (%s)\n", - configfile->filename); - return NULL; - } - configfile->size = finfo.st_size; - } - - /* - * allocate a buffer of filesize bytes; should be enough to - * prevent buffer overflows - */ - here_doc = malloc(configfile->size); /* allocate buffer memory */ - memset(here_doc, 0, configfile->size); - - here_string = 1; - limit_len = snprintf(here_limit, 9, "%s", delimit); - while (!dotconf_get_next_line(buffer, CFG_BUFSIZE, configfile)) - { - if (!strncmp(here_limit, buffer, limit_len - 1)) - { - here_string = 0; - break; - } - offset += snprintf( (here_doc + offset), configfile->size - offset - 1, "%s", buffer); - } - if (here_string) - dotconf_warning(configfile, DCLOG_WARNING, ERR_PARSE_ERROR, "Unterminated here-document!"); - - here_doc[offset-1] = '\0'; /* strip newline */ - - return (char *)realloc(here_doc, offset); -} - -const char *dotconf_invoke_command(configfile_t *configfile, command_t *cmd) -{ - const char *error = 0; - - if ( !configfile->contextchecker - || !(error = configfile->contextchecker(cmd, cmd->option->context)) ) - { - if (!error) - error = cmd->option->callback(cmd, configfile->context); - } - - return error; -} - -configoption_t *dotconf_find_command(configfile_t *configfile, const char *command) -{ - configoption_t *option; - int i = 0, mod = 0, done = 0; - - for (option = 0, mod = 0; configfile->config_options[mod] && !done; mod++) - for (i = 0; configfile->config_options[mod][i].name[0]; i++) - { - if (!configfile->cmp_func(name, - configfile->config_options[mod][i].name, CFG_MAX_OPTION)) - { - option = (configoption_t *) &configfile->config_options[mod][i]; - /* TODO: this could be flagged: option overwriting by modules */ - done = 1; - break; /* found it; break out */ - } - } - - /* handle ARG_NAME fallback */ - if ( (option && option->name[0] == 0) - || configfile->config_options[mod - 1][i].type == ARG_NAME) - { - option = (configoption_t *) &configfile->config_options[mod - 1][i]; - } - - return option; -} - -char *dotconf_read_arg(configfile_t *configfile, char **line) -{ - int sq = 0, dq = 0; /* single quote, double quote */ - int done; - char *cp1 = *line; - char *cp2, *eos; - char buf[CFG_MAX_VALUE]; - - memset(buf, 0, CFG_MAX_VALUE); - done = 0; - cp2 = buf; - eos = cp2 + CFG_MAX_VALUE - 1; - - if (*cp1 == '#' || !*cp1) - return NULL; - - /* skip all whitespace between 2 arguments */ - while ( isspace((int)cp1[0]) && (*cp1 != '\0')) - cp1++; - - while ((*cp1 != '\0') && (cp2 != eos) && !done) - { - switch (*cp1) - { - case '\'': /* single quote */ - if (dq) - break; /* already double quoting, break out */ - if (sq) - sq--; /* already single quoting, clear state */ - else if (!sq) - sq++; /* set state for single quoting */ - break; - case '"': /* double quote */ - if (sq) - break; /* already single quoting, break out */ - if (dq) - dq--; /* already double quoting, clear state */ - else if (!dq) - dq++; /* set state for double quoting */ - break; - case '\\': /* protected chars */ - if (!cp1[1]) /* dont protect NUL */ - break; - *cp2++ = *(++cp1); - cp1++; /* skip the protected one */ - continue; - break; - default: - break; - } - - /* unquoted space: start a new option argument */ - if (isspace((int)*cp1) && !dq && !sq) - { - *cp2 = '\0'; /* terminate current argument */ - break; - } - /* unquoted, unescaped comment-hash ; break out */ - else if (*cp1 == '#' && !dq && !sq) - { - *cp2 = '\0'; - break; - } - /* not space or quoted:eat it; dont take quote if quoting */ - else if ( (!isspace((int)*cp1) && !dq && !sq && *cp1 != '"' && *cp1 != '\'') - || (dq && (*cp1 != '"')) || (sq && *cp1 != '\'') ) - { - *cp2++ = *cp1; - } - cp1++; - } - - *line = cp1; - - /* FIXME: escaping substitutes does not work - Subst ${HOME} \$\{HOME\} - BOTH! will be substituted, which is somewhat wrong, ain't it ?? :-( - */ - if ( (configfile->flags & DONT_SUBSTITUTE) == DONT_SUBSTITUTE ) - return buf[0] ? strdup(buf) : NULL; - return buf[0] ? dotconf_substitute_env(configfile, strdup(buf)) : NULL; -} - -const char *dotconf_handle_command(configfile_t *configfile, char *buffer) -{ - char *cp1, *cp2; /* generic char pointer */ - char *eob; /* end of buffer; end of string */ - int i; /* generic counter, mod holds the module index */ - int memory_cleanup; - const char *error; /* error message as return by callback */ - command_t command; /* command structure */ - configoption_t *option; /* matched option from config_options */ - - i = memory_cleanup = 0; - error = 0; - - /* TODO????: insert 'skipped_line' callback code */ - - /* clear fields */ - memset(&command, 0, sizeof(command_t)); - name[0] = 0; - - /* initialize char pointer */ - cp1 = buffer; - eob = cp1 + strlen(cp1); /* calculate end of buffer */ - - /* skip any whitspace of indented lines */ - while ((cp1 < eob) && (isspace((int)*cp1))) - cp1++; - - /* ignore comments and empty lines */ - if (!cp1 || !*cp1 || *cp1 == '#' || *cp1 == '\n' || *cp1 == EOF) - return NULL; - - /* skip line if it only contains whitespace */ - if (cp1 == eob) - return NULL; - - /* get first token: read the name of a possible option */ - cp2 = name; - while ((*cp1 != '\0') && (!isspace((int)*cp1))) - *cp2++ = *cp1++; - *cp2 = '\0'; - - option = dotconf_find_command(configfile, name); - - if (!option || option->callback == 0) - { - dotconf_warning(configfile, DCLOG_INFO, ERR_UNKNOWN_OPTION, - "Unknown Config-Option: '%s'", name); - return NULL; - } - - /* fill in the command_t structure with values we already know */ - command.name = option->type == ARG_NAME ? name : option->name; - command.option = option; - command.context = configfile->context; - command.configfile = configfile; - command.data.list = (char **)calloc(CFG_VALUES, sizeof(char *)); - - if (option->type == ARG_RAW) - { - /* if it is an ARG_RAW type, save some time and call the - callback now */ - command.data.str = cp1; - } - else if (option->type == ARG_STR) - { - /* check if it's a here-document and act accordingly */ - char *cp3 = cp1; - - /* skip whitespace */ - while ((cp3 < eob) && (*cp3 != '\0') && (isspace((int)*cp3))) - cp3++; - - if (!strncmp("<<", cp3, 2)) /* here document magic bytes :) */ - { - command.data.str = dotconf_get_here_document(configfile, cp3 + 2); - command.arg_count = 1; - memory_cleanup = !!command.data.str; - } - } - - if ( !(option->type == ARG_STR && command.data.str != 0) ) - { - - /* skip whitespace */ - while ((cp1 < eob) && (*cp1 != '\0') && (isspace((int)*cp1))) - cp1++; - - command.arg_count = 0; - while ( command.arg_count < (CFG_VALUES - 1) - && (command.data.list[command.arg_count] = dotconf_read_arg(configfile, &cp1)) ) - { - command.arg_count++; - } - - /* skip whitespace again */ - while ((cp1 < eob) && (*cp1 != '\0') && (isspace((int)*cp1))) - cp1++; - - if (command.arg_count && command.data.list[command.arg_count-1] && *cp1) - command.data.list[command.arg_count++] = strdup(cp1); - - /* has an option entry been found before or do we have to use a fallback? */ - if ((option->name && option->name[0] > 32) || option->type == ARG_NAME) - { - /* found it, now check the type of args it wants */ - switch (option->type) - { - case ARG_TOGGLE: - { - /* the value is true if the argument is Yes, On or 1 */ - if (command.arg_count < 1) - { - dotconf_warning(configfile, DCLOG_WARNING, ERR_WRONG_ARG_COUNT, - "Missing argument to option '%s'", name); - goto out; - } - - command.data.value = CFG_TOGGLED(command.data.list[0]); - break; - } - case ARG_INT: - { - if (command.arg_count < 1) - { - dotconf_warning(configfile, DCLOG_WARNING, ERR_WRONG_ARG_COUNT, - "Missing argument to option '%s'", name); - goto out; - } - - sscanf(command.data.list[0], "%li", &command.data.value); - break; - } - case ARG_STR: - { - if (command.arg_count < 1) - { - dotconf_warning(configfile, DCLOG_WARNING, ERR_WRONG_ARG_COUNT, - "Missing argument to option '%s'", name); - goto out; - } - - command.data.str = command.data.list[0]; - break; - } - case ARG_NAME: /* fall through */ - case ARG_LIST: - case ARG_NONE: - case ARG_RAW: /* this has been handled before */ - default: - break; //win32 edit - } - } - } - - error = dotconf_invoke_command(configfile, &command); - -out: - if (command.option->type == ARG_STR && memory_cleanup) - free(command.data.str); - else - { - for (i = 0; i < command.arg_count; i++) - free(command.data.list[i]); - } - - free(command.data.list); - return error; -} - -const char *dotconf_command_loop_until_error(configfile_t *configfile) -{ - char buffer[CFG_BUFSIZE]; - - while ( !(dotconf_get_next_line(buffer, CFG_BUFSIZE, configfile)) ) - { - const char *error = dotconf_handle_command(configfile, buffer); - if ( error ) - return error; - } - return NULL; -} - -int dotconf_command_loop(configfile_t *configfile) -{ - /* ------ returns: 0 for failure -- !0 for success ------------------------------------------ */ - char buffer[CFG_BUFSIZE]; - - while ( !(dotconf_get_next_line(buffer, CFG_BUFSIZE, configfile)) ) - { - const char *error = dotconf_handle_command(configfile, buffer); - if ( error != NULL ) - { - if ( dotconf_warning(configfile, DCLOG_ERR, 0, error) ) - return 0; - } - } - return 1; -} - -configfile_t *dotconf_create(char *fname, const configoption_t * options, - context_t *context, unsigned long flags) -{ - configfile_t *new = 0; - char *dc_env; - - if (access(fname, R_OK)) - { - fprintf(stderr, "Error opening configuration file '%s'\n", fname); - return NULL; - } - - new = calloc(1, sizeof(configfile_t)); - if (!(new->stream = fopen(fname, "r"))) - { - fprintf(stderr, "Error opening configuration file '%s'\n", fname); - free(new); - return NULL; - } - - new->flags = flags; - new->filename = strdup(fname); - - new->includepath = malloc(CFG_MAX_FILENAME); - new->includepath[0] = 0x00; - - /* take includepath from environment if present */ - if ((dc_env = getenv(CFG_INCLUDEPATH_ENV)) != NULL) - { - snprintf(new->includepath, CFG_MAX_FILENAME, "%s", dc_env); - } - - new->context = context; - - dotconf_register_options(new, dotconf_options); - dotconf_register_options(new, options); - - if ( new->flags & CASE_INSENSITIVE ) - new->cmp_func = strncasecmp; - else - new->cmp_func = strncmp; - - return new; -} - -void dotconf_cleanup(configfile_t *configfile) -{ - if (configfile->stream) - fclose(configfile->stream); - - if (configfile->filename) - free(configfile->filename); - - if (configfile->config_options) - free(configfile->config_options); - - if (configfile->includepath) - free(configfile->includepath); - - free(configfile); -} - -/* ------ internal utility function that verifies if a character is in the WILDCARDS list -- */ -int dotconf_is_wild_card(char value) -{ - int retval = 0; - int i; - int wildcards_len = strlen(WILDCARDS); - - for (i=0;i 0 && path != NULL && pre != NULL && ext != NULL ) - { - prefix_len = strcspn(filename,WILDCARDS); /* find any wildcard in WILDCARDS */ - - if ( prefix_len < len ) /* Wild card found */ - { - tmp = filename + prefix_len; - tmp_count = prefix_len + 1; - - while ( tmp != filename && *(tmp) != '/' ) - { - tmp--; - tmp_count--; - } - - if ( *(tmp) == '/' ) - { - *path = (char*)malloc(tmp_count+1); - found_path = 1; - - } else - - *path = (char*)malloc(1); - - *pre = (char*)malloc((prefix_len-(tmp_count-(found_path?0:1)))+1); - - if ( *path && *pre ) - { - if (found_path) - strncpy(*path,filename,tmp_count); - (*path)[tmp_count] = '\0'; - - strncpy(*pre,(tmp+(found_path?1:0)), - (prefix_len-(tmp_count-(found_path?0:1)))); - (*pre)[(prefix_len-(tmp_count-(found_path?0:1)))] = '\0'; - - *ext = filename + prefix_len; - *wildcard = (**ext); - (*ext)++; - - retval = prefix_len; - - } - - } - - } - - return retval; -} - -/* ------ internal utility function that compares two stings from back to front -- */ -int dotconf_strcmp_from_back(const char* s1, const char* s2) -{ - int retval = 0; - int i,j; - int len_1 = strlen(s1); - int len_2 = strlen(s2); - - for (i=len_1,j=len_2;(i>=0 && j>=0);i--,j--) - { - if (s1[i] != s2[j]) - { - retval = -1; - break; - } - } - - return retval; -} - -/* ------ internal utility function that determins if a string matches the '?' criteria -- */ -int dotconf_question_mark_match(char* dir_name, char* pre, char* ext) -{ - int retval = -1; - int dir_name_len = strlen(dir_name); - int pre_len = strlen(pre); - int ext_len = strlen(ext); - int w_card_check = strcspn(ext,WILDCARDS); - - if ( (w_card_check < ext_len) && (strncmp(dir_name,pre,pre_len) == 0) - && (strcmp(dir_name,".") != 0 ) && (strcmp(dir_name,"..") != 0) ) - { - retval = 1; /* Another wildcard found */ - - } else { - - if ((dir_name_len >= pre_len) && - (strncmp(dir_name,pre,pre_len) == 0) && - (strcmp(dir_name,".") != 0 ) && - (strcmp(dir_name,"..") != 0)) - { - retval = 0; /* Matches no other wildcards */ - } - - } - - return retval; -} - -/* ------ internal utility function that determins if a string matches the '*' criteria -- */ -int dotconf_star_match(char* dir_name, char* pre, char* ext) -{ - int retval = -1; - int dir_name_len = strlen(dir_name); - int pre_len = strlen(pre); - int ext_len = strlen(ext); - int w_card_check = strcspn(ext,WILDCARDS); - - if ( (w_card_check < ext_len) && (strncmp(dir_name,pre,pre_len) == 0) - && (strcmp(dir_name,".") != 0 ) && (strcmp(dir_name,"..") != 0) ) - { - retval = 1; /* Another wildcard found */ - - } else { - - if ((dir_name_len >= (ext_len + pre_len)) && - (dotconf_strcmp_from_back(dir_name,ext) == 0) && - (strncmp(dir_name,pre,pre_len) == 0) && - (strcmp(dir_name,".") != 0 ) && - (strcmp(dir_name,"..") != 0)) - { - retval = 0; /* Matches no other wildcards */ - } - - } - - return retval; -} - -/* ------ 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) -{ - configfile_t *included; - DIR* dh = 0; - struct dirent* dirptr = 0; - - char new_pre[CFG_MAX_FILENAME]; - char already_matched[CFG_MAX_FILENAME]; - - char wc = '\0'; - - char* new_path = 0; - char* wc_path = 0; - char* wc_pre = 0; - char* wc_ext = 0; - - int pre_len; - int new_path_len; - int name_len = 0; - int alloced = 0; - int match_state = 0; - - pre_len = strlen(pre); - - if ((dh = opendir(path)) != NULL) - { - while ( (dirptr = readdir(dh)) != NULL ) - { - match_state = dotconf_question_mark_match(dirptr->d_name,pre,ext); - - if (match_state >= 0) - { - name_len = strlen(dirptr->d_name); - new_path_len = strlen(path) + name_len + strlen(ext) + 1; - - if ( !alloced ) - { - if ((new_path = (char*)malloc(new_path_len)) == NULL ) - { - return -1; - } - - alloced = new_path_len; - - } else { - - if ( new_path_len > alloced ) - { - if ( realloc(new_path,new_path_len) == NULL ) - { - free(new_path); - return -1; - } - - } - - } - - if (match_state == 1) - { - - strncpy(new_pre,dirptr->d_name,(name_len > pre_len)?(pre_len+1):pre_len); - new_pre[(name_len > pre_len)?(pre_len+1):pre_len] = '\0'; - - sprintf(new_path,"%s%s%s",path,new_pre,ext); - - if (strcmp(new_path,already_matched) == 0) - { - continue; /* Already searched this expression */ - - } else { - - strcpy(already_matched,new_path); - - } - - if (dotconf_find_wild_card(new_path,&wc,&wc_path,&wc_pre,&wc_ext) >= 0) - { - if ( dotconf_handle_wild_card(cmd,wc,wc_path,wc_pre,wc_ext) < 0) - { - dotconf_warning(cmd->configfile, DCLOG_WARNING, ERR_INCLUDE_ERROR, - "Error occured while processing wildcard %c\n" - "Filename is '%s'\n", wc, new_path); - - free(new_path); - dotconf_wild_card_cleanup(wc_path,wc_pre); - return -1; - } - - dotconf_wild_card_cleanup(wc_path,wc_pre); - continue; - } - - } - - sprintf(new_path,"%s%s",path,dirptr->d_name); - - if (access(new_path, R_OK)) - { - dotconf_warning(cmd->configfile, DCLOG_WARNING, ERR_INCLUDE_ERROR, - "Cannot open %s for inclusion.\n" - "IncludePath is '%s'\n", new_path, cmd->configfile->includepath); - return -1; - } - - included = dotconf_create(new_path, cmd->configfile->config_options[1], - cmd->configfile->context, cmd->configfile->flags); - if (included) - { - included->errorhandler = cmd->configfile->errorhandler; - included->contextchecker = cmd->configfile->contextchecker; - dotconf_command_loop(included); - dotconf_cleanup(included); - } - - } - - } - - closedir(dh); - free(new_path); - - } - - return 0; -} - -/* ------ 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) -{ - configfile_t *included; - DIR* dh = 0; - struct dirent* dirptr = 0; - - char new_pre[CFG_MAX_FILENAME]; - char new_ext[CFG_MAX_FILENAME]; - char already_matched[CFG_MAX_FILENAME]; - - char wc = '\0'; - - char* new_path = 0; - char* s_ext = 0; - char* t_ext = 0; - char* sub = 0; - char* wc_path = 0; - char* wc_pre = 0; - char* wc_ext = 0; - - int pre_len; - int new_path_len; - int name_len = 0; - int alloced = 0; - int match_state = 0; - int t_ext_count = 0; - int sub_count = 0; - - pre_len = strlen(pre); - memset(already_matched,0,CFG_MAX_FILENAME); - s_ext = ext; - - while (dotconf_is_wild_card(*s_ext)) /* remove trailing wild-cards proceeded by * */ - { - s_ext++; - } - - t_ext = s_ext; - - while(t_ext != NULL && !(dotconf_is_wild_card(*t_ext)) && *t_ext != '\0') - { - t_ext++; /* find non-wild-card string */ - t_ext_count++; - } - - strncpy(new_ext,s_ext,t_ext_count); - new_ext[t_ext_count] = '\0'; - - if ((dh = opendir(path)) != NULL) - { - while ( (dirptr = readdir(dh)) != NULL ) - { - sub_count = 0; - t_ext_count = 0; - - match_state = dotconf_star_match(dirptr->d_name,pre,s_ext); - - if (match_state >= 0) - { - name_len = strlen(dirptr->d_name); - new_path_len = strlen(path) + name_len + strlen(s_ext) + 1; - - if ( !alloced ) - { - if ((new_path = (char*)malloc(new_path_len)) == NULL ) - { - return -1; - } - - alloced = new_path_len; - - } else { - - if ( new_path_len > alloced ) - { - if ( realloc(new_path,new_path_len) == NULL ) - { - free(new_path); - return -1; - } - - } - - } - - if (match_state == 1) - { - - if ((sub = strstr((dirptr->d_name+pre_len),new_ext)) == NULL) - { - continue; - } - - while (sub != dirptr->d_name) - { - sub--; - sub_count++; - } - - if (sub_count + t_ext_count > name_len) - { - continue; - } - - strncpy(new_pre,dirptr->d_name,(sub_count+t_ext_count)); - new_pre[sub_count+t_ext_count] = '\0'; - strcat(new_pre,new_ext); - - sprintf(new_path,"%s%s%s",path,new_pre,t_ext); - - if (strcmp(new_path,already_matched) == 0) - { - continue; /* Already searched this expression */ - - } else { - - strcpy(already_matched,new_path); - - } - - if (dotconf_find_wild_card(new_path,&wc,&wc_path,&wc_pre,&wc_ext) >= 0) - { - if ( dotconf_handle_wild_card(cmd,wc,wc_path,wc_pre,wc_ext) < 0) - { - dotconf_warning(cmd->configfile, DCLOG_WARNING, ERR_INCLUDE_ERROR, - "Error occured while processing wildcard %c\n" - "Filename is '%s'\n", wc, new_path); - - free(new_path); - dotconf_wild_card_cleanup(wc_path,wc_pre); - return -1; - } - - dotconf_wild_card_cleanup(wc_path,wc_pre); - continue; - } - - } - - sprintf(new_path,"%s%s",path,dirptr->d_name); - - if (access(new_path, R_OK)) - { - dotconf_warning(cmd->configfile, DCLOG_WARNING, ERR_INCLUDE_ERROR, - "Cannot open %s for inclusion.\n" - "IncludePath is '%s'\n", new_path, cmd->configfile->includepath); - return -1; - } - - included = dotconf_create(new_path, cmd->configfile->config_options[1], - cmd->configfile->context, cmd->configfile->flags); - if (included) - { - included->errorhandler = cmd->configfile->errorhandler; - included->contextchecker = cmd->configfile->contextchecker; - dotconf_command_loop(included); - dotconf_cleanup(included); - } - - } - - } - - closedir(dh); - free(new_path); - - } - - return 0; -} - -/* ------ callbacks of the internal option (Include, IncludePath) ------------------------------- */ -DOTCONF_CB(dotconf_cb_include) -{ - char *filename = 0; - configfile_t *included; - - char wild_card; - char* path = 0; - char* pre = 0; - char* ext = 0; - - - if (cmd->configfile->includepath - && cmd->data.str[0] != '/' && cmd->configfile->includepath[0] != '\0') - { - /* relative file AND include path is used */ - int len, inclen; - char *sl; - - inclen = strlen(cmd->configfile->includepath); - if (( len = (strlen(cmd->data.str) + inclen + 1)) == CFG_MAX_FILENAME) - { - dotconf_warning(cmd->configfile, DCLOG_WARNING, ERR_INCLUDE_ERROR, - "Absolute filename too long (>%d)", CFG_MAX_FILENAME); - return NULL; - } - - if (cmd->configfile->includepath[inclen - 1] == '/') - sl = ""; - else - { - sl = "/"; - len++; - } - - filename = malloc(len); - snprintf(filename, len, "%s%s%s", - cmd->configfile->includepath, sl, cmd->data.str); - } - else /* fully qualified, or no includepath */ - filename = strdup(cmd->data.str); - - /* Added wild card support here */ - if (dotconf_find_wild_card(filename,&wild_card,&path,&pre,&ext) >= 0) - { - if ( dotconf_handle_wild_card(cmd,wild_card,path,pre,ext) < 0) - { - dotconf_warning(cmd->configfile, DCLOG_WARNING, ERR_INCLUDE_ERROR, - "Error occured while attempting to process %s for inclusion.\n" - "IncludePath is '%s'\n", filename, cmd->configfile->includepath); - } - - dotconf_wild_card_cleanup(path,pre); - free(filename); - return NULL; - } - - if (access(filename, R_OK)) - { - dotconf_warning(cmd->configfile, DCLOG_WARNING, ERR_INCLUDE_ERROR, - "Cannot open %s for inclusion.\n" - "IncludePath is '%s'\n", filename, cmd->configfile->includepath); - free(filename); - return NULL; - } - - included = dotconf_create(filename, cmd->configfile->config_options[1], - cmd->configfile->context, cmd->configfile->flags); - if (included) - { - included->contextchecker = (dotconf_contextchecker_t) cmd->configfile->contextchecker; - included->errorhandler = (dotconf_errorhandler_t) cmd->configfile->errorhandler; - - dotconf_command_loop(included); - dotconf_cleanup(included); - } - - free(filename); - return NULL; -} - -DOTCONF_CB(dotconf_cb_includepath) -{ - char *env = getenv(CFG_INCLUDEPATH_ENV); - /* environment overrides configuration file setting */ - if (!env) - snprintf(cmd->configfile->includepath, CFG_MAX_FILENAME, "%s", cmd->data.str); - return NULL; -} - -/* vim:set ts=4: */ Index: ossp-pkg/lmtp2nntp/lmtp2nntp_dotconf.h RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp_dotconf.h,v co -q -kk -p'1.2' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp_dotconf.h,v' | diff -u - /dev/null -L'ossp-pkg/lmtp2nntp/lmtp2nntp_dotconf.h' 2>/dev/null --- ossp-pkg/lmtp2nntp/lmtp2nntp_dotconf.h +++ /dev/null 2024-04-26 12:11:00.000000000 +0200 @@ -1,262 +0,0 @@ -#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 */