source: trunk/mondo/src/lib/mr_conf.c @ 835

Last change on this file since 835 was 835, checked in by bruno, 13 years ago

Fic compilation warnings and errors (trying o get a building trunk again)

File size: 10.6 KB
Line 
1/* mr_conf.c
2 *
3 * $Id$
4 *
5 * Based on the work done by Anton (c)2002-2004 Anton Kulchitsky  mailto:anton@kulchitsky.org
6 * Code (c)2006 Bruno Cornec <bruno@mondorescue.org>
7 *   
8 *     Main file of mr_conf : a very small and simple
9 *     library for configuration file reading
10 *
11 *  This library is free software; you can redistribute it and/or
12 *  modify it under the terms of the GNU Lesser General Public License
13 *  as published by the Free Software Foundation; either version 2.1
14 *  of the License, or (at your option) any later version.
15 *
16 *  This library is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 *  Lesser General Public License for more details.
20 *
21 *  You should have received a copy of the GNU Lesser General Public
22 *  License along with this library; if not, write to the Free
23 *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 *  02111-1307 USA
25 */
26
27
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32#include "my-stuff.h"
33#include "libmondo-tools.h"
34
35/* error flags */
36#define MRCONF_NO_ERROR             0x0
37#define MRCONF_BAD_FILE             0x1
38#define MRCONF_ALLOC_FAILED         0x2
39#define MRCONF_READING_FAILED       0x3
40#define MRCONF_NO_GROUP_START       0x4
41#define MRCONF_NO_GROUP_END         0x5
42#define MRCONF_FIELD_NOT_FOUND      0x6
43#define MRCONF_FIELD_NO_VALUE       0x7
44#define MRCONF_TOO_LONG_STRING      0x8
45#define MRCONF_CLOSE_BUT_NOT_OPEN   0x9
46#define MRCONF_OPEN_OPENED          0xA
47#define MRCONF_CALL_BUT_NOT_OPEN    0xB
48
49/*setting flags*/
50#define MRCONF_FLAG_VERBOSE         0x1
51
52/*All strings of the library are here*/
53#define MRCONF_STR_ERROR          _("MRCONF: Error:")
54#define MRCONF_STR_WARNING        _("MRCONF: Warning:")
55
56#define MRCONF_STR_BAD_FILE       _("cannot open the file: ")
57#define MRCONF_STR_ALLOC_FAILED   _("cannot allocate the memory")
58#define MRCONF_STR_READING_FAILED _("cannot read file into buffer")
59#define MRCONF_STR_DEFAULT_ERROR  _("default")
60#define MRCONF_STR_FIELD_NOT_FOUND   _("the field is not found, field:")
61#define MRCONF_STR_FIELD_NO_VALUE   _("the field :")
62#define MRCONF_STR_OPEN_OPENED _("attempt to open mr_conf, but it is opened: aborted")
63#define MRCONF_STR_HALT _("MRCONF: Error occured: immidiate halt")
64
65/*warnings*/
66#define MRCONF_STR_SET_TO_ZERO    _("variable will be set to 0")
67#define MRCONF_STR_IGNORE    _("has no value, ignoring it")
68#define MRCONF_STR_CLOSE_BUT_NOT_OPEN _("attempt to close mr_conf but it has not been opened yet")
69#define MRCONF_STR_CALL_BUT_NOT_OPEN _("attempt to use mr_conf when it has not been opened yet")
70
71/*Flags of internal state*/
72#define MRCONF_INTFLAG_OPEN 0x1 /*set if memory allocated */
73
74/* Character for comments */
75#define MRCONF_COMM_CHAR '#'
76
77/*"private" members declarations*/
78static size_t mr_conf_filesize(const char *name);
79static void mr_conf_error_msg(int error_code, const char *add_line);
80static void mr_conf_remove_comments();
81static int mr_conf_check_int_flag(const int flag);
82static void mr_conf_set_int_flag(const int flag);
83static void mr_conf_drop_int_flag(const int flag);
84
85/*global "private" variables*/
86static char *buffer = NULL;     /*buffer for configuration file */
87static int internal_flags = 0;  /*state of the module */
88static FILE *CONF = NULL;       /* Configuration file FD */
89
90/*if output all error and warnin messages*/
91static int mr_conf_flags = MRCONF_FLAG_VERBOSE;
92
93/*
94 * Format of the configuration file is as follows:
95 *
96 * attribute1 = int_value
97 * attribute2 = float_value
98 * attribute3 = string_value
99 */
100
101
102/*open and read file: each call must be coupled with mr_conf_close
103  function: return 0 if success*/
104int mr_conf_open(const char *filename) {
105    size_t length;              /*length of the buffer/file */
106
107    /* check if mr_conf is already opened? */
108    if (mr_conf_check_int_flag(MRCONF_INTFLAG_OPEN)) {
109        mr_conf_error_msg(MRCONF_OPEN_OPENED, NULL);
110        return MRCONF_OPEN_OPENED;
111    }
112
113    length = mr_conf_filesize(filename);
114    CONF = fopen(filename, "r");
115
116    /*if file is empty or not exist => error */
117    if (length == 0) {
118        mr_conf_error_msg(MRCONF_BAD_FILE, filename);
119        return (MRCONF_BAD_FILE);
120    }
121
122    /*creating and reading buffer for file content */
123
124    /*allocate memory for the buffers */
125    buffer = (char *) malloc(sizeof(char) * (length + 1));
126
127    if (buffer == NULL) {
128        mr_conf_error_msg(MRCONF_ALLOC_FAILED, "");
129        return (MRCONF_ALLOC_FAILED);
130    }
131
132    /*set flag that module is in "open" state */
133    mr_conf_set_int_flag(MRCONF_INTFLAG_OPEN);
134
135    /*reading file in buffer (skip all 0 characters) */
136
137    (void) fread(buffer, sizeof(char), length, CONF);
138    buffer[length] = (char) 0;  /*finalize the string */
139
140    if (ferror(CONF)) {
141        mr_conf_error_msg(MRCONF_READING_FAILED, "");
142        return (MRCONF_READING_FAILED);
143    }
144
145    /* finally we have to remove all comment lines */
146    mr_conf_remove_comments();
147
148    return MRCONF_NO_ERROR;
149}
150
151/*release all memory and prepare to the next possiable config file*/
152void mr_conf_close() {
153    /* if not opened => error */
154    if (!mr_conf_check_int_flag(MRCONF_INTFLAG_OPEN)) {
155        mr_conf_error_msg(MRCONF_CLOSE_BUT_NOT_OPEN, NULL);
156    }
157    paranoid_free(buffer);
158    fclose(CONF);
159
160    /*set flag that module is in "close" state */
161    mr_conf_drop_int_flag(MRCONF_INTFLAG_OPEN);
162}
163
164/*read field value after string str in the current file*/
165static char *mr_conf_read(const char *field_name) {
166    char *p = NULL;             /*pointer to the field */
167
168    /* check if mr_conf is not yet opened? */
169    if (!mr_conf_check_int_flag(MRCONF_INTFLAG_OPEN)) {
170        mr_conf_error_msg(MRCONF_CALL_BUT_NOT_OPEN, NULL);
171        return NULL;
172    }
173
174    /*read the number */
175    p = strstr(buffer, field_name);
176    if (p == NULL) {
177        mr_conf_error_msg(MRCONF_FIELD_NOT_FOUND, field_name);
178        return NULL;
179    } else {
180        p += strlen(field_name);
181        while ((*p != '\n') && (*p != '\0') && (*p != '=')) {
182                p++;
183        }
184        if (*p != '=') {
185            mr_conf_error_msg(MRCONF_FIELD_NO_VALUE, field_name);
186            return NULL;
187        } else {
188            /* points after the = sign */
189            p++;
190        }
191    }
192    /* skip initial spaces and tabs after = */
193    while ((*p == ' ') || (*p == '\t')) {
194            p++;
195    }
196
197    return p;
198}
199
200/*read integer number after string str in the current file*/
201int mr_conf_iread(const char *field_name) {
202    char *p = NULL;             /*pointer to the field */
203    int ret = 0;                /*return value */
204
205    p = mr_conf_read(field_name);
206    if (p != NULL) {
207        ret = atoi(p);
208        }
209    return ret;
210}
211
212/*read float/double number after string str in the current file*/
213double mr_conf_fread(const char *field_name) {
214    char *p = NULL;             /*pointer to the field */
215    double ret = 0.0;               /*return value */
216
217    p = mr_conf_read(field_name);
218    if (p != NULL) {
219        ret = atof(p);
220    }
221    return ret;
222}
223
224/*
225  reads string outstr after string str in the current file (between
226  "..."), not more than maxlength simbols: cannot check if outstr has
227  enough length! It must be at least maxlength+1 ! Returns number of
228  read chars
229*/
230char *mr_conf_sread(const char *field_name) {
231    char *p = NULL;             /*pointer to the field */
232    char *q = NULL;             /*pointer to the field */
233    char *r = NULL;             /*pointer to the field */
234    char *ret = NULL;           /*return value */
235    int size = 0;               /*size of returned string */
236    int i = 0;
237
238    ret = NULL;
239
240    p = mr_conf_read(field_name);
241    if (p == NULL) {
242        return(p);
243    }
244    asprintf(&q, p);
245
246    /* trunk at first \n */
247    r = index(q,'\n');
248
249    size = r-q+1;
250    /*copy filtered data to the buffer */
251    ret = (char *) malloc(sizeof(char) * (size));
252    if (ret == NULL) {
253        mr_conf_error_msg(MRCONF_ALLOC_FAILED, "");
254        return (NULL);
255    }
256    while (i < size - 1) {
257        ret[i] = *p;
258        i++;
259        p++;
260    }
261
262    ret[i] = (char) 0;      /*and set its length */
263    paranoid_free(q);
264
265    return ret;
266}
267
268/*removes all comments from the buffer*/
269static void mr_conf_remove_comments() {
270    char *tmp_buf;              /*temporary buffer without comments */
271    size_t length               /*initial length */ ;
272    size_t i;                   /*iterator */
273    size_t k;                   /*conditioned iterator for tmp_buffer */
274
275    length = strlen(buffer);
276
277    /*sizing the new chain */
278    k = 0;
279    i = 0;
280    while (i < length) {
281        if (buffer[i] != MRCONF_COMM_CHAR) {
282            k++;
283            i++;
284        } else {
285            while ((buffer[i] != '\n') && (buffer[i] != (char) 0)) {
286                i++;
287            }
288        }
289    }
290    /* k is new buffer length now */
291    tmp_buf = (char *) malloc(sizeof(char) * (k + 1));
292    if (tmp_buf == NULL) {
293        mr_conf_error_msg(MRCONF_ALLOC_FAILED, "");
294        return;
295    }
296
297    k = 0;
298    i = 0;
299    while (i < length) {
300        if (buffer[i] != MRCONF_COMM_CHAR) {
301            tmp_buf[k++] = buffer[i++];
302        } else {
303            while ((buffer[i] != '\n') && (buffer[i] != (char) 0)) {
304                i++;
305            }
306        }
307    }
308    tmp_buf[k] = (char) 0;      /*and set its length */
309
310    paranoid_free(buffer);
311    /*copy filtered data to the buffer */
312    buffer = tmp_buf;
313}
314
315static int mr_conf_check_int_flag(const int flag) {
316    return (flag & internal_flags);
317}
318
319static void mr_conf_set_int_flag(const int flag) {
320    internal_flags = flag | internal_flags;
321}
322
323static void mr_conf_drop_int_flag(const int flag) {
324    internal_flags = (~flag) & internal_flags;
325}
326
327
328/*local function to define size of a file. Return 0 for mistake*/
329static size_t mr_conf_filesize(const char *name) {
330    FILE *F = fopen(name, "r"); /*file to open */
331    size_t length;              /*number to return */
332
333    if (F == NULL) {
334        return 0;
335    }
336
337    fseek(F, 0, SEEK_END);      /*set position to the end of file */
338    length = ftell(F);          /*define number of position=> this is its
339                                   length */
340    fclose(F);
341
342    return length;
343}
344
345/*output error message*/
346static void mr_conf_error_msg(int error_code, const char *add_line) {
347    if ((mr_conf_flags & MRCONF_FLAG_VERBOSE)) {    /*if verbose mode */
348        switch (error_code) {
349        case MRCONF_BAD_FILE:
350            log_msg(4, "%s %s %s\n", MRCONF_STR_ERROR, MRCONF_STR_BAD_FILE,
351                   add_line);
352            break;
353
354        case MRCONF_ALLOC_FAILED:
355            log_msg(4, "%s %s\n", MRCONF_STR_ERROR, MRCONF_STR_ALLOC_FAILED);
356            break;
357
358        case MRCONF_READING_FAILED:
359            log_msg(4, "%s %s\n", MRCONF_STR_ERROR, MRCONF_STR_READING_FAILED);
360            break;
361
362        case MRCONF_FIELD_NOT_FOUND:
363            log_msg(4, "%s %s \"%s\"\n", MRCONF_STR_ERROR,
364                   MRCONF_STR_FIELD_NOT_FOUND, add_line);
365            log_msg(4, "%s %s\n", MRCONF_STR_WARNING, MRCONF_STR_SET_TO_ZERO);
366            break;
367
368        case MRCONF_FIELD_NO_VALUE:
369            log_msg(4, "%s %s \"%s\"\n", MRCONF_STR_ERROR,
370                   MRCONF_STR_FIELD_NO_VALUE, add_line);
371            log_msg(4, "%s %s\n", MRCONF_STR_WARNING, MRCONF_STR_IGNORE);
372            break;
373
374        case MRCONF_CLOSE_BUT_NOT_OPEN:
375            log_msg(4, "%s %s\n", MRCONF_STR_WARNING,
376                   MRCONF_STR_CLOSE_BUT_NOT_OPEN);
377            break;
378
379        case MRCONF_CALL_BUT_NOT_OPEN:
380            log_msg(4, "%s %s\n", MRCONF_STR_WARNING,
381                   MRCONF_STR_CALL_BUT_NOT_OPEN);
382            break;
383
384        case MRCONF_OPEN_OPENED:
385            log_msg(4, "%s %s\n", MRCONF_STR_ERROR, MRCONF_STR_OPEN_OPENED);
386            break;
387
388        default:
389            log_msg(4, "%s %s\n", MRCONF_STR_ERROR, MRCONF_STR_DEFAULT_ERROR);
390            break;
391        }
392    }
393}
Note: See TracBrowser for help on using the repository browser.