more/better error checks, harmonized coding style

This commit is contained in:
marschap
2006-04-26 18:02:25 +00:00
parent 31b9ed6ef1
commit 1aff9c4226
+270 -271
View File
@@ -5,12 +5,12 @@
* This file is released under the GNU General Public License. Refer to the * This file is released under the GNU General Public License. Refer to the
* COPYING file distributed with this package. * COPYING file distributed with this package.
* *
* Copyright (c) 2001, Joris Robijn * Copyright(c) 2001, Joris Robijn
* (c) 2003, Rene Wagner * (c) 2003, Rene Wagner
* *
* *
* Defines routines to read ini-file-like files. * Defines routines to read ini-file-like files.
* Optionally retrieves settings from an LDAP directory (OpenLDAP 2.1.x) * Optionally retrieves settings from an LDAP directory(OpenLDAP 2.1.x)
*/ */
#include "config.h" #include "config.h"
@@ -29,15 +29,15 @@
typedef struct key { typedef struct key {
char * name; char *name;
char * value; char *value;
struct key * next_key; struct key *next_key;
} key; } key;
typedef struct section { typedef struct section {
char * name; char *name;
key * first_key; key *first_key;
struct section * next_section; struct section *next_section;
} section; } section;
@@ -45,20 +45,21 @@ static section * first_section = NULL;
/* Yes there is a static. It's C after all :)*/ /* Yes there is a static. It's C after all :)*/
section * find_section( char * sectionname ); section * find_section(char * sectionname);
section * add_section( char * sectionname ); section * add_section(char * sectionname);
key * find_key( section * s, char * keyname, int skip ); key * find_key(section * s, char * keyname, int skip);
key * add_key( section * s, char * keyname, char * value ); key * add_key(section * s, char * keyname, char * value);
char get_next_char_f(buffile * f); char get_next_char_f(buffile * f);
int process_config( section ** current_section, char (*get_next_char)(), char modify_section_allowed, char * source_descr, buffile * f ); int process_config(section ** current_section, char(*get_next_char)(), char modify_section_allowed, char * source_descr, buffile * f);
#ifdef WITH_LDAP_SUPPORT #ifdef WITH_LDAP_SUPPORT
int connect_to_ldap(void); int connect_to_ldap(void);
static LDAP * ld = NULL; static LDAP * ld = NULL;
int use_ldap=0; int use_ldap = 0;
static char * ldap_host=NULL, * ldap_base_dn=NULL; static char * ldap_host = NULL, * ldap_base_dn = NULL;
int ldap_port; int ldap_port;
/* not supported for now /* not supported for now
@@ -67,92 +68,89 @@ int ldap_port;
*/ */
#endif /* WITH_LDAP_SUPPORT */ #endif /* WITH_LDAP_SUPPORT */
/**** EXTERNAL FUNCTIONS ****/ /**** EXTERNAL FUNCTIONS ****/
int config_read_file( char *filename ) int config_read_file(char *filename)
{ {
buffile * f; buffile *f;
section * curr_section = NULL; section *curr_section = NULL;
#ifdef WITH_LDAP_SUPPORT #ifdef WITH_LDAP_SUPPORT
LDAPURLDesc * url = NULL; LDAPURLDesc *url = NULL;
int retval; int retval;
#endif /* WITH_LDAP_SUPPORT */ #endif /* WITH_LDAP_SUPPORT */
report( RPT_NOTICE, "Using Configuration File: %s", filename); report(RPT_NOTICE, "Using Configuration File: %s", filename);
#ifdef WITH_LDAP_SUPPORT #ifdef WITH_LDAP_SUPPORT
if (ldap_is_ldap_url( filename )) { if (ldap_is_ldap_url(filename)) {
use_ldap=1; use_ldap = 1;
if (0 != (retval = ldap_url_parse( filename, &url))) { if (0 != (retval = ldap_url_parse(filename, &url))) {
report( RPT_ERR, "Errors parsing LDAP URL %s: %s", filename, ldap_err2string(retval)); report(RPT_ERR, "Errors parsing LDAP URL %s: %s", filename, ldap_err2string(retval));
ldap_free_urldesc(url); ldap_free_urldesc(url);
return (-1); return(-1);
} }
ldap_host=strdup(url->lud_host); ldap_host = strdup(url->lud_host);
ldap_port=url->lud_port; ldap_port = url->lud_port;
report( RPT_INFO, "Using LDAP server: %s:%d", ldap_host, ldap_port); report(RPT_INFO, "Using LDAP server: %s:%d", ldap_host, ldap_port);
ldap_base_dn=strdup(url->lud_dn); ldap_base_dn = strdup(url->lud_dn);
report( RPT_INFO, "Using LDAP base DN: %s", ldap_base_dn); report(RPT_INFO, "Using LDAP base DN: %s", ldap_base_dn);
ldap_free_urldesc(url); ldap_free_urldesc(url);
if (connect_to_ldap() < 0 ) { if (connect_to_ldap() < 0) {
debug( RPT_DEBUG, "connect_to_ldap returned errors."); debug(RPT_DEBUG, "connect_to_ldap returned errors.");
return (-1); return(-1);
} }
return 0; return 0;
} }
#endif /* WITH_LDAP_SUPPORT */ #endif /* WITH_LDAP_SUPPORT */
f = buffile_open( filename, "r" ); f = buffile_open(filename, "r");
if( f==NULL ) { if (f == NULL) {
return -1; return -1;
} }
process_config( &curr_section, get_next_char_f, 1, filename, f ); process_config(&curr_section, get_next_char_f, 1, filename, f);
buffile_close( f ); buffile_close(f);
return 0; return 0;
} }
int config_read_string( char *sectionname, char *str ) int config_read_string(char *sectionname, char *str)
/* All the config parameters are placed in the given section in memory.*/ /* All the config parameters are placed in the given section in memory.*/
{ {
int pos=0; int pos = 0;
section * s; section *s;
/* We use a nested fuction to transfer the characters from buffer to parser*/ /* We use a nested fuction to transfer the characters from buffer to parser*/
char get_next_char() { char get_next_char() {
return str[pos++]; return str[pos++];
} }
if( !( s=find_section( sectionname ))) { if ((s = find_section(sectionname)) == NULL)
s=add_section( sectionname ); s = add_section(sectionname);
}
process_config( &s, get_next_char, 0, "command line", NULL ); process_config(&s, get_next_char, 0, "command line", NULL);
return 0; return 0;
} }
char *config_get_string( char * sectionname, char * keyname, char *config_get_string(char * sectionname, char * keyname,
int skip, char * default_value ) int skip, char * default_value)
{ {
section * s; key *k = find_key(find_section(sectionname), keyname, skip);
key * k;
s = find_section( sectionname ); if (k == NULL)
if( !s ) return default_value; return default_value;
k = find_key( s, keyname, skip );
if( !k ) return default_value;
return k->value; return k->value;
@@ -160,106 +158,87 @@ char *config_get_string( char * sectionname, char * keyname,
/* Reallocate memory space for the return value*/ /* Reallocate memory space for the return value*/
/* /*
string_storage = realloc( string_storage, ( strlen( k->value ) / 256 + 1) * 256 ); string_storage = realloc(string_storage,(strlen(k->value) / 256 + 1) * 256);
strcpy( string_storage, k->value ); strcpy(string_storage, k->value);
But then you also need a global static string_storage = NULL; But then you also need a global static string_storage = NULL;
*/ */
} }
short config_get_bool( char *sectionname, char *keyname, short config_get_bool(char *sectionname, char *keyname,
int skip, short default_value ) int skip, short default_value)
{ {
section * s; key *k = find_key(find_section(sectionname), keyname, skip);
key * k;
s = find_section( sectionname ); if (k == NULL)
if( !s ) return default_value; return default_value;
k = find_key( s, keyname, skip );
if( !k ) return default_value;
if( strcasecmp( k->value, "0" )==0 || strcasecmp( k->value, "false" )==0 if (strcasecmp(k->value, "0") == 0 || strcasecmp(k->value, "false") == 0
|| strcasecmp( k->value, "n" )==0 || strcasecmp( k->value, "no" )==0 ) { || strcasecmp(k->value, "n") == 0 || strcasecmp(k->value, "no") == 0) {
return 0; return 0;
} }
if( strcasecmp( k->value, "1" )==0 || strcasecmp( k->value, "true" )==0 if (strcasecmp(k->value, "1") == 0 || strcasecmp(k->value, "true") == 0
|| strcasecmp( k->value, "y" )==0 || strcasecmp( k->value, "yes" )==0 ) { || strcasecmp(k->value, "y") == 0 || strcasecmp(k->value, "yes") == 0) {
return 1; return 1;
} }
return default_value; return default_value;
} }
long int config_get_int( char *sectionname, char *keyname, long int config_get_int(char *sectionname, char *keyname,
int skip, long int default_value ) int skip, long int default_value)
{ {
section * s; key *k = find_key(find_section(sectionname), keyname, skip);
key * k;
long int v;
char * v_end;
s = find_section( sectionname ); if (k != NULL) {
if( !s ) return default_value; char *end;
k = find_key( s, keyname, skip ); long int v = strtol(k->value, &end, 0);
if( !k ) return default_value;
v = strtol( k->value, &v_end, 0 ); if ((end != NULL) && (end != k->value) && (*end == '\0'))
if( v_end-(k->value) != strlen(k->value) ) { /* Conversion succesful*/
/* Conversion not succesful*/ return v;
return default_value;
} }
return v; return default_value;
} }
double config_get_float( char *sectionname, char *keyname, double config_get_float(char *sectionname, char *keyname,
int skip, double default_value ) int skip, double default_value)
{ {
section * s; key *k = find_key(find_section(sectionname), keyname, skip);
key * k;
double v;
char * v_end;
s = find_section( sectionname ); if (k != NULL) {
if( !s ) return default_value; char *end;
k = find_key( s, keyname, skip ); double v = strtod(k->value, &end);
if( !k ) return default_value;
v = strtod( k->value, &v_end ); if ((end != NULL) && (end != k->value) && (*end == '\0'))
if( v_end-(k->value) != strlen(k->value) ) { /* Conversion succesful*/
/* Conversion not succesful*/ return v;
return default_value;
} }
return v; return default_value;
} }
int config_has_section( char *sectionname ) int config_has_section(char *sectionname)
{ {
section * s; return (find_section(sectionname) != NULL) ? 1 : 0;
s = find_section( sectionname );
if( s ) return 1; else return 0;
} }
int config_has_key( char *sectionname, char *keyname ) int config_has_key(char *sectionname, char *keyname)
{ {
section * s; section *s = find_section(sectionname);
key * k;
int count = 0; int count = 0;
s = find_section( sectionname ); if (s != NULL) {
if( !s ) return 0; key *k;
for( k=s->first_key; k; k=k->next_key ) { for (k = s->first_key; k != NULL; k = k->next_key) {
/* Did we find the right key ?*/
/* Did we find the right key ?*/ if (strcasecmp(k->name, keyname) == 0)
if( strcasecmp( k->name, keyname ) == 0 ) { count++;
count ++; }
}
} }
return count; return count;
} }
@@ -267,32 +246,29 @@ int config_has_key( char *sectionname, char *keyname )
void config_clear() void config_clear()
{ {
section * s; section *s;
section * next_s; section *next_s;
key * k;
key * next_k;
for( s = first_section; s; ) { for (s = first_section; s != NULL; s = next_s) {
for( k=s->first_key; k; ) { key *k;
key *next_k;
for (k = s->first_key; k != NULL; k = next_k) {
/* Advance before we destroy the current key */ /* Advance before we destroy the current key */
next_k = k->next_key; next_k = k->next_key;
free( k->name ); free(k->name);
free( k->value ); free(k->value);
free( k ); free(k);
k = next_k;
} }
/* Advance before we destroy the current section */ /* Advance before we destroy the current section */
next_s = s->next_section; next_s = s->next_section;
/* And destroy it */ /* And destroy it */
free( s->name ); free(s->name);
free( s ); free(s);
s = next_s;
} }
/* And make everything inaccessable */ /* Finally make everything inaccessable */
first_section = NULL; first_section = NULL;
} }
@@ -301,156 +277,161 @@ void config_clear()
#ifdef WITH_LDAP_SUPPORT #ifdef WITH_LDAP_SUPPORT
int int
connect_to_ldap (void) connect_to_ldap(void)
{ {
int retval; int retval;
LDAPMessage * res; LDAPMessage *res;
debug( RPT_INFO, "Connecting to LDAP server: %s:%d", ldap_host, ldap_port); debug(RPT_INFO, "Connecting to LDAP server: %s:%d", ldap_host, ldap_port);
if (!(ld = ldap_init(ldap_host, ldap_port))) { if (!(ld = ldap_init(ldap_host, ldap_port))) {
report(RPT_ERR, "LDAP session could not be initialized."); report(RPT_ERR, "LDAP session could not be initialized.");
return (-1); return(-1);
} }
/***************************************************** /*****************************************************
* disabled unless you really have a DN/pwd to bind to * disabled unless you really have a DN/pwd to bind to
* WARNING: LCDd should not have LDAP write access!! * WARNING: LCDd should not have LDAP write access!!
* *
* if (LDAP_SUCCESS != (retval = ldap_simple_bind_s (ld, ldap_user, ldap_pwd))) { * if (LDAP_SUCCESS != (retval = ldap_simple_bind_s(ld, ldap_user, ldap_pwd))) {
* report (RPT_ERR, "LDAP login on %s:%d failed: %s", ldap_host, ldap_port, ldap_err2string (retval)); * report(RPT_ERR, "LDAP login on %s:%d failed: %s", ldap_host, ldap_port, ldap_err2string(retval));
* ldap_unbind (ld); * ldap_unbind(ld);
* ld = NULL; * ld = NULL;
* *
* return (-1); * return(-1);
* } * }
* fprintf(stderr, "LDAP login successful on %s:%d\n", ldap_host, ldap_port); * fprintf(stderr, "LDAP login successful on %s:%d\n", ldap_host, ldap_port);
********************************************************/ ********************************************************/
/* check for the existence of the config object... */ /* check for the existence of the config object... */
if (LDAP_SUCCESS != (retval = ldap_search_s (ld, ldap_base_dn, LDAP_SCOPE_BASE, "objectClass=lcdprocConfig", NULL, 0, &res))) { if (LDAP_SUCCESS != (retval = ldap_search_s(ld, ldap_base_dn, LDAP_SCOPE_BASE, "objectClass=lcdprocConfig", NULL, 0, &res))) {
report( RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port); report(RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
return (-1); return(-1);
} }
if (0 == ldap_count_entries(ld, res)) { if (0 == ldap_count_entries(ld, res)) {
report( RPT_ERR, "No configuration object found in LDAP at: %s", ldap_base_dn); report(RPT_ERR, "No configuration object found in LDAP at: %s", ldap_base_dn);
return (-1); return(-1);
} }
debug( RPT_DEBUG, "Configuration LDAP object found."); debug(RPT_DEBUG, "Configuration LDAP object found.");
return 0; return 0;
} }
#define BUFSIZE 255 #define BUFSIZE 255
#endif /* WITH_LDAP_SUPPORT */ #endif /* WITH_LDAP_SUPPORT */
section * find_section( char * sectionname ) section * find_section(char * sectionname)
{ {
section * s; section *s;
#ifdef WITH_LDAP_SUPPORT #ifdef WITH_LDAP_SUPPORT
LDAPMessage * res; LDAPMessage *res;
int retval; int retval;
char *filter=NULL; char *filter = NULL;
if (use_ldap) { if (use_ldap) {
debug( RPT_DEBUG, "Searching LDAP for section [%s]", sectionname); debug(RPT_DEBUG, "Searching LDAP for section [%s]", sectionname);
if (NULL == (filter = malloc(BUFSIZE))){ if (NULL == (filter = malloc(BUFSIZE))){
report( RPT_ERR, "Could not allocate memory in find_section()"); report(RPT_ERR, "Could not allocate memory in find_section()");
return NULL; return NULL;
} }
strcpy(filter, "cn="); strcpy(filter, "cn=");
strncat(filter, sectionname, BUFSIZE); strncat(filter, sectionname, BUFSIZE);
if (LDAP_SUCCESS != (retval = ldap_search_s (ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &res))) { if (LDAP_SUCCESS != (retval = ldap_search_s(ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &res))) {
if (NULL != filter) { if (NULL != filter) {
free(filter); free(filter);
filter=NULL; filter = NULL;
} }
ldap_msgfree(res); ldap_msgfree(res);
report( RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port); report(RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
return NULL; return NULL;
} }
if (NULL != filter) { if (NULL != filter) {
free(filter); free(filter);
filter=NULL; filter = NULL;
} }
if (0 == ldap_count_entries( ld, res )) { if (0 == ldap_count_entries(ld, res)) {
debug( RPT_DEBUG, "Section [%s] not found in LDAP.", sectionname); debug(RPT_DEBUG, "Section [%s] not found in LDAP.", sectionname);
return NULL; return NULL;
} }
ldap_msgfree(res); ldap_msgfree(res);
debug( RPT_DEBUG, "Found section [%s] in LDAP", sectionname); debug(RPT_DEBUG, "Found section [%s] in LDAP", sectionname);
s = (section*) malloc( sizeof( section )); s = (section*) malloc(sizeof(section));
s->name=strdup( sectionname ); if (s != NULL) {
s->first_key = NULL; s->name = strdup(sectionname);
s->next_section = NULL; s->first_key = NULL;
s->next_section = NULL;
}
return s; return s;
} }
#endif /* WITH_LDAP_SUPPORT */ #endif /* WITH_LDAP_SUPPORT */
for( s=first_section; s; s=s->next_section ) { for (s = first_section; s != NULL; s = s->next_section) {
if( strcasecmp( s->name, sectionname ) == 0 ) { if (strcasecmp(s->name, sectionname) == 0) {
return s; return s;
} }
} }
return NULL; /* not found*/ return NULL; /* not found */
} }
section * add_section( char * sectionname ) section * add_section(char * sectionname)
{ {
section *s; section *s;
section ** place = &first_section; section **place = &first_section;
for( s=first_section; s; s=s->next_section ) for (s = first_section; s != NULL; s = s->next_section)
place = &(s->next_section); place = &(s->next_section);
*place = (section*) malloc( sizeof( section )); *place = (section*) malloc(sizeof(section));
(*place)->name = strdup( sectionname ); if (*place != NULL) {
(*place)->first_key = NULL; (*place)->name = strdup(sectionname);
(*place)->next_section = NULL; (*place)->first_key = NULL;
(*place)->next_section = NULL;
}
return (*place); return(*place);
} }
key * find_key( section * s, char * keyname, int skip ) key * find_key(section * s, char * keyname, int skip)
{ {
key * k; key *k;
int count = 0; int count = 0;
key * last_key = NULL; key *last_key = NULL;
#ifdef WITH_LDAP_SUPPORT #ifdef WITH_LDAP_SUPPORT
LDAPMessage * res; LDAPMessage *res;
LDAPMessage * entry; LDAPMessage *entry;
int retval; int retval;
char *buf=NULL; char *buf = NULL;
char **vals; char **vals;
#endif /* WITH_LDAP_SUPPORT */ #endif /* WITH_LDAP_SUPPORT */
/* Check for NULL section*/ /* Check for NULL section*/
if(!s) return NULL; if (s == NULL)
return NULL;
#ifdef WITH_LDAP_SUPPORT #ifdef WITH_LDAP_SUPPORT
if (use_ldap) { if (use_ldap) {
debug( RPT_DEBUG, "Searching LDAP for key '%s' in section [%s] skipping %d entries.", keyname, s->name, skip); debug(RPT_DEBUG, "Searching LDAP for key '%s' in section [%s] skipping %d entries.", keyname, s->name, skip);
if (NULL == (buf = malloc(BUFSIZE))){ if (NULL == (buf = malloc(BUFSIZE))){
report (RPT_ERR, "Could not allocate memory in find_key()."); report(RPT_ERR, "Could not allocate memory in find_key().");
} }
strcpy(buf, "cn="); strcpy(buf, "cn=");
strncat(buf, s->name, BUFSIZE); strncat(buf, s->name, BUFSIZE);
if (LDAP_SUCCESS != (retval = ldap_search_s (ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, buf, NULL, 0, &res))) { if (LDAP_SUCCESS != (retval = ldap_search_s(ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, buf, NULL, 0, &res))) {
if (NULL != buf) { if (NULL != buf) {
free(buf); free(buf);
buf=NULL; buf=NULL;
} }
ldap_msgfree(res); ldap_msgfree(res);
report( RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port); report(RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
return NULL; return NULL;
} }
if (NULL == (entry = ldap_first_entry( ld, res ))) { if (NULL == (entry = ldap_first_entry(ld, res))) {
debug( RPT_DEBUG, "Section [%s] not found in LDAP.", s->name); debug(RPT_DEBUG, "Section [%s] not found in LDAP.", s->name);
if (NULL != buf) { if (NULL != buf) {
free(buf); free(buf);
buf=NULL; buf = NULL;
} }
/* DON'T enable the following /* DON'T enable the following
* ldap_msgfree(entry); * ldap_msgfree(entry);
@@ -463,14 +444,14 @@ key * find_key( section * s, char * keyname, int skip )
strcpy(buf, "lcdproc"); strcpy(buf, "lcdproc");
strncat(buf, keyname, BUFSIZE); strncat(buf, keyname, BUFSIZE);
/* debug( RPT_DEBUG, "Key name translated to attribute name: %s", buf); */ /* debug(RPT_DEBUG, "Key name translated to attribute name: %s", buf); */
vals = ldap_get_values (ld, entry, buf); vals = ldap_get_values(ld, entry, buf);
if (skip+1 > ldap_count_values (vals)) { if (skip+1 > ldap_count_values(vals)) {
debug( RPT_DEBUG, "No such entry found."); debug(RPT_DEBUG, "No such entry found.");
if (NULL != buf) { if (NULL != buf) {
free(buf); free(buf);
buf=NULL; buf = NULL;
} }
ldap_value_free(vals); ldap_value_free(vals);
/* DON'T enable the following /* DON'T enable the following
@@ -488,71 +469,78 @@ key * find_key( section * s, char * keyname, int skip )
if (vals && vals[skip]) { if (vals && vals[skip]) {
if (NULL != buf) { if (NULL != buf) {
free(buf); free(buf);
buf=NULL; buf = NULL;
} }
buf=strdup(vals[skip]); buf=strdup(vals[skip]);
debug( RPT_DEBUG, "Entry found. Value is: %s", buf); debug(RPT_DEBUG, "Entry found. Value is: %s", buf);
ldap_value_free (vals); ldap_value_free(vals);
k=(key*) malloc( sizeof( key )); k = (key *) malloc(sizeof(key));
k->name = strdup( keyname ); if ( k != NULL) {
k->value = strdup( buf ); k->name = strdup(keyname);
k->next_key = NULL; k->value = strdup(buf);
k->next_key = NULL;
}
if (NULL != buf) { if (NULL != buf) {
free(buf); free(buf);
buf=NULL; buf = NULL;
} }
return k; return k;
} }
report( RPT_ERR, "LDAP server encountered errors."); report(RPT_ERR, "LDAP server encountered errors.");
ldap_value_free (vals); ldap_value_free(vals);
if (NULL != buf) { if (NULL != buf) {
free(buf); free(buf);
buf=NULL; buf = NULL;
} }
return NULL; return NULL;
} }
#endif /* WITH_LDAP_SUPPORT */ #endif /* WITH_LDAP_SUPPORT */
for( k=s->first_key; k; k=k->next_key ) { for (k = s->first_key; k != NULL; k = k->next_key) {
/* Did we find the right key ?*/ /* Did we find the right key ?*/
if( strcasecmp( k->name, keyname ) == 0 ) { if (strcasecmp(k->name, keyname) == 0) {
if( count == skip ) { if (count == skip)
return k; return k;
} else {
count ++; count++;
last_key = k; last_key = k;
}
} }
} }
if( skip == -1 ) { if (skip == -1)
return last_key; return last_key;
}
return NULL; /* not found*/ return NULL; /* not found*/
} }
key * add_key( section * s, char * keyname, char * value ) key * add_key(section * s, char * keyname, char * value)
{ {
key * k; if (s != NULL) {
key *k;
key **place = &(s->first_key);
key ** place = &( s->first_key ); for (k = s->first_key; k != NULL; k = k->next_key)
place = &(k->next_key);
for( k=s->first_key; k; k=k->next_key ) *place = (key *) malloc(sizeof(key));
place = &(k->next_key); if (*place != NULL) {
(*place)->name = strdup(keyname);
(*place)->value = strdup(value);
(*place)->next_key = NULL;
}
*place = (key*) malloc( sizeof( key )); return(*place);
(*place)->name = strdup( keyname ); }
(*place)->value = strdup( value ); return NULL;
(*place)->next_key = NULL;
return (*place);
} }
char get_next_char_f(buffile * f) { char get_next_char_f(buffile * f)
{
char * buf = buffile_read(f, 1); char * buf = buffile_read(f, 1);
char c = buf[0]; char c = buf[0];
free(buf); free(buf);
return c; return c;
} }
@@ -579,7 +567,7 @@ char get_next_char_f(buffile * f) {
int process_config( section ** current_section, char (*get_next_char)(), char modify_section_allowed, char * source_descr, buffile * f) int process_config(section ** current_section, char(*get_next_char)(), char modify_section_allowed, char * source_descr, buffile * f)
{ {
char state = ST_INITIAL; char state = ST_INITIAL;
char ch; char ch;
@@ -590,26 +578,22 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
char value[MAXVALUELENGTH+1]; char value[MAXVALUELENGTH+1];
int value_pos = 0; int value_pos = 0;
int quote = 0; int quote = 0;
key * k; key *k;
int line_nr = 1; int line_nr = 1;
while( state != ST_END ) { while (state != ST_END) {
if (NULL != f) { ch = (f != NULL)
ch = get_next_char(f); ? get_next_char(f)
} : get_next_char();
else {
ch = get_next_char();
}
/* Secretly keep count of the line numbers*/ /* Secretly keep count of the line numbers*/
if( ch == '\n' ) { if (ch == '\n')
line_nr ++; line_nr++;
}
switch( state ) { switch (state) {
case ST_INITIAL: case ST_INITIAL:
switch( ch ) { switch (ch) {
case '\n': case '\n':
case '\r': case '\r':
case '\t': case '\t':
@@ -639,16 +623,17 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
} }
break; break;
case ST_IGNORE: case ST_IGNORE:
switch( ch ) { switch (ch) {
case '\n': case '\n':
state = ST_INITIAL; state = ST_INITIAL;
break; break;
} }
break; break;
case ST_SECTIONNAME: case ST_SECTIONNAME:
switch( ch ) { switch (ch) {
case '\0':
case '\n': case '\n':
report( RPT_WARNING, "Section name incorrectly closed on line %d of %s: %s", line_nr, source_descr, sectionname ); report(RPT_WARNING, "Section name incorrectly closed on line %d of %s: %s", line_nr, source_descr, sectionname);
state = ST_INITIAL; state = ST_INITIAL;
break; break;
case '\r': case '\r':
@@ -656,30 +641,27 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
case ' ': case ' ':
case '"': case '"':
case '[': case '[':
report( RPT_WARNING, "Section name contains invalid chars on line %d of %s: %s", line_nr, source_descr, sectionname ); report(RPT_WARNING, "Section name contains invalid chars on line %d of %s: %s", line_nr, source_descr, sectionname);
state = ST_INVALID_SECTIONNAME; state = ST_INVALID_SECTIONNAME;
break; break;
case ']': case ']':
if( !( *current_section=find_section( sectionname ))) { if (!(*current_section=find_section(sectionname))) {
*current_section=add_section( sectionname ); *current_section=add_section(sectionname);
} }
state = ST_INITIAL; state = ST_INITIAL;
break; break;
case '\0':
report( RPT_WARNING, "Section name incorrectly closed on line %d of %s: %s", line_nr, source_descr, sectionname );
break;
default: default:
if( sectionname_pos < MAXSECTIONNAMELENGTH ) { if (sectionname_pos < MAXSECTIONNAMELENGTH) {
sectionname[sectionname_pos++] = ch; sectionname[sectionname_pos++] = ch;
sectionname[sectionname_pos] = '\0'; sectionname[sectionname_pos] = '\0';
} else { } else {
report( RPT_WARNING, "Section name too long on line %d of %s: %s", line_nr, source_descr, sectionname ); report(RPT_WARNING, "Section name too long on line %d of %s: %s", line_nr, source_descr, sectionname);
state = ST_INVALID_SECTIONNAME; state = ST_INVALID_SECTIONNAME;
} }
} }
break; break;
case ST_INVALID_SECTIONNAME: case ST_INVALID_SECTIONNAME:
switch( ch ) { switch (ch) {
case '\n': case '\n':
case ']': case ']':
state = ST_INITIAL; state = ST_INITIAL;
@@ -687,19 +669,19 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
} }
break; break;
case ST_KEYNAME: case ST_KEYNAME:
switch( ch ) { switch (ch) {
case '\0': case '\0':
case '\n': case '\n':
case '\r': case '\r':
case '\t': case '\t':
case ' ': case ' ':
report( RPT_WARNING, "Loose word found on line %d of %s: %s", line_nr, source_descr, keyname ); report(RPT_WARNING, "Loose word found on line %d of %s: %s", line_nr, source_descr, keyname);
state = ST_INITIAL; state = ST_INITIAL;
break; break;
case '"': case '"':
case '[': case '[':
case ']': case ']':
report( RPT_WARNING, "Key name contains invalid characters on line %d of %s: %s", line_nr, source_descr, keyname ); report(RPT_WARNING, "Key name contains invalid characters on line %d of %s: %s", line_nr, source_descr, keyname);
state = ST_INVALID_KEYNAME; state = ST_INVALID_KEYNAME;
break; break;
case '=': case '=':
@@ -708,8 +690,8 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
value_pos = 0; value_pos = 0;
break; break;
default: default:
if( keyname_pos>=MAXKEYNAMELENGTH ) { if (keyname_pos>=MAXKEYNAMELENGTH) {
report( RPT_WARNING, "Key name too long on line %d of %s: %s", line_nr, source_descr, keyname ); report(RPT_WARNING, "Key name too long on line %d of %s: %s", line_nr, source_descr, keyname);
state = ST_INVALID_KEYNAME; state = ST_INVALID_KEYNAME;
} else { } else {
keyname[keyname_pos++] = ch; keyname[keyname_pos++] = ch;
@@ -718,20 +700,20 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
} }
break; break;
case ST_INVALID_KEYNAME: case ST_INVALID_KEYNAME:
switch( ch ) { switch (ch) {
case '\n': case '\n':
state = ST_INITIAL; state = ST_INITIAL;
/*case ' ':*/ /*case ' ':*/
} }
break; break;
case ST_VALUE: case ST_VALUE:
switch( ch ) { switch (ch) {
case '[': case '[':
case ']': case ']':
case '#': case '#':
case ';': case ';':
case '=': case '=':
report( RPT_WARNING, "Value contains invalid characters on line %d of %s, at key: %s", line_nr, source_descr, keyname ); report(RPT_WARNING, "Value contains invalid characters on line %d of %s, at key: %s", line_nr, source_descr, keyname);
state = ST_INVALID_VALUE; state = ST_INVALID_VALUE;
break; break;
case '"': case '"':
@@ -743,28 +725,28 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
case '\t': case '\t':
case ' ': case ' ':
/* Value complete !*/ /* Value complete !*/
if( ! *current_section ) { if (! *current_section) {
report( RPT_WARNING, "Data before any section on line %d of %s with key: %s", line_nr, source_descr, keyname ); report(RPT_WARNING, "Data before any section on line %d of %s with key: %s", line_nr, source_descr, keyname);
} }
else { else {
/* Store the value*/ /* Store the value*/
k = add_key( *current_section, keyname, value ); k = add_key(*current_section, keyname, value);
} }
/* And be ready for next thing...*/ /* And be ready for next thing...*/
state = ST_INITIAL; state = ST_INITIAL;
break; break;
default: default:
if( value_pos<MAXVALUELENGTH ) { if (value_pos<MAXVALUELENGTH) {
value[value_pos++] = ch; value[value_pos++] = ch;
value[value_pos] = '\0'; value[value_pos] = '\0';
} else { } else {
report( RPT_WARNING, "Value key is too long on line %d of %s, at key: %s", line_nr, source_descr, keyname ); report(RPT_WARNING, "Value key is too long on line %d of %s, at key: %s", line_nr, source_descr, keyname);
state = ST_INVALID_KEYNAME; state = ST_INVALID_KEYNAME;
} }
} }
break; break;
case ST_INVALID_VALUE: case ST_INVALID_VALUE:
switch( ch ) { switch (ch) {
case '\n': case '\n':
state = ST_INITIAL; state = ST_INITIAL;
break; break;
@@ -773,25 +755,25 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
} }
break; break;
case ST_QUOTEDVALUE: case ST_QUOTEDVALUE:
switch( ch ) { switch (ch) {
case '\0': case '\0':
case '\n': case '\n':
report( RPT_WARNING, "String is incorrectly terminated on line %d of %s: %s", line_nr, source_descr, keyname ); report(RPT_WARNING, "String is incorrectly terminated on line %d of %s: %s", line_nr, source_descr, keyname);
state = ST_INITIAL; state = ST_INITIAL;
break; break;
case '\\': case '\\':
if( !quote ) { if (!quote) {
quote = 1; quote = 1;
break; break;
} }
case '"': case '"':
if( !quote ) { if (!quote) {
state = ST_VALUE; state = ST_VALUE;
break; break;
} }
default: default:
if( quote ) { if (quote) {
switch( ch ) { switch (ch) {
case 'n': ch = '\n'; break; case 'n': ch = '\n'; break;
case 'r': ch = '\r'; break; case 'r': ch = '\r'; break;
case 't': ch = '\t'; break; case 't': ch = '\t'; break;
@@ -804,7 +786,7 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
} }
break; break;
case ST_INVALID_QUOTEDVALUE: case ST_INVALID_QUOTEDVALUE:
switch( ch ) { switch (ch) {
case '\n': case '\n':
state = ST_INITIAL; state = ST_INITIAL;
break; break;
@@ -813,10 +795,27 @@ int process_config( section ** current_section, char (*get_next_char)(), char mo
} }
break; break;
} }
if( ch == '\0' ) { if (ch == '\0') {
state = ST_END; state = ST_END;
} }
} }
return 0; return 0;
} }
#if 0
void config_dump(void)
{
section *s;
for (s = first_section; s != NULL; s = s->next_section) {
key *k;
fprintf(stderr, "[%s]\n", s->name);
for (k = s->first_key; k != NULL; k = k->next_key)
fprintf(stderr, "%s = '%s'\n", k->name, k->value);
fprintf(stderr, "\n");
}
}
#endif