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

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