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

Last change on this file since 835 was 835, checked in by Bruno Cornec, 18 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.