source: MondoRescue/branches/stable/mondo/src/lib/mr_conf.c@ 1227

Last change on this file since 1227 was 1227, checked in by Bruno Cornec, 17 years ago

Removal of MRCONF_ALLOC_FAILED as mr_malloc is always returning a pointer or exiting in case of pb.

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