source: MondoRescue/branches/2.2.10/mondo/src/lib/mr_conf.c@ 2291

Last change on this file since 2291 was 2291, checked in by Bruno Cornec, 15 years ago
  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string

(report bug fix done originaly in 2.2.9)

  • Property svn:eol-style set to native
File size: 12.0 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
[1264]19#include "mr_types.h"
[1054]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
[1545]37#define MRCONF_STRING_ENDQUOTE 0xD
[1054]38
39/*setting flags*/
40#define MRCONF_FLAG_VERBOSE 0x1
41
42/*All strings of the library are here*/
43#define MRCONF_STR_ERROR _("MRCONF: Error:")
44#define MRCONF_STR_WARNING _("MRCONF: Warning:")
45
46#define MRCONF_STR_BAD_FILE _("cannot open the file: ")
47#define MRCONF_STR_ALLOC_FAILED _("cannot allocate the memory")
48#define MRCONF_STR_READING_FAILED _("cannot read file into buffer")
49#define MRCONF_STR_DEFAULT_ERROR _("default")
50#define MRCONF_STR_FIELD_NOT_FOUND _("the field is not found, field:")
51#define MRCONF_STR_FIELD_NO_VALUE _("the field :")
52#define MRCONF_STR_OPEN_OPENED _("attempt to open mr_conf, but it is opened: aborted")
53#define MRCONF_STR_HALT _("MRCONF: Error occured: immidiate halt")
54
55/*warnings*/
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")
[1427]60#define MRCONF_STR_STRING_ENDQUOTE _("a string is not finished by a quote")
[1054]61
62/*Flags of internal state*/
63#define MRCONF_INTFLAG_OPEN 0x1 /*set if memory allocated */
64
65/* Character for comments */
66#define MRCONF_COMM_CHAR '#'
67
68/*"private" members declarations*/
69static size_t mr_conf_filesize(const char *name);
[1422]70#define mr_conf_error_msg(x, y) {mr_conf_error_msg_int(x, y, __LINE__,__FILE__);}
71static void mr_conf_error_msg_int(int error_code, const char *add_line, int line, const char *file);
[1064]72static void mr_conf_remove_comments(void);
[1054]73static int mr_conf_check_int_flag(const int flag);
74static void mr_conf_set_int_flag(const int flag);
75static void mr_conf_drop_int_flag(const int flag);
76
77/*global "private" variables*/
78static char *buffer = NULL; /*buffer for configuration file */
79static int internal_flags = 0; /*state of the module */
80static FILE *CONF = NULL; /* Configuration file FD */
[1571]81static char *mr_conf_filename = NULL; /* Configuration filename */
[1054]82
83/*if output all error and warning messages*/
84static int mr_conf_flags = MRCONF_FLAG_VERBOSE;
85
86/*
87 * Format of the configuration file is as follows:
88 *
89 * attribute1 = int_value
90 * attribute2 = float_value
91 * attribute3 = string_value
92 */
93
94
95/*open and read file: each call must be coupled with mr_conf_close
96 function: return 0 if success*/
97int mr_conf_open(const char *filename) {
98 size_t length; /*length of the buffer/file */
99 size_t res = 0;
100
101 /* check if mr_conf is already opened? */
102 if (mr_conf_check_int_flag(MRCONF_INTFLAG_OPEN)) {
103 mr_conf_error_msg(MRCONF_OPEN_OPENED, NULL);
104 return MRCONF_OPEN_OPENED;
105 }
106
107 length = mr_conf_filesize(filename);
108 CONF = fopen(filename, "r");
109
[2291]110 mr_asprintf(&mr_conf_filename, "%s", filename);
[1571]111
[1054]112 /*if file is empty or not exist => error */
113 if (length == 0) {
114 mr_conf_error_msg(MRCONF_BAD_FILE, filename);
115 return (MRCONF_BAD_FILE);
116 }
117
118 /*creating and reading buffer for file content */
119
120 /*allocate memory for the buffers */
121 buffer = (char *) mr_malloc(sizeof(char) * (length + 1));
122
123 /*set flag that module is in "open" state */
124 mr_conf_set_int_flag(MRCONF_INTFLAG_OPEN);
125
126 /*reading file in buffer (skip all 0 characters) */
127
128 res = fread(buffer, sizeof(char), length, CONF);
129 buffer[length] = (char) 0; /*finalize the string */
130
131 if (ferror(CONF)) {
132 mr_conf_error_msg(MRCONF_READING_FAILED, "");
133 return (MRCONF_READING_FAILED);
134 }
135
136 /* finally we have to remove all comment lines */
137 mr_conf_remove_comments();
138
139 return MRCONF_NO_ERROR;
140}
141
142/*release all memory and prepare to the next possiable config file*/
[1064]143void mr_conf_close(void) {
[1054]144 /* if not opened => error */
145 if (!mr_conf_check_int_flag(MRCONF_INTFLAG_OPEN)) {
146 mr_conf_error_msg(MRCONF_CLOSE_BUT_NOT_OPEN, NULL);
147 }
148 mr_free(buffer);
149 fclose(CONF);
150
[1571]151 mr_free(mr_conf_filename);
152
[1054]153 /*set flag that module is in "close" state */
154 mr_conf_drop_int_flag(MRCONF_INTFLAG_OPEN);
155}
156
157/*read field value after string str in the current file*/
158static char *mr_conf_read(const char *field_name) {
159 char *p = NULL; /*pointer to the field */
160
161 /* check if mr_conf is not yet opened? */
162 if (!mr_conf_check_int_flag(MRCONF_INTFLAG_OPEN)) {
163 mr_conf_error_msg(MRCONF_CALL_BUT_NOT_OPEN, NULL);
164 return NULL;
165 }
166
167 /*read the number */
168 p = strstr(buffer, field_name);
169 if (p == NULL) {
170 mr_conf_error_msg(MRCONF_FIELD_NOT_FOUND, field_name);
171 return NULL;
172 } else {
173 p += strlen(field_name);
174 while ((*p != '\n') && (*p != '\0') && (*p != '=')) {
175 p++;
176 }
177 if (*p != '=') {
178 mr_conf_error_msg(MRCONF_FIELD_NO_VALUE, field_name);
179 return NULL;
180 } else {
181 /* points after the = sign */
182 p++;
183 }
184 }
185 /* skip initial spaces and tabs after = */
186 while ((*p == ' ') || (*p == '\t')) {
187 p++;
188 }
189
190 return p;
191}
192
193/*read integer number after string str in the current file*/
[1594]194char *mr_conf_iread(const char *field_name) {
[1054]195 char *p = NULL; /*pointer to the field */
[1594]196 char *p1 = NULL; /*return field */
[1054]197
198 p = mr_conf_read(field_name);
199 if (p != NULL) {
[1594]200 mr_asprintf(&p1, "%d", p);
[1054]201 }
[1594]202 return p1;
[1054]203}
204
205/*read float/double number after string str in the current file*/
[1594]206char *mr_conf_fread(const char *field_name) {
[1054]207 char *p = NULL; /*pointer to the field */
[1594]208 char *p1 = NULL; /*return field */
[1054]209
210 p = mr_conf_read(field_name);
211 if (p != NULL) {
[1594]212 mr_asprintf(&p1, "%f", p);
[1054]213 }
[1594]214 return p1;
[1054]215}
216
[1256]217
[1054]218/*
219*/
220char *mr_conf_sread(const char *field_name) {
221 char *p = NULL; /*pointer to the field */
222 char *q = NULL; /*pointer to the field */
223 char *r = NULL; /*pointer to the field */
224 char *ret = NULL; /*return value */
225 int size = 0; /*size of returned string */
226 int i = 0;
227
228 ret = NULL;
229
230 p = mr_conf_read(field_name);
231 if (p == NULL) {
232 return(p);
233 }
[2291]234 mr_asprintf(&q, "%s", p);
[1054]235
236 if (*p != '"') {
[1559]237 mr_conf_error_msg(MRCONF_STRING_QUOTE, field_name);
[1054]238 return (NULL);
239 }
240 p++;
241
242 /* trunk at first \n */
243 r = index(q,'\n');
244 r--;
245 if (*r != '"') {
[1559]246 mr_conf_error_msg(MRCONF_STRING_QUOTE, field_name);
[1054]247 return (NULL);
248 }
249 r--;
250
251 size = r-q+1;
252 /*copy filtered data to the buffer */
253 ret = (char *) mr_malloc(sizeof(char) * (size));
254 while (i < size - 1) {
255 ret[i] = *p;
256 i++;
257 p++;
258 }
259
260 ret[i] = (char) 0; /* and set its length */
261 mr_free(q);
262
263 return ret;
264}
265
[1256]266/*read boolean after string str in the current file*/
[1594]267char *mr_conf_bread(const char *field_name) {
[1256]268 char *p = NULL; /*pointer to the field */
[1594]269 char *p1 = NULL; /*pointer to the field */
[1256]270
[1594]271 p = mr_conf_read(field_name);
[1256]272 if (p != NULL) {
273 /* match if yes/true/1 */
274 if ((strncasecmp(p, "y" , (size_t)1) == 0) ||
275 (strncasecmp(p, "t" , (size_t)1) == 0) ||
276 (strncasecmp(p, "1" , (size_t)1) == 0)) {
[1594]277 mr_asprintf(&p1, "%d", TRUE);
278 } else {
279 mr_asprintf(&p1, "%d", FALSE);
[1256]280 }
281 }
[1594]282 return p1;
[1256]283}
284
[1594]285/* Convert a string with decimal value of TRUE/FALSE in boolean */
286bool mr_atob(const char *str) {
287 bool ret = FALSE;
288 char *p = NULL;
289
290 mr_asprintf(&p, "%d", FALSE);
291 if (strcmp(str,p) != 0) {
292 ret = TRUE;
293 }
294 mr_free(p);
295 return(ret);
296}
297
[1054]298/*removes all comments from the buffer*/
[1264]299static void mr_conf_remove_comments(void) {
[1054]300 char *tmp_buf; /*temporary buffer without comments */
301 size_t length /*initial length */ ;
302 size_t i; /*iterator */
303 size_t k; /*conditioned iterator for tmp_buffer */
[1422]304 bool found_quote = FALSE;
[1429]305 bool found_comment = FALSE;
[1054]306
307 length = strlen(buffer);
308
309 /*sizing the new chain */
310 k = 0;
311 i = 0;
312 while (i < length) {
[1427]313 /* Handle quotes to detect strings */
[1429]314 if ((buffer[i] == '"') && (! found_comment)) {
[1422]315 if (found_quote) {
316 found_quote = FALSE;
317 } else {
318 found_quote = TRUE;
319 }
[1423]320 }
[1429]321 /* Handle start of comment - only when not in a string */
322 if (buffer[i] == MRCONF_COMM_CHAR) {
323 if (found_quote) {
324 found_comment = FALSE;
325 } else {
326 found_comment = TRUE;
327 }
328 }
329 /* Comments end with EOL */
330 if (buffer[i] == '\n') {
331 found_comment = FALSE;
332 }
333 if (! found_comment) {
[1054]334 k++;
335 i++;
336 } else {
[1429]337 /* Skip comment */
[1054]338 while ((buffer[i] != '\n') && (buffer[i] != (char) 0)) {
339 i++;
340 }
[1427]341 if (buffer[i] == (char) 0) {
[1559]342 mr_conf_error_msg(MRCONF_STRING_ENDQUOTE, buffer);
[1427]343 }
[1054]344 }
345 }
346 /* k is new buffer length now */
347 tmp_buf = (char *) mr_malloc(sizeof(char) * (k + 1));
348
349 k = 0;
350 i = 0;
351 while (i < length) {
[1426]352 if (buffer[i] == '"') {
[1422]353 if (found_quote) {
354 found_quote = FALSE;
355 } else {
356 found_quote = TRUE;
357 }
[1423]358 }
[1427]359 if ((buffer[i] != MRCONF_COMM_CHAR) || (found_quote)) {
[1054]360 tmp_buf[k++] = buffer[i++];
361 } else {
[1427]362 /* Skip comment as it's not inside a string */
[1054]363 while ((buffer[i] != '\n') && (buffer[i] != (char) 0)) {
364 i++;
365 }
366 }
367 }
368 tmp_buf[k] = (char) 0; /*and set its length */
369
370 mr_free(buffer);
371 /*copy filtered data to the buffer */
372 buffer = tmp_buf;
373}
374
375static int mr_conf_check_int_flag(const int flag) {
376 return (flag & internal_flags);
377}
378
379static void mr_conf_set_int_flag(const int flag) {
380 internal_flags = flag | internal_flags;
381}
382
383static void mr_conf_drop_int_flag(const int flag) {
384 internal_flags = (~flag) & internal_flags;
385}
386
387
388/*local function to define size of a file. Return 0 for mistake*/
389static size_t mr_conf_filesize(const char *name) {
390 FILE *F = fopen(name, "r"); /*file to open */
391 size_t length; /*number to return */
392
393 if (F == NULL) {
394 return 0;
395 }
396
397 fseek(F, 0, SEEK_END); /*set position to the end of file */
398 length = ftell(F); /*define number of position=> this is its
399 length */
400 fclose(F);
401
402 return length;
403}
404
405/*output error message*/
[1422]406static void mr_conf_error_msg_int(int error_code, const char *add_line, int line, const char *file) {
[1054]407 if ((mr_conf_flags & MRCONF_FLAG_VERBOSE)) { /*if verbose mode */
408 switch (error_code) {
409 case MRCONF_BAD_FILE:
[1571]410 mr_msg_int(1,line,file,"%s (%s) %s %s", MRCONF_STR_ERROR, mr_conf_filename, MRCONF_STR_BAD_FILE,
[1054]411 add_line);
412 break;
413
414 case MRCONF_READING_FAILED:
[1571]415 mr_msg_int(1,line,file,"%s (%s) %s", MRCONF_STR_ERROR, mr_conf_filename, MRCONF_STR_READING_FAILED);
[1054]416 break;
417
418 case MRCONF_FIELD_NOT_FOUND:
[1584]419 mr_msg_int(1,line,file,"%s (%s) %s \"%s\"", MRCONF_STR_WARNING, mr_conf_filename, MRCONF_STR_FIELD_NOT_FOUND, add_line);
[1054]420 break;
421
422 case MRCONF_FIELD_NO_VALUE:
[1584]423 mr_msg_int(1,line,file,"%s (%s) %s \"%s\"", MRCONF_STR_ERROR, mr_conf_filename, MRCONF_STR_FIELD_NO_VALUE, add_line);
[1571]424 mr_msg_int(1,line,file,"%s (%s) %s", MRCONF_STR_WARNING, mr_conf_filename, MRCONF_STR_IGNORE);
[1054]425 break;
426
427 case MRCONF_CLOSE_BUT_NOT_OPEN:
[1571]428 mr_msg_int(1,line,file,"%s (%s) %s", MRCONF_STR_WARNING, mr_conf_filename, MRCONF_STR_CLOSE_BUT_NOT_OPEN);
[1054]429 break;
430
431 case MRCONF_CALL_BUT_NOT_OPEN:
[1571]432 mr_msg_int(1,line,file,"%s (%s) %s", MRCONF_STR_WARNING, mr_conf_filename, MRCONF_STR_CALL_BUT_NOT_OPEN);
[1054]433 break;
434
435 case MRCONF_OPEN_OPENED:
[1571]436 mr_msg_int(1,line,file,"%s (%s) %s", MRCONF_STR_ERROR, mr_conf_filename, MRCONF_STR_OPEN_OPENED);
[1054]437 break;
438
439 case MRCONF_STRING_QUOTE:
[1583]440 mr_msg_int(1,line,file,"%s: %s (%s) %s", add_line, MRCONF_STR_ERROR, mr_conf_filename, MRCONF_STR_STRING_QUOTE);
[1054]441 break;
442
[1542]443 case MRCONF_STRING_ENDQUOTE:
[1583]444 mr_msg_int(1,line,file,"%s: %s (%s) %s", add_line, MRCONF_STR_ERROR, mr_conf_filename, MRCONF_STR_STRING_ENDQUOTE);
[1542]445 break;
446
[1054]447 default:
[1571]448 mr_msg_int(1,line,file,"%s (%s) %s", MRCONF_STR_ERROR, mr_conf_filename, MRCONF_STR_DEFAULT_ERROR);
[1054]449 break;
450 }
451 }
452}
Note: See TracBrowser for help on using the repository browser.