~ubuntu-branches/ubuntu/trusty/lcdproc/trusty-proposed

« back to all changes in this revision

Viewing changes to shared/configfile.c

  • Committer: Bazaar Package Importer
  • Author(s): Jose Luis Tallon
  • Date: 2006-10-15 14:48:37 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20061015144837-wybst1fonzi46a0c
Tags: 0.5.1-1
* New upstream version
  - Fixes compiling on hppa (Closes: #389294)
  - Many new features and some config changes. Please read upstream's
  release notes for more information

* Avoid needing a /etc/mtab file at build time (Closes: #391912)

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * This file is released under the GNU General Public License. Refer to the
6
6
 * COPYING file distributed with this package.
7
7
 *
8
 
 * Copyright (c) 2001, Joris Robijn
9
 
 *           (c) 2003, Rene Wagner
 
8
 * Copyright(c) 2001, Joris Robijn
 
9
 *          (c) 2003, Rene Wagner
10
10
 *
11
11
 *
12
12
 * Defines routines to read ini-file-like files.
13
 
 * Optionally retrieves settings from an LDAP directory (OpenLDAP 2.1.x)
 
13
 * Optionally retrieves settings from an LDAP directory(OpenLDAP 2.1.x)
14
14
 */
15
15
 
16
16
#include "config.h"
25
25
#endif /* WITH_LDAP_SUPPORT */
26
26
 
27
27
#include "shared/report.h"
28
 
#include "shared/fileio.h"
29
28
 
30
29
 
31
30
typedef struct key {
32
 
        char * name;
33
 
        char * value;
34
 
        struct key * next_key;
 
31
        char *name;
 
32
        char *value;
 
33
        struct key *next_key;
35
34
} key;
36
35
 
37
36
typedef struct section {
38
 
        char * name;
39
 
        key * first_key;
40
 
        struct section * next_section;
 
37
        char *name;
 
38
        key *first_key;
 
39
        struct section *next_section;
41
40
} section;
42
41
 
43
42
 
44
 
static section * first_section = NULL;
 
43
static section *first_section = NULL;
45
44
/* Yes there is a static. It's C after all :)*/
46
45
 
47
46
 
48
 
section * find_section( char * sectionname );
49
 
section * add_section( char * sectionname );
50
 
key * find_key( section * s, char * keyname, int skip );
51
 
key * add_key( section * s, char * keyname, char * value );
52
 
char get_next_char_f(buffile * f);
53
 
int process_config( section ** current_section, char (*get_next_char)(), char modify_section_allowed, char * source_descr, buffile * f );
 
47
static section *find_section(const char *sectionname);
 
48
static section *add_section(const char *sectionname);
 
49
static key *find_key(section *s, const char *keyname, int skip);
 
50
static key *add_key(section *s, const char *keyname, const char *value);
 
51
static char get_next_char_f(FILE *f);
 
52
static int process_config(section **current_section, char(*get_next_char)(), const char *source_descr, FILE *f);
 
53
 
54
54
 
55
55
#ifdef WITH_LDAP_SUPPORT
56
 
int connect_to_ldap(void);
57
 
 
58
 
static LDAP * ld = NULL;
59
 
int use_ldap=0;
60
 
 
61
 
static char * ldap_host=NULL, * ldap_base_dn=NULL;
 
56
static int connect_to_ldap(void);
 
57
 
 
58
static LDAP *ld = NULL;
 
59
int use_ldap = 0;
 
60
 
 
61
static char *ldap_host = NULL, *ldap_base_dn = NULL;
62
62
int ldap_port;
63
63
 
64
64
/* not supported for now
67
67
 */
68
68
#endif /* WITH_LDAP_SUPPORT */
69
69
 
70
 
/**** EXTERNAL FUNCTIONS ****/
71
 
 
72
 
int config_read_file( char *filename )
 
70
 
 
71
/**** PUBLIC FUNCTIONS ****/
 
72
 
 
73
/** Parse configuration from INI-file style config file into memory.
 
74
 * \param filename Name of the config file.
 
75
 * \returns 0 : config successfully parsed
 
76
 * \returns <0 : error occurred
 
77
 */
 
78
int config_read_file(const char *filename)
73
79
{
74
 
        buffile * f;
75
 
        section * curr_section = NULL;
 
80
        FILE *f;
 
81
        section *curr_section = NULL;
 
82
        int result = 0;
76
83
 
77
84
#ifdef WITH_LDAP_SUPPORT
78
 
        LDAPURLDesc * url = NULL;
 
85
        LDAPURLDesc *url = NULL;
79
86
        int retval;
80
87
#endif /* WITH_LDAP_SUPPORT */   
81
88
 
82
 
        report( RPT_NOTICE, "Using Configuration File: %s", filename);
 
89
        report(RPT_NOTICE, "Using Configuration File: %s", filename);
83
90
 
84
91
#ifdef WITH_LDAP_SUPPORT
85
 
        if (ldap_is_ldap_url( filename )) {
86
 
                use_ldap=1;
87
 
                
88
 
                if (0 != (retval = ldap_url_parse( filename, &url))) {
89
 
                        report( RPT_ERR, "Errors parsing LDAP URL %s: %s", filename, ldap_err2string(retval));
 
92
        if (ldap_is_ldap_url(filename)) {
 
93
                use_ldap = 1;
 
94
 
 
95
                if (0 != (retval = ldap_url_parse(filename, &url))) {
 
96
                        report(RPT_ERR, "Errors parsing LDAP URL %s: %s", filename, ldap_err2string(retval));
90
97
                        ldap_free_urldesc(url);
91
 
                        return (-1);
 
98
                        return(-1);
92
99
                }
93
100
 
94
 
                ldap_host=strdup(url->lud_host);
95
 
                ldap_port=url->lud_port;
96
 
                report( RPT_INFO, "Using LDAP server: %s:%d", ldap_host, ldap_port);
 
101
                ldap_host = strdup(url->lud_host);
 
102
                ldap_port = url->lud_port;
 
103
                report(RPT_INFO, "Using LDAP server: %s:%d", ldap_host, ldap_port);
97
104
 
98
 
                ldap_base_dn=strdup(url->lud_dn);
99
 
                report( RPT_INFO, "Using LDAP base DN: %s", ldap_base_dn);
 
105
                ldap_base_dn = strdup(url->lud_dn);
 
106
                report(RPT_INFO, "Using LDAP base DN: %s", ldap_base_dn);
100
107
 
101
108
                ldap_free_urldesc(url);
102
109
 
103
 
                if (connect_to_ldap() < 0 ) {
104
 
                        debug( RPT_DEBUG, "connect_to_ldap returned errors.");
105
 
                        return (-1);
 
110
                if (connect_to_ldap() < 0) {
 
111
                        debug(RPT_DEBUG, "connect_to_ldap returned errors.");
 
112
                        return(-1);
106
113
                }
107
114
 
108
115
                return 0;
109
116
        }
110
117
#endif /* WITH_LDAP_SUPPORT */ 
111
118
 
112
 
        f = buffile_open( filename, "r" );
113
 
        if( f==NULL ) {
 
119
        f = fopen(filename, "r");
 
120
        if (f == NULL) {
114
121
                return -1;
115
122
        }
116
123
 
117
 
        process_config( &curr_section, get_next_char_f, 1, filename, f );
118
 
 
119
 
        buffile_close( f );
120
 
 
121
 
        return 0;
 
124
        result = process_config(&curr_section, get_next_char_f, filename, f);
 
125
 
 
126
        fclose(f);
 
127
 
 
128
        return result;
122
129
}
123
130
 
124
131
 
125
 
int config_read_string( char *sectionname, char *str )
 
132
int config_read_string(const char *sectionname, const char *str)
126
133
/* All the config parameters are placed in the given section in memory.*/
127
134
{
128
 
        int pos=0;
129
 
        section * s;
 
135
        int pos = 0;
 
136
        section *s;
130
137
 
131
138
        /* We use a nested fuction to transfer the characters from buffer to parser*/
132
139
        char get_next_char() {
133
140
                return str[pos++];
134
141
        }
135
142
 
136
 
        if( !( s=find_section( sectionname ))) {
137
 
                s=add_section( sectionname );
138
 
        }
139
 
 
140
 
        process_config( &s, get_next_char, 0, "command line", NULL );
141
 
 
142
 
        return 0;
 
143
        if ((s = find_section(sectionname)) == NULL)
 
144
                s = add_section(sectionname);
 
145
 
 
146
        return process_config(&s, get_next_char, "command line", NULL);
143
147
}
144
148
 
145
149
 
146
 
char *config_get_string( char * sectionname, char * keyname,
147
 
                int skip, char * default_value )
 
150
/** Get string from configuration in memory.
 
151
 * \param sectionname   Name of the section where the key is sought.
 
152
 * \param keyname       Name of the key to look for.
 
153
 * \param skip          Number of values to skip/ignore before returning the value.
 
154
 * \param default_value Default value if section/key is not found.
 
155
 * \return Value found / default value
 
156
 */
 
157
const char *config_get_string(const char *sectionname, const char *keyname,
 
158
                int skip, const char *default_value)
148
159
{
149
 
        section * s;
150
 
        key * k;
 
160
        key *k = find_key(find_section(sectionname), keyname, skip);
151
161
 
152
 
        s = find_section( sectionname );
153
 
        if( !s ) return default_value;
154
 
        k = find_key( s, keyname, skip );
155
 
        if( !k ) return default_value;
 
162
        if (k == NULL)
 
163
                return default_value;
156
164
 
157
165
        return k->value;
158
166
 
160
168
 
161
169
        /* Reallocate memory space for the return value*/
162
170
        /*
163
 
        string_storage = realloc( string_storage, ( strlen( k->value ) / 256 + 1) * 256 );
164
 
        strcpy( string_storage, k->value );
 
171
        string_storage = realloc(string_storage,(strlen(k->value) / 256 + 1) * 256);
 
172
        strcpy(string_storage, k->value);
165
173
 
166
174
   But then you also need a global static string_storage = NULL;
167
175
*/
168
176
}
169
177
 
170
178
 
171
 
short config_get_bool( char *sectionname, char *keyname,
172
 
                int skip, short default_value )
 
179
/** Get boolean value from configuration in memory.
 
180
 * \param sectionname   Name of the section where the key is sought.
 
181
 * \param keyname       Name of the key to look for.
 
182
 * \param skip          Number of values to skip/ignore before returning the value.
 
183
 * \param default_value Default value if section/key is not found or value is no legal boolean.
 
184
 * \return Value found / default value
 
185
 */
 
186
short config_get_bool(const char *sectionname, const char *keyname,
 
187
                int skip, short default_value)
173
188
{
174
 
        section * s;
175
 
        key * k;
176
 
 
177
 
        s = find_section( sectionname );
178
 
        if( !s ) return default_value;
179
 
        k = find_key( s, keyname, skip );
180
 
        if( !k ) return default_value;
181
 
 
182
 
        if( strcasecmp( k->value, "0" )==0 || strcasecmp( k->value, "false" )==0
183
 
        || strcasecmp( k->value, "n" )==0 || strcasecmp( k->value, "no" )==0 ) {
 
189
        key *k = find_key(find_section(sectionname), keyname, skip);
 
190
 
 
191
        if (k == NULL)
 
192
                return default_value;
 
193
 
 
194
        if (strcasecmp(k->value, "0") == 0 || strcasecmp(k->value, "false") == 0
 
195
        || strcasecmp(k->value, "n") == 0 || strcasecmp(k->value, "no") == 0 
 
196
        || strcasecmp(k->value, "off") == 0) {
184
197
                return 0;
185
198
        }
186
 
        if( strcasecmp( k->value, "1" )==0 || strcasecmp( k->value, "true" )==0
187
 
        || strcasecmp( k->value, "y" )==0 || strcasecmp( k->value, "yes" )==0 ) {
 
199
        if (strcasecmp(k->value, "1") == 0 || strcasecmp(k->value, "true") == 0
 
200
        || strcasecmp(k->value, "y") == 0 || strcasecmp(k->value, "yes") == 0
 
201
        || strcasecmp(k->value, "on") == 0) {
188
202
                return 1;
189
203
        }
190
204
        return default_value;
191
205
}
192
206
 
193
207
 
194
 
long int config_get_int( char *sectionname, char *keyname,
195
 
                int skip, long int default_value )
196
 
{
197
 
        section * s;
198
 
        key * k;
199
 
        long int v;
200
 
        char * v_end;
201
 
 
202
 
        s = find_section( sectionname );
203
 
        if( !s ) return default_value;
204
 
        k = find_key( s, keyname, skip );
205
 
        if( !k ) return default_value;
206
 
 
207
 
        v = strtol( k->value, &v_end, 0 );
208
 
        if( v_end-(k->value) != strlen(k->value) ) {
209
 
                /* Conversion not succesful*/
210
 
                return default_value;
211
 
        }
212
 
        return v;
213
 
}
214
 
 
215
 
 
216
 
double config_get_float( char *sectionname, char *keyname,
217
 
                int skip, double default_value )
218
 
{
219
 
        section * s;
220
 
        key * k;
221
 
        double v;
222
 
        char * v_end;
223
 
 
224
 
        s = find_section( sectionname );
225
 
        if( !s ) return default_value;
226
 
        k = find_key( s, keyname, skip );
227
 
        if( !k ) return default_value;
228
 
 
229
 
        v = strtod( k->value, &v_end );
230
 
        if( v_end-(k->value) != strlen(k->value) ) {
231
 
                /* Conversion not succesful*/
232
 
                return default_value;
233
 
        }
234
 
        return v;
235
 
}
236
 
 
237
 
 
238
 
int config_has_section( char *sectionname )
239
 
{
240
 
        section * s;
241
 
 
242
 
        s = find_section( sectionname );
243
 
        if( s ) return 1; else return 0;
244
 
}
245
 
 
246
 
 
247
 
int config_has_key( char *sectionname, char *keyname )
248
 
{
249
 
        section * s;
250
 
        key * k;
251
 
 
 
208
/** Get integer from configuration in memory.
 
209
 * \param sectionname   Name of the section where the key is sought.
 
210
 * \param keyname       Name of the key to look for.
 
211
 * \param skip          Number of values to skip/ignore before returning the value.
 
212
 * \param default_value Default value if section/key is not found or value is no integer.
 
213
 * \return Value found / default value
 
214
 */
 
215
long int config_get_int(const char *sectionname, const char *keyname,
 
216
                int skip, long int default_value)
 
217
{
 
218
        key *k = find_key(find_section(sectionname), keyname, skip);
 
219
 
 
220
        if (k != NULL) {
 
221
                char *end;
 
222
                long int v = strtol(k->value, &end, 0);
 
223
 
 
224
                if ((end != NULL) && (end != k->value) && (*end == '\0'))
 
225
                        /* Conversion succesful */
 
226
                        return v;
 
227
        }
 
228
        return default_value;
 
229
}
 
230
 
 
231
 
 
232
/** Get floating point number from configuration in memory.
 
233
 * \param sectionname   Name of the section where the key is sought.
 
234
 * \param keyname       Name of the key to look for.
 
235
 * \param skip          Number of values to skip/ignore before returning the value.
 
236
 * \param default_value Default value if section/key is not found or value is no floating point number.
 
237
 * \return Value found / default value
 
238
 */
 
239
double config_get_float(const char *sectionname, const char *keyname,
 
240
                int skip, double default_value)
 
241
{
 
242
        key *k = find_key(find_section(sectionname), keyname, skip);
 
243
 
 
244
        if (k != NULL) {
 
245
                char *end;
 
246
                double v = strtod(k->value, &end);
 
247
 
 
248
                if ((end != NULL) && (end != k->value) && (*end == '\0'))
 
249
                        /* Conversion succesful*/
 
250
                        return v;
 
251
        }
 
252
        return default_value;
 
253
}
 
254
 
 
255
 
 
256
/** Test whether the configuration containis a specific section.
 
257
 * \param sectionname Name of the section to look for.
 
258
 * \return 0 = section not in config; 1 = section in config
 
259
 */
 
260
int config_has_section(const char *sectionname)
 
261
{
 
262
        return (find_section(sectionname) != NULL) ? 1 : 0;
 
263
}
 
264
 
 
265
 
 
266
/** Test whether the configuration contains a specific key in a specfic section.
 
267
 * \param sectionname Name of the section where the key is sought.
 
268
 * \param keyname     Name of the key to look for.
 
269
 * \return 0 =  key or section not found; n = key found with n values
 
270
 */
 
271
int config_has_key(const char *sectionname, const char *keyname)
 
272
{
 
273
        section *s = find_section(sectionname);
252
274
        int count = 0;
253
275
 
254
 
        s = find_section( sectionname );
255
 
        if( !s ) return 0;
256
 
 
257
 
        for( k=s->first_key; k; k=k->next_key ) {
258
 
 
259
 
                /* Did we find the right key ?*/
260
 
                if( strcasecmp( k->name, keyname ) == 0 ) {
261
 
                        count ++;
262
 
                }
 
276
        if (s != NULL) {
 
277
                key *k;
 
278
 
 
279
                for (k = s->first_key; k != NULL; k = k->next_key) {
 
280
                        /* Did we find the right key ?*/
 
281
                        if (strcasecmp(k->name, keyname) == 0)
 
282
                                count++;
 
283
                }       
263
284
        }
264
285
        return count;
265
286
}
266
287
 
267
288
 
 
289
/** Clear configuration. */
268
290
void config_clear()
269
291
{
270
 
        section * s;
271
 
        section * next_s;
272
 
        key * k;
273
 
        key * next_k;
274
 
 
275
 
        for( s = first_section; s; ) {
276
 
                for( k=s->first_key; k; ) {
 
292
        section *s;
 
293
        section *next_s;
 
294
 
 
295
        for (s = first_section; s != NULL; s = next_s) {
 
296
                key *k;
 
297
                key *next_k;
 
298
 
 
299
                for (k = s->first_key; k != NULL; k = next_k) {
277
300
                        /* Advance before we destroy the current key */
278
301
                        next_k = k->next_key;
279
302
 
280
 
                        free( k->name );
281
 
                        free( k->value );
282
 
                        free( k );
283
 
 
284
 
                        k = next_k;
 
303
                        free(k->name);
 
304
                        free(k->value);
 
305
                        free(k);
285
306
                }
286
307
                /* Advance before we destroy the current section */
287
308
                next_s = s->next_section;
288
309
 
289
310
                /* And destroy it */
290
 
                free( s->name );
291
 
                free( s );
292
 
 
293
 
                s = next_s;
 
311
                free(s->name);
 
312
                free(s);
294
313
        }
295
 
        /* And make everything inaccessable */
 
314
        /* Finally make everything inaccessable */
296
315
        first_section = NULL;
297
316
}
298
317
 
300
319
/**** INTERNAL FUNCTIONS ****/
301
320
 
302
321
#ifdef WITH_LDAP_SUPPORT
303
 
int
304
 
connect_to_ldap (void)
 
322
static int
 
323
connect_to_ldap(void)
305
324
{
306
325
        int retval;
307
 
        LDAPMessage * res;
 
326
        LDAPMessage *res;
308
327
 
309
 
        debug( RPT_INFO, "Connecting to LDAP server: %s:%d", ldap_host, ldap_port);
 
328
        debug(RPT_INFO, "Connecting to LDAP server: %s:%d", ldap_host, ldap_port);
310
329
 
311
330
        if (!(ld = ldap_init(ldap_host, ldap_port))) {
312
331
                report(RPT_ERR, "LDAP session could not be initialized.");
313
 
                return (-1);
 
332
                return(-1);
314
333
        }
315
334
 
316
335
/*****************************************************
317
336
 * disabled unless you really have a DN/pwd to bind to
318
337
 * WARNING: LCDd should not have LDAP write access!!
319
338
 *
320
 
 *      if (LDAP_SUCCESS != (retval = ldap_simple_bind_s (ld, ldap_user, ldap_pwd))) {
321
 
 *              report (RPT_ERR, "LDAP login on %s:%d failed: %s", ldap_host, ldap_port, ldap_err2string (retval));
322
 
 *              ldap_unbind (ld);
 
339
 *      if (LDAP_SUCCESS != (retval = ldap_simple_bind_s(ld, ldap_user, ldap_pwd))) {
 
340
 *              report(RPT_ERR, "LDAP login on %s:%d failed: %s", ldap_host, ldap_port, ldap_err2string(retval));
 
341
 *              ldap_unbind(ld);
323
342
 *              ld = NULL;
324
343
 *              
325
 
 *              return (-1);
 
344
 *              return(-1);
326
345
 *      }
327
346
 *      fprintf(stderr, "LDAP login successful on %s:%d\n", ldap_host, ldap_port);
328
347
 ********************************************************/
329
 
 
 
348
 
330
349
        /* check for the existence of the config object... */
331
 
        if (LDAP_SUCCESS != (retval = ldap_search_s (ld, ldap_base_dn, LDAP_SCOPE_BASE, "objectClass=lcdprocConfig", NULL, 0, &res))) {
332
 
                report( RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
333
 
                return (-1);
 
350
        if (LDAP_SUCCESS != (retval = ldap_search_s(ld, ldap_base_dn, LDAP_SCOPE_BASE, "objectClass=lcdprocConfig", NULL, 0, &res))) {
 
351
                report(RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
 
352
                return(-1);
334
353
        }
335
354
        if (0 == ldap_count_entries(ld, res)) {
336
 
                report( RPT_ERR, "No configuration object found in LDAP at: %s", ldap_base_dn);
337
 
                return (-1);
 
355
                report(RPT_ERR, "No configuration object found in LDAP at: %s", ldap_base_dn);
 
356
                return(-1);
338
357
        }
339
 
        debug( RPT_DEBUG, "Configuration LDAP object found.");
 
358
        debug(RPT_DEBUG, "Configuration LDAP object found.");
340
359
        return 0;
341
360
}
342
361
 
343
362
#define BUFSIZE 255
344
363
#endif /* WITH_LDAP_SUPPORT */
345
364
 
346
 
section * find_section( char * sectionname )
 
365
 
 
366
static section *find_section(const char *sectionname)
347
367
{
348
 
        section * s;
 
368
        section *s;
349
369
 
350
370
#ifdef WITH_LDAP_SUPPORT
351
 
        LDAPMessage * res;
 
371
        LDAPMessage *res;
352
372
        int retval;
353
 
        char *filter=NULL;
 
373
        char *filter = NULL;
354
374
 
355
375
        if (use_ldap) {
356
 
                debug( RPT_DEBUG, "Searching LDAP for section [%s]", sectionname);
 
376
                debug(RPT_DEBUG, "Searching LDAP for section [%s]", sectionname);
357
377
                if (NULL == (filter = malloc(BUFSIZE))){
358
 
                        report( RPT_ERR, "Could not allocate memory in find_section()");
 
378
                        report(RPT_ERR, "Could not allocate memory in find_section()");
359
379
                        return NULL;
360
380
                }
361
381
                strcpy(filter, "cn=");
362
382
                strncat(filter, sectionname, BUFSIZE);
363
 
                if (LDAP_SUCCESS != (retval = ldap_search_s (ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &res))) {
 
383
                if (LDAP_SUCCESS != (retval = ldap_search_s(ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &res))) {
364
384
                        if (NULL != filter) {
365
385
                                free(filter);
366
 
                                filter=NULL;
 
386
                                filter = NULL;
367
387
                        }
368
388
                        ldap_msgfree(res);
369
 
                        report( RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
 
389
                        report(RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
370
390
                        return NULL;
371
391
                }
372
392
                if (NULL != filter) {
373
393
                        free(filter);
374
 
                        filter=NULL;
 
394
                        filter = NULL;
375
395
                }
376
 
                if (0 == ldap_count_entries( ld, res )) {
377
 
                        debug( RPT_DEBUG, "Section [%s] not found in LDAP.", sectionname);
 
396
                if (0 == ldap_count_entries(ld, res)) {
 
397
                        debug(RPT_DEBUG, "Section [%s] not found in LDAP.", sectionname);
378
398
                        return NULL;
379
399
                }
380
400
                ldap_msgfree(res);
381
 
                debug( RPT_DEBUG, "Found section [%s] in LDAP", sectionname);
382
 
                s = (section*) malloc( sizeof( section ));
383
 
                s->name=strdup( sectionname );
384
 
                s->first_key = NULL;
385
 
                s->next_section = NULL;
 
401
                debug(RPT_DEBUG, "Found section [%s] in LDAP", sectionname);
 
402
                s = (section*) malloc(sizeof(section));
 
403
                if (s != NULL) {
 
404
                        s->name = strdup(sectionname);
 
405
                        s->first_key = NULL;
 
406
                        s->next_section = NULL;
 
407
                }
386
408
                return s;
387
409
        }
388
410
#endif /* WITH_LDAP_SUPPORT */
389
411
 
390
 
        for( s=first_section; s; s=s->next_section ) {
391
 
                if( strcasecmp( s->name, sectionname ) == 0 ) {
 
412
        for (s = first_section; s != NULL; s = s->next_section) {
 
413
                if (strcasecmp(s->name, sectionname) == 0) {
392
414
                        return s;
393
415
                }
394
416
        }
395
 
        return NULL; /* not found*/
 
417
        return NULL; /* not found */
396
418
}
397
419
 
398
 
section * add_section( char * sectionname )
 
420
 
 
421
static section *add_section(const char *sectionname)
399
422
{
400
423
        section *s;
401
 
        section ** place = &first_section;
 
424
        section **place = &first_section;
402
425
 
403
 
        for( s=first_section; s; s=s->next_section )
 
426
        for (s = first_section; s != NULL; s = s->next_section)
404
427
                place = &(s->next_section);
405
428
 
406
 
        *place = (section*) malloc( sizeof( section ));
407
 
        (*place)->name = strdup( sectionname );
408
 
        (*place)->first_key = NULL;
409
 
        (*place)->next_section = NULL;
 
429
        *place = (section*) malloc(sizeof(section));
 
430
        if (*place != NULL) {
 
431
                (*place)->name = strdup(sectionname);
 
432
                (*place)->first_key = NULL;
 
433
                (*place)->next_section = NULL;
 
434
        }       
410
435
 
411
 
        return (*place);
 
436
        return(*place);
412
437
}
413
438
 
414
 
key * find_key( section * s, char * keyname, int skip )
 
439
 
 
440
static key *find_key(section *s, const char *keyname, int skip)
415
441
{
416
 
        key * k;
 
442
        key *k;
417
443
        int count = 0;
418
 
        key * last_key = NULL;
 
444
        key *last_key = NULL;
419
445
 
420
446
#ifdef WITH_LDAP_SUPPORT        
421
 
        LDAPMessage * res;
422
 
        LDAPMessage * entry;
 
447
        LDAPMessage *res;
 
448
        LDAPMessage *entry;
423
449
        int retval;
424
 
        char *buf=NULL;
 
450
        char *buf = NULL;
425
451
        char **vals;
426
452
#endif /* WITH_LDAP_SUPPORT */
427
453
 
428
454
        /* Check for NULL section*/
429
 
        if(!s) return NULL;
 
455
        if (s == NULL)
 
456
                return NULL;
430
457
 
431
458
#ifdef WITH_LDAP_SUPPORT
432
459
        if (use_ldap) {
433
 
                debug( RPT_DEBUG, "Searching LDAP for key '%s' in section [%s] skipping %d entries.", keyname, s->name, skip);
 
460
                debug(RPT_DEBUG, "Searching LDAP for key '%s' in section [%s] skipping %d entries.", keyname, s->name, skip);
434
461
 
435
462
                if (NULL == (buf = malloc(BUFSIZE))){
436
 
                        report (RPT_ERR, "Could not allocate memory in find_key().");
 
463
                        report(RPT_ERR, "Could not allocate memory in find_key().");
437
464
                }
438
465
                strcpy(buf, "cn=");
439
466
                strncat(buf, s->name, BUFSIZE);
440
 
                if (LDAP_SUCCESS != (retval = ldap_search_s (ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, buf, NULL, 0, &res))) {
 
467
                if (LDAP_SUCCESS != (retval = ldap_search_s(ld, ldap_base_dn, LDAP_SCOPE_ONELEVEL, buf, NULL, 0, &res))) {
441
468
                        if (NULL != buf) {
442
469
                                free(buf);
443
470
                                buf=NULL;
444
471
                        }
445
472
                        ldap_msgfree(res);
446
 
                        report( RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
 
473
                        report(RPT_ERR, "Could not access LDAP server on %s:%d", ldap_host, ldap_port);
447
474
                        return NULL;
448
475
                }
449
 
                if (NULL == (entry = ldap_first_entry( ld, res ))) {
450
 
                        debug( RPT_DEBUG, "Section [%s] not found in LDAP.", s->name);
 
476
                if (NULL == (entry = ldap_first_entry(ld, res))) {
 
477
                        debug(RPT_DEBUG, "Section [%s] not found in LDAP.", s->name);
451
478
                        if (NULL != buf) {
452
479
                                free(buf);
453
 
                                buf=NULL;
 
480
                                buf = NULL;
454
481
                        }
455
482
                        /* DON'T enable the following
456
483
                         * ldap_msgfree(entry);
460
487
                        return NULL;
461
488
                }
462
489
 
463
 
                
 
490
 
464
491
                strcpy(buf, "lcdproc");
465
492
                strncat(buf, keyname, BUFSIZE);
466
 
                /* debug( RPT_DEBUG, "Key name translated to attribute name: %s", buf); */
467
 
                vals = ldap_get_values (ld, entry, buf);
468
 
                
469
 
                if (skip+1 > ldap_count_values (vals)) {
470
 
                        debug( RPT_DEBUG, "No such entry found.");
 
493
                /* debug(RPT_DEBUG, "Key name translated to attribute name: %s", buf); */
 
494
                vals = ldap_get_values(ld, entry, buf);
 
495
 
 
496
                if (skip+1 > ldap_count_values(vals)) {
 
497
                        debug(RPT_DEBUG, "No such entry found.");
471
498
                        if (NULL != buf) {
472
499
                                free(buf);
473
 
                                buf=NULL;
 
500
                                buf = NULL;
474
501
                        }
475
502
                        ldap_value_free(vals);
476
503
                        /* DON'T enable the following
488
515
                if (vals && vals[skip]) {
489
516
                        if (NULL != buf) {
490
517
                                free(buf);
491
 
                                buf=NULL;
 
518
                                buf = NULL;
492
519
                        }
493
520
                        buf=strdup(vals[skip]);
494
 
                        debug( RPT_DEBUG, "Entry found. Value is: %s", buf);
495
 
                        ldap_value_free (vals);
496
 
                                                
497
 
                        k=(key*) malloc( sizeof( key ));
498
 
                        k->name = strdup( keyname );
499
 
                        k->value = strdup( buf );
500
 
                        k->next_key = NULL;
501
 
                        
 
521
                        debug(RPT_DEBUG, "Entry found. Value is: %s", buf);
 
522
                        ldap_value_free(vals);
 
523
 
 
524
                        k = (key *) malloc(sizeof(key));
 
525
                        if ( k != NULL) {
 
526
                                k->name = strdup(keyname);
 
527
                                k->value = strdup(buf);
 
528
                                k->next_key = NULL;
 
529
                        }       
 
530
 
502
531
                        if (NULL != buf) {
503
532
                                free(buf);
504
 
                                buf=NULL;
 
533
                                buf = NULL;
505
534
                        }
506
535
                        return k;
507
536
                } 
508
 
                report( RPT_ERR, "LDAP server encountered errors.");
509
 
                ldap_value_free (vals);
 
537
                report(RPT_ERR, "LDAP server encountered errors.");
 
538
                ldap_value_free(vals);
510
539
                if (NULL != buf) {
511
540
                        free(buf);
512
 
                        buf=NULL;
 
541
                        buf = NULL;
513
542
                }
514
543
                return NULL;
515
544
        }
516
545
#endif /* WITH_LDAP_SUPPORT */
517
546
 
518
 
        for( k=s->first_key; k; k=k->next_key ) {
 
547
        for (k = s->first_key; k != NULL; k = k->next_key) {
519
548
 
520
549
                /* Did we find the right key ?*/
521
 
                if( strcasecmp( k->name, keyname ) == 0 ) {
522
 
                        if( count == skip ) {
 
550
                if (strcasecmp(k->name, keyname) == 0) {
 
551
                        if (count == skip)
523
552
                                return k;
524
 
                        } else {
525
 
                                count ++;
526
 
                                last_key = k;
527
 
                        }
 
553
 
 
554
                        count++;
 
555
                        last_key = k;
528
556
                }
529
557
        }
530
 
        if( skip == -1 ) {
 
558
        if (skip == -1)
531
559
                return last_key;
 
560
 
 
561
        return NULL; /* not found*/
 
562
}
 
563
 
 
564
 
 
565
static key *add_key(section *s, const char *keyname, const char *value)
 
566
{
 
567
        if (s != NULL) {
 
568
                key *k;
 
569
                key **place = &(s->first_key);
 
570
 
 
571
                for (k = s->first_key; k != NULL; k = k->next_key)
 
572
                        place = &(k->next_key);
 
573
 
 
574
                *place = (key *) malloc(sizeof(key));
 
575
                if (*place != NULL) {
 
576
                        (*place)->name = strdup(keyname);
 
577
                        (*place)->value = strdup(value);
 
578
                        (*place)->next_key = NULL;
 
579
                }
 
580
 
 
581
                return(*place);
532
582
        }
533
 
        return NULL; /* not found*/
534
 
}
535
 
 
536
 
key * add_key( section * s, char * keyname, char * value )
537
 
{
538
 
        key * k;
539
 
 
540
 
        key ** place = &( s->first_key );
541
 
 
542
 
        for( k=s->first_key; k; k=k->next_key )
543
 
                place = &(k->next_key);
544
 
 
545
 
        *place = (key*) malloc( sizeof( key ));
546
 
        (*place)->name = strdup( keyname );
547
 
        (*place)->value = strdup( value );
548
 
        (*place)->next_key = NULL;
549
 
 
550
 
        return (*place);
551
 
}
552
 
 
553
 
char get_next_char_f(buffile * f) {
554
 
        char * buf = buffile_read(f, 1);
555
 
        char c = buf[0];
556
 
        free(buf);
557
 
        return c;
558
 
}
559
 
 
560
 
 
561
 
/* Parser states*/
562
 
#define ST_INITIAL 0
563
 
#define ST_IGNORE 1
564
 
#define ST_SECTIONNAME 2
565
 
#define ST_KEYNAME 3
566
 
#define ST_VALUE 10
567
 
#define ST_QUOTEDVALUE 11
568
 
#define ST_QUOTEDVALUE_ESCCHAR 12
569
 
#define ST_INVALID_SECTIONNAME 23
570
 
#define ST_INVALID_KEYNAME 24
571
 
#define ST_INVALID_VALUE 30
572
 
#define ST_INVALID_QUOTEDVALUE 31
573
 
#define ST_END 99
574
 
 
575
 
/* Limits*/
576
 
#define MAXSECTIONNAMELENGTH 40
577
 
#define MAXKEYNAMELENGTH 40
578
 
#define MAXVALUELENGTH 200
579
 
 
580
 
 
581
 
 
582
 
int process_config( section ** current_section, char (*get_next_char)(), char modify_section_allowed, char * source_descr, buffile * f)
583
 
{
584
 
        char state = ST_INITIAL;
 
583
        return NULL;
 
584
}
 
585
 
 
586
 
 
587
static char get_next_char_f(FILE *f)
 
588
{
 
589
        int c = fgetc(f);
 
590
 
 
591
        return((c == EOF) ? '\0' : c);
 
592
}
 
593
 
 
594
 
 
595
/* Parser states */
 
596
#define ST_INITIAL              0
 
597
#define ST_COMMENT              257
 
598
#define ST_SECTIONLABEL         258
 
599
#define ST_KEYNAME              259
 
600
#define ST_ASSIGNMENT           260
 
601
#define ST_VALUE                261
 
602
#define ST_QUOTEDVALUE          262
 
603
#define ST_SECTIONLABEL_DONE    263
 
604
#define ST_VALUE_DONE           264
 
605
#define ST_INVALID_SECTIONLABEL 265
 
606
#define ST_INVALID_KEYNAME      266
 
607
#define ST_INVALID_ASSIGNMENT   267
 
608
#define ST_INVALID_VALUE        268
 
609
#define ST_END                  999
 
610
 
 
611
/* Limits */
 
612
#define MAXSECTIONLABELLENGTH   40
 
613
#define MAXKEYNAMELENGTH        40
 
614
#define MAXVALUELENGTH          200
 
615
 
 
616
 
 
617
static int process_config(section **current_section, char(*get_next_char)(), const char *source_descr, FILE *f)
 
618
{
 
619
        int state = ST_INITIAL;
585
620
        char ch;
586
 
        char sectionname[MAXSECTIONNAMELENGTH+1];
 
621
        char sectionname[MAXSECTIONLABELLENGTH+1];
587
622
        int sectionname_pos = 0;
588
623
        char keyname[MAXKEYNAMELENGTH+1];
589
624
        int keyname_pos = 0;
590
625
        char value[MAXVALUELENGTH+1];
591
626
        int value_pos = 0;
592
 
        int quote = 0;
593
 
        key * k;
 
627
        int escape = 0;
 
628
        key *k;
594
629
        int line_nr = 1;
595
 
 
596
 
        while( state != ST_END ) {
597
 
 
598
 
                if (NULL != f) {
599
 
                        ch = get_next_char(f);
600
 
                }
601
 
                else {
602
 
                        ch = get_next_char();
603
 
                }
604
 
 
605
 
                /* Secretly keep count of the line numbers*/
606
 
                if( ch == '\n' ) {
607
 
                        line_nr ++;
608
 
                }
609
 
 
610
 
                switch( state ) {
 
630
        int error = 0;
 
631
 
 
632
        while (state != ST_END) {
 
633
 
 
634
                ch = (f != NULL)
 
635
                        ? get_next_char(f)
 
636
                        : get_next_char();
 
637
 
 
638
                /* Secretly keep count of the line numbers */
 
639
                if (ch == '\n')
 
640
                        line_nr++;
 
641
 
 
642
                switch (state) {
611
643
                  case ST_INITIAL:
612
 
                        switch( ch ) {
 
644
                        switch (ch) {
 
645
                          case '#':
 
646
                          case ';':
 
647
                                /* comment start */
 
648
                                state = ST_COMMENT;
 
649
                                /* fall through */
 
650
                          case '\0':
613
651
                          case '\n':
614
652
                          case '\r':
615
653
                          case '\t':
616
654
                          case ' ':
617
 
                                break;
618
 
                          case '#':
619
 
                          case ';':
620
 
                          case '=':
621
 
                          case ']':
622
 
                                /* It's a comment or an error*/
623
 
                                state = ST_IGNORE;
624
 
                                break;
 
655
                                /* ignore spaces */
 
656
                                break;
625
657
                          case '[':
626
 
                                /* It's a section name*/
627
 
                                state = ST_SECTIONNAME;
628
 
                                sectionname[0] = 0;
 
658
                                /* section name */
 
659
                                state = ST_SECTIONLABEL;
629
660
                                sectionname_pos = 0;
630
 
                                break;
631
 
                          case 0:
 
661
                                sectionname[sectionname_pos] = '\0';
632
662
                                break;
633
663
                          default:
634
 
                                /* It's a keyname*/
 
664
                                /* key word */
635
665
                                state = ST_KEYNAME;
636
 
                                keyname[0] = ch;
637
 
                                keyname[1] = 0;
638
 
                                keyname_pos = 1;
639
 
                        }
640
 
                        break;
641
 
                  case ST_IGNORE:
642
 
                        switch( ch ) {
643
 
                          case '\n':
644
 
                                state = ST_INITIAL;
645
 
                                break;
646
 
                        }
647
 
                        break;
648
 
                  case ST_SECTIONNAME:
649
 
                        switch( ch ) {
650
 
                          case '\n':
651
 
                                report( RPT_WARNING, "Section name incorrectly closed on line %d of %s: %s", line_nr, source_descr, sectionname );
652
 
                                state = ST_INITIAL;
653
 
                                break;
654
 
                          case '\r':
655
 
                          case '\t':
656
 
                          case ' ':
657
 
                          case '"':
658
 
                          case '[':
659
 
                                report( RPT_WARNING, "Section name contains invalid chars on line %d of %s: %s", line_nr, source_descr, sectionname );
660
 
                                state = ST_INVALID_SECTIONNAME;
 
666
                                keyname_pos = 0;
 
667
                                keyname[keyname_pos++] = ch;
 
668
                                keyname[keyname_pos] = '\0';
 
669
                        }
 
670
                        break;
 
671
                  case ST_SECTIONLABEL:
 
672
                        /* section label: "["{non-space chars}+"]" */
 
673
                        switch (ch) {
 
674
                          case '\0':
 
675
                          case '\n':
 
676
                                /* premature end of label */
 
677
                                report(RPT_WARNING, "Unterminated section label on line %d of %s: %s",
 
678
                                                line_nr, source_descr, sectionname);
 
679
                                error = 1;
 
680
                                state = ST_INITIAL;     /* alrady at the end, no resync required */     
661
681
                                break;
662
682
                          case ']':
663
 
                                if( !( *current_section=find_section( sectionname ))) {
664
 
                                        *current_section=add_section( sectionname );
 
683
                                /* label terminated: find/create section */
 
684
                                if (!(*current_section = find_section(sectionname))) {
 
685
                                        *current_section = add_section(sectionname);
665
686
                                }
666
 
                                state = ST_INITIAL;
667
 
                                break;
668
 
                          case 0:
669
 
                                report( RPT_WARNING, "Section name incorrectly closed on line %d of %s: %s", line_nr, source_descr, sectionname );
670
 
                                break;
 
687
                                state = ST_SECTIONLABEL_DONE;
 
688
                                break;
 
689
                        //  case '\r':
 
690
                        //  case '\t':
 
691
                        //  case ' ':
 
692
                        //      /* no spaces allowed in section labels WHY? */
 
693
                        //      report(RPT_WARNING, "Invalid character in section label on line %d of %s: %s",
 
694
                        //                      line_nr, source_descr, sectionname);
 
695
                        //      error = 1;
 
696
                        //      state = ST_INVALID_SECTIONLABEL;        /* resync required */
 
697
                        //      break;
671
698
                          default:
672
 
                                if( sectionname_pos<MAXSECTIONNAMELENGTH ) {
 
699
                                /* append char to section label */
 
700
                                if (sectionname_pos < MAXSECTIONLABELLENGTH) {
673
701
                                        sectionname[sectionname_pos++] = ch;
674
 
                                        sectionname[sectionname_pos] = 0;
675
 
                                } else {
676
 
                                        report( RPT_WARNING, "Section name too long on line %d of %s: %s", line_nr, source_descr, sectionname );
677
 
                                        state = ST_INVALID_SECTIONNAME;
 
702
                                        sectionname[sectionname_pos] = '\0';
 
703
                                        break;
678
704
                                }
679
 
                        }
680
 
                        break;
681
 
                  case ST_INVALID_SECTIONNAME:
682
 
                        switch( ch ) {
683
 
                          case '\n':
684
 
                          case ']':
685
 
                                state = ST_INITIAL;
686
 
                                break;
 
705
                                report(RPT_WARNING, "Section name too long on line %d of %s: %s",
 
706
                                                line_nr, source_descr, sectionname);
 
707
                                error = 1;
 
708
                                state = ST_INVALID_SECTIONLABEL;        /* resync required */
687
709
                        }
688
710
                        break;
689
711
                  case ST_KEYNAME:
690
 
                        switch( ch ) {
691
 
                          case 0:
692
 
                          case '\n':
 
712
                        /* key name: {non-space chars}+ */
 
713
                        switch (ch) {
693
714
                          case '\r':
694
715
                          case '\t':
695
716
                          case ' ':
696
 
                                report( RPT_WARNING, "Loose word found on line %d of %s: %s", line_nr, source_descr, keyname );
697
 
                                state = ST_INITIAL;
 
717
                                /* ignore trailing spaces */
 
718
                                if (keyname_pos != 0)
 
719
                                        state = ST_ASSIGNMENT;
698
720
                                break;
699
 
                          case '"':
700
 
                          case '[':
701
 
                          case ']':
702
 
                                report( RPT_WARNING, "Key name contains invalid characters on line %d of %s: %s", line_nr, source_descr, keyname );
703
 
                                state = ST_INVALID_KEYNAME;
 
721
                          case '\0':
 
722
                          case '\n':
 
723
                                /* premature end of line */
 
724
                                report(RPT_WARNING, "Loose word found on line %d of %s: %s",
 
725
                                                line_nr, source_descr, keyname);
 
726
                                error = 1;
 
727
                                state = ST_INITIAL;     /* already at the end; no resync required */
704
728
                                break;
705
729
                          case '=':
 
730
                                /* end of key reached, "=" found, now we need a value */
706
731
                                state = ST_VALUE;
707
 
                                value[0] = 0;
 
732
                                value[0] = '\0';
708
733
                                value_pos = 0;
709
734
                                break;
 
735
                        //  case '"':
 
736
                        //  case '[':
 
737
                        //  case ']':
 
738
                        //      /* character invalid in key names WHY ? */
 
739
                        //      report(RPT_WARNING, "Invalid character in key name on line %d of %s: %s",
 
740
                        //                      line_nr, source_descr, keyname);
 
741
                        //      error = 1;
 
742
                        //      state = ST_INVALID_KEYNAME;     /* resync required */
 
743
                        //      break;
710
744
                          default:
711
 
                                if( keyname_pos>=MAXKEYNAMELENGTH ) {
712
 
                                        report( RPT_WARNING, "Key name too long on line %d of %s: %s", line_nr, source_descr, keyname );
713
 
                                        state = ST_INVALID_KEYNAME;
714
 
                                } else {
 
745
                                /* append char to key name */
 
746
                                if (keyname_pos < MAXKEYNAMELENGTH) {
715
747
                                        keyname[keyname_pos++] = ch;
716
 
                                        keyname[keyname_pos] = 0;
717
 
                                }
 
748
                                        keyname[keyname_pos] = '\0';
 
749
                                        break;
 
750
                                }       
 
751
                                report(RPT_WARNING, "Key name too long on line %d of %s: %s",
 
752
                                                line_nr, source_descr, keyname);
 
753
                                error = 1;
 
754
                                state = ST_INVALID_KEYNAME;     /* resync required */
718
755
                        }
719
756
                        break;
720
 
                  case ST_INVALID_KEYNAME:
721
 
                        switch( ch ) {
722
 
                          case '\n':
723
 
                                state = ST_INITIAL;
724
 
                          /*case ' ':*/
 
757
                  case ST_ASSIGNMENT:
 
758
                        /* assignement: "=" */
 
759
                        switch (ch) {
 
760
                          case '\t':
 
761
                          case ' ':
 
762
                                /* ignore leading spaces */
 
763
                                break;
 
764
                          case '=':
 
765
                                /* "=" found, now we need a value */
 
766
                                state = ST_VALUE;
 
767
                                value[0] = '\0';
 
768
                                value_pos = 0;
 
769
                                break;
 
770
                          default:
 
771
                                report(RPT_WARNING, "Assigment expected on line %d of %s: %s",
 
772
                                                line_nr, source_descr, keyname);
 
773
                                error = 1;
 
774
                                state = ST_INVALID_ASSIGNMENT;          
725
775
                        }
726
776
                        break;
727
777
                  case ST_VALUE:
728
 
                        switch( ch ) {
 
778
                        /* value: {non-space char}+ | "\""{any potentially-quoted char}+"\"" */
 
779
                        switch (ch) {
 
780
                          case '#':
 
781
                          case ';':
 
782
                                /* allow comment if we already had a value */
 
783
                                /* WHY ONLY THEN ? 'xx=' can be seen as equivalent to 'xx=""' */
 
784
                                if (value_pos > 0) {
 
785
                                        state = ST_COMMENT;
 
786
                                        break;
 
787
                                }
 
788
                                /* fall through */
729
789
                          case '[':
730
790
                          case ']':
731
 
                          case '#':
732
 
                          case ';':
733
791
                          case '=':
734
 
                                report( RPT_WARNING, "Value contains invalid characters on line %d of %s, at key: %s", line_nr, source_descr, keyname );
 
792
                                /* illegal characters WHY? */
 
793
                                report(RPT_WARNING, "Invalid character '%c' in value on line %d of %s, at key: %s",
 
794
                                                ch, line_nr, source_descr, keyname);
 
795
                                error = 1;
735
796
                                state = ST_INVALID_VALUE;
736
797
                                break;
737
 
                          case '"':
738
 
                                state = ST_QUOTEDVALUE;
739
 
                                break;
740
 
                          case 0:
 
798
                          case '\t':
 
799
                          case ' ':
 
800
                                /* ignore leading spaces */
 
801
                                if (value_pos == 0)
 
802
                                        break;
 
803
                                /* fall through */      
 
804
                          case '\0':
741
805
                          case '\n':
742
806
                          case '\r':
743
 
                          case '\t':
744
 
                          case ' ':
745
 
                                /* Value complete !*/
746
 
                                if( ! *current_section ) {
747
 
                                        report( RPT_WARNING, "Data before any section on line %d of %s with key: %s", line_nr, source_descr, keyname );
 
807
                                /* value complete */
 
808
                                if (!*current_section) {
 
809
                                        report(RPT_WARNING, "Data outside sections on line %d of %s with key: %s",
 
810
                                                        line_nr, source_descr, keyname);
 
811
                                        error = 1;
748
812
                                }
749
813
                                else {
750
814
                                        /* Store the value*/
751
 
                                        k = add_key( *current_section, keyname, value );
 
815
                                        k = add_key(*current_section, keyname, value);
752
816
                                }
753
817
                                /* And be ready for next thing...*/
754
 
                                state = ST_INITIAL;
 
818
                                state = ((ch == ' ') || (ch == '\t')) ? ST_VALUE_DONE : ST_INITIAL;
 
819
                                break;
 
820
                          case '"':
 
821
                                /* quoted string */ 
 
822
                                state = ST_QUOTEDVALUE;
755
823
                                break;
756
824
                          default:
757
 
                                if( value_pos<MAXVALUELENGTH ) {
 
825
                                /* append char to value */
 
826
                                if (value_pos < MAXVALUELENGTH) {
758
827
                                        value[value_pos++] = ch;
759
 
                                        value[value_pos] = 0;
760
 
                                } else {
761
 
                                        report( RPT_WARNING, "Value key is too long on line %d of %s, at key: %s", line_nr, source_descr, keyname );
762
 
                                        state = ST_INVALID_KEYNAME;
 
828
                                        value[value_pos] = '\0';
 
829
                                        break;
763
830
                                }
764
 
                        }
765
 
                        break;
766
 
                  case ST_INVALID_VALUE:
767
 
                        switch( ch ) {
768
 
                          case '\n':
769
 
                                state = ST_INITIAL;
770
 
                                break;
771
 
                          case '"':
772
 
                                state = ST_INVALID_QUOTEDVALUE;
 
831
                                report(RPT_WARNING, "Value too long on line %d of %s, at key: %s",
 
832
                                                line_nr, source_descr, keyname);
 
833
                                error = 1;
 
834
                                state = ST_INVALID_VALUE;
773
835
                        }
774
836
                        break;
775
837
                  case ST_QUOTEDVALUE:
776
 
                        switch( ch ) {
777
 
                          case 0:
 
838
                        /* a quoted part of a string */
 
839
                        switch (ch) {
 
840
                          case '\0':
778
841
                          case '\n':
779
 
                                report( RPT_WARNING, "String is incorrectly terminated on line %d of %s: %s", line_nr, source_descr, keyname );
 
842
                                report(RPT_WARNING, "Premature end of quoted string on line %d of %s: %s",
 
843
                                                line_nr, source_descr, keyname);
 
844
                                error = 1;
780
845
                                state = ST_INITIAL;
781
846
                                break;
782
847
                          case '\\':
783
 
                                if( !quote ) {
784
 
                                        quote = 1;
 
848
                                if (!escape) {
 
849
                                        escape = 1;
785
850
                                        break;
786
851
                                }
 
852
                                /* fall though */
787
853
                          case '"':
788
 
                                if( !quote ) {
 
854
                                if (!escape) {
789
855
                                        state = ST_VALUE;
790
856
                                        break;
791
857
                                }
 
858
                                /* fall though */
792
859
                          default:
793
 
                                if( quote ) {
794
 
                                        switch( ch ) {
 
860
                                if (escape) {
 
861
                                        switch (ch) {
 
862
                                          case 'a': ch = '\a'; break;
 
863
                                          case 'b': ch = '\b'; break;
 
864
                                          case 'f': ch = '\f'; break;
795
865
                                          case 'n': ch = '\n'; break;
796
866
                                          case 'r': ch = '\r'; break;
797
867
                                          case 't': ch = '\t'; break;
798
 
                                          /* default: litteral*/
 
868
                                          case 'v': ch = '\v'; break;
 
869
                                          /* default: literal char  (i.e. ignore '\') */
799
870
                                        }
800
 
                                        quote = 0;
 
871
                                        escape = 0;
801
872
                                }
802
873
                                value[value_pos++] = ch;
803
 
                                value[value_pos] = 0;
 
874
                                value[value_pos] = '\0';
804
875
                        }
805
 
                        break;
806
 
                  case ST_INVALID_QUOTEDVALUE:
807
 
                        switch( ch ) {
 
876
                        break;
 
877
                  case ST_SECTIONLABEL_DONE:
 
878
                  case ST_VALUE_DONE:
 
879
                        switch (ch) {
 
880
                          case ';':
 
881
                          case '#':
 
882
                                state = ST_COMMENT;
 
883
                                break;
 
884
                          case '\0':
808
885
                          case '\n':
809
 
                                state = ST_INITIAL;
810
 
                                break;
811
 
                          case '"':
 
886
                                state = ST_INITIAL;
 
887
                                break;
 
888
                          case '\t':
 
889
                          case ' ':
 
890
                                break;
 
891
                          default:
 
892
                                /* illegal characters */
 
893
                                report(RPT_WARNING, "Invalid character '%c' on line %d of %s",
 
894
                                                ch, line_nr, source_descr);
 
895
                                error = 1;
812
896
                                state = ST_INVALID_VALUE;
813
 
                        }
814
 
                        break;
 
897
                         }      
 
898
                  case ST_INVALID_SECTIONLABEL:
 
899
                        /* invalid section label: resync up to end of label/next line */
 
900
                        if (ch == ']')
 
901
                                state = ST_INITIAL;
 
902
                        /* fall through */
 
903
                  case ST_INVALID_ASSIGNMENT:
 
904
                  case ST_INVALID_KEYNAME:
 
905
                  case ST_INVALID_VALUE:
 
906
                  case ST_COMMENT:
 
907
                        /* comment or error: ignore anything up to the next line */
 
908
                        if (ch == '\n')
 
909
                                state = ST_INITIAL;
815
910
                }
816
 
                if( ch == 0 ) {
 
911
                if (ch == '\0') {
 
912
                        if ((!error) && (state != ST_INITIAL) && (state != ST_COMMENT) &&
 
913
                            (state != ST_SECTIONLABEL_DONE) && (state != ST_VALUE_DONE)) {
 
914
                                report(RPT_WARNING, "Premature end of configuration on line %d of %s: %d",
 
915
                                                line_nr, source_descr, state);
 
916
 
 
917
                                error = 1;
 
918
                        }                       
817
919
                        state = ST_END;
818
920
                }
 
921
 
819
922
        }
820
 
        return 0;
821
 
}
822
 
 
 
923
        return (error) ? -1 : 0;
 
924
}
 
925
 
 
926
 
 
927
#if CONFIGFILE_DEBUGTEST
 
928
void config_dump(void)
 
929
{
 
930
section *s;
 
931
 
 
932
        for (s = first_section; s != NULL; s = s->next_section) {
 
933
                key *k;
 
934
 
 
935
                fprintf(stderr, "[%s]\n", s->name);
 
936
 
 
937
                for (k = s->first_key; k != NULL; k = k->next_key)
 
938
                        fprintf(stderr, "%s = \"%s\"\n", k->name, k->value);
 
939
 
 
940
                fprintf(stderr, "\n");
 
941
        }       
 
942
}
 
943
 
 
944
 
 
945
int main(int argc, char *argv[])
 
946
{
 
947
        if (argc > 0)
 
948
                config_read_file(argv[1]);
 
949
        config_dump();
 
950
}
 
951
#endif