source: MondoRescue/trunk/mondo/src/lib/mr_conf.c@ 852

Last change on this file since 852 was 852, checked in by Bruno Cornec, 18 years ago

License is GPLv2 for new files introduced

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