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

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

Includes of common are not accessible to lib

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