00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <ctype.h>
00037 #include <errno.h>
00038 #include <limits.h>
00039 #include <math.h>
00040 #include <string.h>
00041 #include <strings.h>
00042
00043 #include "confloader.h"
00044
00045 static unsigned int linenum = 0;
00046
00047 static int
00048 withret( char* str)
00049 {
00050 unsigned int i = 0;
00051 if (str == NULL)
00052 return 0;
00053 while(str[i] != '\0') {
00054 if (str[i++] == '\n')
00055 return 1;
00056 }
00057 return 0;
00058 }
00059
00060 static int
00061 onlyblank(char* str)
00062 {
00063 unsigned int i = 0;
00064 while(str[i] != '\0')
00065 if (!isspace(str[i++]))
00066 return 0;
00067 return 1;
00068 }
00069
00070 static char*
00071 getline(FILE* file)
00072 {
00073 unsigned int size = 0;
00074 char* buf = NULL;
00075 while(!withret(buf)) {
00076 unsigned int osize = size;
00077 size *= 2;
00078 size += 256;
00079 buf = realloc(buf, size * sizeof(char));
00080 if (buf == NULL)
00081 return NULL;
00082 memset(buf + osize, 0, size - osize);
00083 if (osize) osize--;
00084 if (fgets(buf + osize, size, file) == NULL) {
00085 if (feof(file) && (withret(buf) || onlyblank(buf))) {
00086 linenum++;
00087 return buf;
00088 }
00089 free(buf);
00090 return NULL;
00091 }
00092 }
00093 linenum++;
00094 return buf;
00095 }
00096
00097 static int
00098 readyesno(char* line)
00099 {
00100 int ret = -1;
00101 unsigned int i = 0;
00102 unsigned int j = 0;
00103 while(line[i] != '=' && line[i] != '\0') {i++;}
00104 if (line[i++] == '\0') return -1;
00105 while(isspace(line[i])) {i++;}
00106 if (line[i] == '\0') return -1;
00107 j = i;
00108 while (line[j] != '\0' && !isspace(line[j])) {j++;}
00109 switch (j - i) {
00110 case 5:
00111 if (!strncasecmp(line + i, "false", 5)) ret = 0;
00112 else return -1;
00113 break;
00114 case 4:
00115 if (!strncasecmp(line + i, "true", 4)) ret = 1;
00116 else return -1;
00117 break;
00118 case 3:
00119 if (!strncasecmp(line + i, "yes", 3)) ret = 1;
00120 else return -1;
00121 break;
00122 case 2:
00123 if (!strncasecmp(line + i, "no", 2)) ret = 0;
00124 else return -1;
00125 break;
00126 case 1:
00127 if (line[i] == 'Y' || line[i] == 'y' || line[i] == '1') ret = 1;
00128 else if (line[i] == 'N' || line[i] == 'n' || line[i] == '0') ret = 0;
00129 else return -1;
00130 break;
00131 default:
00132 return -1;
00133 }
00134 while (line[j] != '\0' && line[j] != '#') {
00135 if (!isspace(line[j])) return -1;
00136 j++;
00137 }
00138 return ret;
00139 }
00140
00141 static int
00142 readint(char* line, long int* value, FILE* fderr)
00143 {
00144 long int tmp = 0;
00145 unsigned int i = 0;
00146 char* end = NULL;
00147 while(line[i] != '=' && line[i] != '\0') {i++;}
00148 if (line[i++] == '\0') return -1;
00149 while(line[i] != '\0' && isspace(line[i])) {i++;}
00150 if (line[i] == '\0') return -1;
00151
00152 tmp = strtol(line + i, &end, 0);
00153 if ((tmp == LONG_MIN || tmp == LONG_MAX) && errno == ERANGE) {
00154 if (fderr != NULL) {
00155 fprintf(fderr, "line %d: value out of range\n", linenum);
00156 }
00157 return -1;
00158 }
00159 while (*end != '\0' && *end != '#') {
00160 if (!isspace(*end))
00161 return -1;
00162 end++;
00163 }
00164 *value = tmp;
00165 return 1;
00166 }
00167
00168 static int
00169 readfloat(char* line, double* value, FILE* fderr)
00170 {
00171 double tmp = 0;
00172 unsigned int i = 0;
00173 char* end = NULL;
00174 while(line[i] != '=' && line[i] != '\0') {i++;}
00175 if (line[i++] == '\0') return -1;
00176 while(line[i] != '\0' && isspace(line[i])) {i++;}
00177 if (line[i] == '\0') return -1;
00178 tmp = strtod(line + i, &end);
00179 if ((tmp == -HUGE_VAL || tmp == HUGE_VAL || value == 0)
00180 && errno == ERANGE) {
00181 if (fderr != NULL) {
00182 fprintf(fderr, "line %d: value out of range\n", linenum);
00183 }
00184 return -1;
00185 }
00186 while (*end != '\0' && *end != '#') {
00187 if (!isspace(*end)) return -1;
00188 end++;
00189 }
00190 *value = tmp;
00191 return 1;
00192 }
00193
00194
00195
00196
00197
00198 static int
00199 readstring(char* line, char** value, char caselogfile)
00200 {
00201 char* tmp = NULL;
00202 unsigned int i = 0;
00203 unsigned int j = 0;
00204 unsigned int bscount = 0;
00205 char* end = NULL;
00206 if (!caselogfile) {
00207 while(line[i] != '=' && line[i] != '\0') {i++;}
00208 if (line[i++] == '\0') return -1;
00209 }
00210 while(line[i] != '\0' && isspace(line[i])) {i++;}
00211 if (line[i] != '"' && line[i] != '\'')
00212 return -1;
00213
00214 i++;
00215 j = i;
00216 LOOP:
00217 bscount = 0;
00218 while(line[i] != '"' && line[i] != '\'' && line[i] != '\0') {
00219 if (line[i] == '\\')
00220 bscount++;
00221 else
00222 bscount = 0;
00223 i++;
00224 }
00225 if ((line[i] == '"' || line[i] == '\'') && bscount % 2 == 1)
00226 goto LOOP;
00227
00228 end = line + i + 1;
00229 while (*end != '\0' && *end != '#') {
00230 if (!isspace(*end)) return -1;
00231 end++;
00232 }
00233
00234 tmp = (char*) malloc(sizeof(char) * (i - j + 1));
00235 memcpy(tmp, line + j, i - j);
00236 tmp[i - j] = '\0';
00237
00238 *value = tmp;
00239 return i - j;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248 static log_t
00249 readlogtype(char* line, char** value, FILE* fderr)
00250 {
00251 log_t tmp = LOG__NOTDEF;
00252 char* filename = NULL;
00253 unsigned int i = 0;
00254 char* end = NULL;
00255 int len = 0;
00256 while(line[i] != '=' && line[i] != '\0') {i++;}
00257 if (line[i++] == '\0') return ELOG;
00258 while(line[i] != '\0' && isspace(line[i])) {i++;}
00259 if (line[i] == '\0') return ELOG;
00260 len = strlen(line+i);
00261 if (len >= 4) {
00262 if (strncasecmp(line+i, "none", 4) == 0) {
00263 tmp = LOG__NONE;
00264 end = line + i + 4;
00265 goto LENOK;
00266 }
00267 }
00268 if (len >= 6) {
00269 if (strncasecmp(line+i, "syslog", 6) == 0) {
00270 tmp = LOG__SYSLOG;
00271 end = line + i + 6;
00272 }
00273 if (strncasecmp(line+i, "stderr", 6) == 0) {
00274 tmp = LOG__STDERR;
00275 end = line + i + 6;
00276 }
00277 if (strncasecmp(line+i, "stdout", 6) == 0) {
00278 tmp = LOG__STDOUT;
00279 end = line + i + 6;
00280 }
00281 if (strncasecmp(line+i, "file ", 5) == 0)
00282 tmp = LOG__FILE;
00283 goto LENOK;
00284 }
00285 return ELOG;
00286 LENOK:
00287 if (tmp == LOG__FILE) {
00288 int filenamelen = -1;
00289 int spc = 0;
00290 while(line[5 + i + spc] != '\0' && isspace(line[5 + i + spc])) {spc++;}
00291 filenamelen = readstring(line + i + 5, &filename, 1);
00292 if (filenamelen == -1)
00293 return ELOG;
00294 end = line + 7 + i + filenamelen + spc;
00295 }
00296 while (*end != '\0' && *end != '#') {
00297 if (!isspace(*end)) return ELOG;
00298 end++;
00299 }
00300 *value = filename;
00301 return tmp;
00302 }
00303
00304 static int
00305 lineparse(FILE* file, FILE* fderr)
00306 {
00307 char* line = getline(file);
00308 unsigned int i = 0;
00309 unsigned int j = i;
00310 int size = 0;
00311 int n = 0;
00312 if (line == NULL)
00313 return -1;
00314 while(isspace(line[i])) {i++;}
00315 if (line[i] == '\0' || line[i] == '#') {
00316 free(line);
00317 return 0;
00318 }
00319 while(line[j] != '\0' && !isspace(line[j])
00320 && line[j] != '=') {j++;}
00321 if (line[j] == '\0') {
00322 free(line);
00323 return -1;
00324 }
00325 size = j - i;
00326 while (conf[n].name != NULL) {
00327 if (strlen(conf[n].name) < size) {
00328 n++;
00329 continue;
00330 }
00331 if (!strncmp(conf[n].name, line + i, size)) {
00332 switch (conf[n].type) {
00333 case YESNO:
00334 #ifdef _DEBUGCONFLOADER_
00335 fprintf(stderr, "case yesno");
00336 #endif
00337 conf[n].value.yn = readyesno(line + i);
00338 free(line);
00339 if (conf[n].value.yn == -1) return -1;
00340 if (conf[n].mandatory) conf[n].mandatory++;
00341 #ifdef _DEBUGCONFLOADER_
00342 fprintf(stderr, " (%d)\n", conf[n].value.yn);
00343 #endif
00344 return 1;
00345 case INTOPT:
00346 {
00347 long int val = 0;
00348 #ifdef _DEBUGCONFLOADER_
00349 fprintf(stderr, "case intopt");
00350 #endif
00351 if (readint(line, &val, fderr) != -1) {
00352 free(line);
00353 conf[n].value.i = val;
00354 if (conf[n].mandatory) conf[n].mandatory++;
00355 #ifdef _DEBUGCONFLOADER_
00356 fprintf(stderr, " (%ld)\n", val);
00357 #endif
00358 return 1;
00359 }
00360 free(line);
00361 return -1;
00362 }
00363 case FLOATOPT:
00364 {
00365 double val = 0;
00366 #ifdef _DEBUGCONFLOADER_
00367 fprintf(stderr, "case floatopt");
00368 #endif
00369 if (readfloat(line, &val, fderr) != -1) {
00370 free(line);
00371 conf[n].value.f = val;
00372 if (conf[n].mandatory) conf[n].mandatory++;
00373 #ifdef _DEBUGCONFLOADER_
00374 fprintf(stderr, " (%f)\n", val);
00375 #endif
00376 return 1;
00377 }
00378 free(line);
00379 return -1;
00380 }
00381 case STRINGOPT:
00382 {
00383 char* val = NULL;
00384 #ifdef _DEBUGCONFLOADER_
00385 fprintf(stderr, "case stringopt");
00386 #endif
00387 if (readstring(line, &val, 0) != -1) {
00388 free(line);
00389 conf[n].value.str = val;
00390 if (conf[n].mandatory) conf[n].mandatory++;
00391 #ifdef _DEBUGCONFLOADER_
00392 fprintf(stderr, " (%s)\n", val);
00393 #endif
00394 return 1;
00395 }
00396 free(line);
00397 return -1;
00398 }
00399 case FILEOPT:
00400 {
00401 char* val = NULL;
00402 #ifdef _DEBUGCONFLOADER_
00403 fprintf(stderr, "case fileopt (not fully implemented)");
00404 #endif
00405 if (readstring(line, &val, 0) != -1) {
00406 free(line);
00407 conf[n].value.str = val;
00408 if (conf[n].mandatory) conf[n].mandatory++;
00409 #ifdef _DEBUGCONFLOADER_
00410 fprintf(stderr, " (%s)\n", val);
00411 #endif
00412
00413 return 1;
00414 }
00415 free(line);
00416 return -1;
00417 }
00418 case LOGOPT:
00419 {
00420 char* val = NULL;
00421 unsigned int logtype = 0;
00422 #ifdef _DEBUGCONFLOADER_
00423 fprintf(stderr, "case logopt");
00424 #endif
00425 logtype = readlogtype(line, &val, fderr);
00426 free(line);
00427 if (logtype != ELOG) {
00428 conf[n].value.log.logtype = logtype;
00429 conf[n].value.log.filename = val;
00430 if (conf[n].mandatory) conf[n].mandatory++;
00431 #ifdef _DEBUGCONFLOADER_
00432 if (conf[n].value.log.logtype == LOG__FILE)
00433 fprintf(stderr, " (file: %s)\n", conf[n].value.log.filename);
00434 if (conf[n].value.log.logtype == LOG__SYSLOG)
00435 fprintf(stderr, " (syslog)\n");
00436 if (conf[n].value.log.logtype == LOG__STDERR)
00437 fprintf(stderr, " (stderr)\n");
00438 if (conf[n].value.log.logtype == LOG__STDOUT)
00439 fprintf(stderr, " (stdout)\n");
00440 if (conf[n].value.log.logtype == LOG__NONE)
00441 fprintf(stderr, " (none)\n");
00442 #endif
00443 return 1;
00444 }
00445 return -1;
00446 }
00447 default:
00448 #ifdef _DEBUGCONFLOADER_
00449 fprintf(stderr, "unknown case\n");
00450 #endif
00451 if (fderr != NULL) {
00452 line[j] = '\0';
00453 fprintf(fderr, "%s: bad type in confoptions\n", line + i);
00454 }
00455 free(line);
00456 return -1;
00457 }
00458 }
00459 n++;
00460 }
00461 if (fderr != NULL) {
00462 line[j] = '\0';
00463 fprintf(fderr, "%s: unknown option\n", line + i);
00464 }
00465 free(line);
00466 return -1;
00467 }
00468
00469 int
00470 confparse(char* conffile, FILE* fderr)
00471 {
00472 FILE* file = fopen(conffile, "r");
00473 int nboptset = 0;
00474 int i = 0;
00475 if (file == NULL) {
00476 fprintf(fderr, "confparser: unable to open configuration file. ");
00477 perror("fopen: ");
00478 return -1;
00479 }
00480
00481 while(!feof(file)) {
00482 int ret = lineparse(file, fderr);
00483 if (ret == -1) {
00484 if (fderr != NULL)
00485 fprintf(fderr, "Parse error line %d\n", linenum);
00486 (void) fclose(file);
00487 return -1;
00488 }
00489 if (ret == 1)
00490 nboptset++;
00491
00492 }
00493 (void) fclose(file);
00494 while (conf[i].name != NULL) {
00495 if (conf[i].mandatory == 1) {
00496 fprintf(fderr, "Mandatory option '%s' missing in the specified configuration file...\n", conf[i].name);
00497 return -1;
00498 }
00499 i++;
00500 }
00501 return nboptset;
00502 }
00503
00504 option
00505 getconf(const char* name)
00506 {
00507 unsigned int namelen = strlen(name);
00508 unsigned int n = 0;
00509 while(conf[n].name != NULL) {
00510 if (strlen(conf[n].name) == namelen) {
00511 if (strncmp(conf[n].name, name, namelen) == 0) {
00512 return conf[n];
00513 }
00514 }
00515 n++;
00516 }
00517 return conf[n];
00518 }