source: MondoRescue/trunk/mondo/mondo/lib/mr_conf.c@ 768

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

mktest generates again good results with the new split of libraries.

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