4576691 [rkeene@sledge /home/rkeene/devel/libconfig-0.2.5]$ cat -n libconfig.c
   1 #include "compat.h"
   2 #include "libconfig.h"
   3 #include "libconfig_private.h"
   4 #include "conf_section.h"
   5 #include "conf_apache.h"
   6 #include "conf_colon.h"
   7 #include "conf_equal.h"
   8 #include "conf_space.h"
   9 #include "conf_xml.h"
  10 
  11 #ifdef HAVE_STRING_H
  12 #include <string.h>
  13 #endif
  14 
  15 #ifdef HAVE_STDLIB_H
  16 #include <stdlib.h>
  17 #endif
  18 
  19 #ifdef HAVE_CTYPE_H
  20 #include <ctype.h>
  21 #endif
  22 
  23 #ifdef HAVE_STDIO_H
  24 #include <stdio.h>
  25 #endif
  26 
  27 #ifdef HAVE_UNISTD_H
  28 #include <unistd.h>
  29 #endif
  30 
  31 #ifdef HAVE_SYS_TYPES_H
  32 #include <sys/types.h>
  33 #endif
  34 
  35 #ifdef HAVE_PWD_H
  36 #include <pwd.h>
  37 #endif
  38 
  39 #ifdef HAVE_NETDB_H
  40 #include <netdb.h>
  41 #endif
  42 
  43 struct lc_varhandler_st *varhandlers = NULL;
  44 lc_err_t lc_errno = LC_ERR_NONE;
  45 const char *lc_err_usererrmsg = NULL;
  46 const char *lc_errfile = NULL;
  47 int lc_optind = 0;
  48 int lc_errline = 0;
  49 
  50 extern char **environ;
  51 
  52 static int lc_process_var_string(void *data, const char *value, const char **endptr) {
  53     char **dataval;
  54 
  55     dataval = data;
  56     *dataval = strdup(value);
  57 
  58     *endptr = NULL;
  59 
  60     return(0);
  61 }
  62 
  63 static int lc_process_var_cidr(void *data, const char *value, const char **endptr) {
  64     return(-1);
  65 }
  66 
  67 static int lc_process_var_hostname4(uint32_t *data, const char *value, const char **endptr) {
  68     struct hostent *ghbn_ret;
  69 
  70     ghbn_ret = gethostbyname(value);
  71     if (ghbn_ret == NULL) {
  72         return(-1);
  73     }
  74 
  75     if (ghbn_ret->h_length != 4) {
  76         return(-1);
  77     }
  78 
  79     if (ghbn_ret->h_addr_list[0] == 0) {
  80         return(-1);
  81     }
  82 
  83     memcpy(data, ghbn_ret->h_addr_list[0], sizeof(*data));
  84 
  85     return(0);
  86 }
  87 
  88 static int lc_process_var_hostname6(void *data, const char *value, const char **endptr) {
  89     return(-1);
  90 }
  91 
  92 static int lc_process_var_ip4(uint32_t *data, const char *value, const char **endptr) {
  93     uint32_t ipval = 0, curr_ipval = 0;
  94     const char *valptr;
  95     int retval = 0;
  96     int dotcount = 0;
  97 
  98     for (valptr = value; *valptr; valptr++) {
  99         if (!isdigit(*valptr)) {
 100             if (*valptr == '.' || *valptr == ',') {
 101                 dotcount++;
 102                 if (dotcount >= 4) {
 103                     retval = -1;
 104                     break;
 105                 }
 106 
 107                 if (curr_ipval > 255) {
 108                     retval = -1;
 109                     break;
 110                 }
 111 
 112                 /* For lists */
 113                 if (*valptr == ',') {
 114                     break;
 115                 }
 116 
 117                 ipval |= curr_ipval << ((dotcount - 1) * 8);
 118                 curr_ipval = 0;
 119 
 120                 continue;
 121             } else {
 122                 retval = -1;
 123                 break;
 124             }
 125         }
 126 
 127         curr_ipval *= 10;
 128         curr_ipval += *valptr - '0';
 129     }
 130 
 131     if (curr_ipval > 255) {
 132         retval = -1;
 133     }
 134 
 135     if (retval == 0) {
 136         ipval |= curr_ipval << 24;
 137         *data = ipval;
 138     }
 139 
 140     return(retval);
 141 }
 142 
 143 static int lc_process_var_ip6(void *data, const char *value, const char **endptr) {
 144     return(-1);
 145 }
 146 
 147 static int lc_process_var_addr4(uint32_t *data, const char *value, const char **endptr) {
 148     int lc_pv_ret;
 149 
 150     lc_pv_ret = lc_process_var_ip4(data, value, endptr);
 151     if (lc_pv_ret == 0) {
 152         return(lc_pv_ret);
 153     }
 154 
 155     lc_pv_ret = lc_process_var_hostname4(data, value, endptr);
 156     if (lc_pv_ret == 0) {
 157         return(lc_pv_ret);
 158     }
 159 
 160     return(-1);
 161 }
 162 
 163 static int lc_process_var_addr6(void *data, const char *value, const char **endptr) {
 164     int lc_pv_ret;
 165 
 166     lc_pv_ret = lc_process_var_ip6(data, value, endptr);
 167     if (lc_pv_ret == 0) {
 168         return(lc_pv_ret);
 169     }
 170 
 171     lc_pv_ret = lc_process_var_hostname6(data, value, endptr);
 172     if (lc_pv_ret == 0) {
 173         return(lc_pv_ret);
 174     }
 175     return(-1);
 176 }
 177 
 178 static int lc_process_var_longlong(long long *data, const char *value, const char **endptr) {
 179     *data = strtoll(value, (char **) endptr, 10);
 180 
 181     return(0);
 182 }
 183 
 184 static int lc_process_var_long(long *data, const char *value, const char **endptr) {
 185     *data = strtoll(value, (char **) endptr, 10);
 186 
 187     return(0);
 188 }
 189 
 190 static int lc_process_var_int(int *data, const char *value, const char **endptr) {
 191     *data = strtoll(value, (char **) endptr, 10);
 192 
 193     return(0);
 194 }
 195 
 196 static int lc_process_var_short(short *data, const char *value, const char **endptr) {
 197     *data = strtoll(value, (char **) endptr, 10);
 198 
 199     return(0);
 200 }
 201 
 202 static int lc_process_var_bool_byexistance(int *data, const char *value, const char **endptr) {
 203     *data = 1;
 204 
 205     *endptr = NULL;
 206 
 207     return(0);
 208 }
 209 
 210 static int lc_process_var_bool(int *data, const char *value, const char **endptr) {
 211     char *trueval[] = {"enable", "true", "yes", "on", "y", "1"};
 212     char *falseval[] = {"disable", "false", "no", "off", "n", "0"};
 213     size_t chkvallen, vallen;
 214     int i;
 215 
 216     *data = -1;
 217 
 218     vallen = strlen(value);
 219 
 220     for (i = 0; i < (sizeof(trueval) / sizeof(*trueval)); i++) {
 221         chkvallen = strlen(trueval[i]);
 222 
 223         /*
 224          * Skip if there's no way we could find a match here.
 225          */
 226         if (chkvallen > vallen) {
 227             continue;
 228         }
 229 
 230         /*
 231          * Skip if there is no partial match.
 232          */
 233         if (strncasecmp(value, trueval[i], chkvallen) != 0) {
 234             continue;
 235         }
 236 
 237         if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \
 238             value[chkvallen] == ' ') {
 239             /* Declare a winner and set the next token. */
 240             *endptr = value + chkvallen;
 241             *data = 1;
 242             return(0);
 243         }
 244     }
 245 
 246     for (i = 0; i < (sizeof(falseval) / sizeof(*falseval)); i++) {
 247         chkvallen = strlen(falseval[i]);
 248 
 249         /*
 250          * Skip if there's no way we could find a match here.
 251          */
 252         if (chkvallen > vallen) {
 253             continue;
 254         }
 255 
 256         /*
 257          * Skip if there is no partial match.
 258          */
 259         if (strncasecmp(value, falseval[i], chkvallen) != 0) {
 260             continue;
 261         }
 262 
 263         if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \
 264             value[chkvallen] == ' ') {
 265             /* Declare a winner and set the next token. */
 266             *endptr = value + chkvallen;
 267             *data = 0;
 268             return(0);
 269         }
 270     }
 271 
 272     lc_errno = LC_ERR_BADFORMAT;
 273     return(-1);
 274 }
 275 
 276 static unsigned long long lc_process_size(const char *value, const char **endptr) {
 277     unsigned long long retval = 0;
 278     char *mult = NULL;
 279 
 280     retval = strtoll(value, &mult, 10);
 281     if (mult != NULL) {
 282         switch (tolower(mult[0])) {
 283             case 'p':
 284                 retval *= 1125899906842624LLU;
 285                 break;
 286             case 't':
 287                 retval *= 1958505086976LLU;
 288                 break;
 289             case 'g':
 290                 retval *= 1073741824;
 291                 break;
 292             case 'm':
 293                 retval *= 1048576;
 294                 break;
 295             case 'k':
 296                 retval *= 1024;
 297                 break;
 298             default:
 299                 break;
 300         }
 301     }
 302 
 303     return(retval);
 304 }
 305 
 306 static int lc_process_var_sizelonglong(long long *data, const char *value, const char **endptr) {
 307     *data = lc_process_size(value, endptr);
 308 
 309     return(0);
 310 }
 311 
 312 static int lc_process_var_sizelong(long *data, const char *value, const char **endptr) {
 313     *data = lc_process_size(value, endptr);
 314 
 315     return(0);
 316 }
 317 
 318 static int lc_process_var_sizeint(int *data, const char *value, const char **endptr) {
 319     *data = lc_process_size(value, endptr);
 320 
 321     return(0);
 322 }
 323 
 324 static int lc_process_var_sizeshort(short *data, const char *value, const char **endptr) {
 325     *data = lc_process_size(value, endptr);
 326 
 327     return(0);
 328 }
 329 
 330 static int lc_process_var_sizesizet(size_t *data, const char *value, const char **endptr) {
 331     *data = lc_process_size(value, endptr);
 332 
 333     return(0);
 334 }
 335 
 336 static int lc_process_var_float(float *data, const char *value, const char **endptr) {
 337 #ifdef HAVE_STRTOF
 338     *data = strtof(value, endptr);
 339 #else
 340     *data = strtod(value, endptr);
 341 #endif
 342 
 343     return(0);
 344 }
 345 
 346 static int lc_process_var_double(double *data, const char *value, const char **endptr) {
 347     *data = strtod(value, endptr);
 348 
 349     return(0);
 350 }
 351 
 352 
 353 int lc_handle_type(lc_var_type_t type, const char *value, void *data) {
 354     const char *next;
 355     int is_list;
 356 
 357     is_list = type & LC_VAR_LIST;
 358 
 359     if (is_list == LC_VAR_LIST) {
 360         /* XXX */
 361     }
 362 
 363     switch (type) {
 364         case LC_VAR_STRING:
 365             return(lc_process_var_string(data, value, &next));
 366             break;
 367         case LC_VAR_LONG_LONG:
 368             return(lc_process_var_longlong(data, value, &next));
 369             break;
 370         case LC_VAR_LONG:
 371             return(lc_process_var_long(data, value, &next));
 372             break;
 373         case LC_VAR_INT:
 374             return(lc_process_var_int(data, value, &next));
 375             break;
 376         case LC_VAR_SHORT:
 377             return(lc_process_var_short(data, value, &next));
 378             break;
 379         case LC_VAR_BOOL:
 380             return(lc_process_var_bool(data, value, &next));
 381             break;
 382         case LC_VAR_SIZE_LONG_LONG:
 383             return(lc_process_var_sizelonglong(data, value, &next));
 384             break;
 385         case LC_VAR_SIZE_LONG:
 386             return(lc_process_var_sizelong(data, value, &next));
 387             break;
 388         case LC_VAR_SIZE_INT:
 389             return(lc_process_var_sizeint(data, value, &next));
 390             break;
 391         case LC_VAR_SIZE_SHORT:
 392             return(lc_process_var_sizeshort(data, value, &next));
 393             break;
 394         case LC_VAR_BOOL_BY_EXISTANCE:
 395             return(lc_process_var_bool_byexistance(data, value, &next));
 396             break;
 397         case LC_VAR_SIZE_SIZE_T:
 398             return(lc_process_var_sizesizet(data, value, &next));
 399             break;
 400         case LC_VAR_IP:
 401         case LC_VAR_IP4:
 402             return(lc_process_var_ip4(data, value, &next));
 403             break;
 404         case LC_VAR_IP6:
 405             return(lc_process_var_ip6(data, value, &next));
 406             break;
 407         case LC_VAR_ADDR:
 408         case LC_VAR_ADDR4:
 409             return(lc_process_var_addr4(data, value, &next));
 410         case LC_VAR_ADDR6:
 411             return(lc_process_var_addr6(data, value, &next));
 412         case LC_VAR_HOSTNAME:
 413         case LC_VAR_HOSTNAME4:
 414             return(lc_process_var_hostname4(data, value, &next));
 415             break;
 416         case LC_VAR_HOSTNAME6:
 417             return(lc_process_var_hostname6(data, value, &next));
 418             break;
 419         case LC_VAR_CIDR:
 420             return(lc_process_var_cidr(data, value, &next));
 421             break;
 422         case LC_VAR_DOUBLE:
 423             return(lc_process_var_double(data, value, &next));
 424             break;
 425         case LC_VAR_FLOAT:
 426             return(lc_process_var_float(data, value, &next));
 427             break;
 428         case LC_VAR_TIME:
 429         case LC_VAR_DATE:
 430         case LC_VAR_FILENAME:
 431         case LC_VAR_DIRECTORY:
 432 #ifdef DEBUG
 433             fprintf(stderr, "Not implemented yet!\n");
 434 #endif
 435             return(-1);
 436         case LC_VAR_NONE:
 437         case LC_VAR_UNKNOWN:
 438         case LC_VAR_SECTION:
 439         case LC_VAR_SECTIONSTART:
 440         case LC_VAR_SECTIONEND:
 441             return(0);
 442         case LC_VAR_LIST:
 443             return(0);
 444     }
 445 
 446     return(-1);
 447 }
 448 
 449 static int lc_handle(struct lc_varhandler_st *handler, const char *var, const char *varargs, const char *value,
	lc_flags_t flags) {
 450     const char *localvar = NULL;
 451     int retval;
 452 
 453     if (var != NULL) {
 454         localvar = strrchr(var, '.');
 455         if (localvar == NULL) {
 456             localvar = var;
 457         } else {
 458             localvar++;
 459         }
 460     } else {
 461         localvar = NULL;
 462     }
 463 
 464     switch (handler->mode) {
 465         case LC_MODE_CALLBACK:
 466             if (handler->callback != NULL) {
 467                 retval = handler->callback(localvar, var, varargs, value, flags, handler->extra);
 468                 if (retval < 0) {
 469                     lc_errno = LC_ERR_CALLBACK;
 470                 }
 471 
 472                 return(retval);
 473             }
 474             break;
 475         case LC_MODE_VAR:
 476             return(lc_handle_type(handler->type, value, handler->data));
 477             break;
 478     }
 479 
 480     return(-1);
 481 }
 482 
 483 static int lc_process_environment(const char *appname) {
 484 #ifndef ENABLE_SMALL
 485     struct lc_varhandler_st *handler = NULL;
 486     size_t appnamelen = 0;
 487     char varnamebuf[128] = {0};
 488     char **currvar;
 489     char *sep = NULL, *value = NULL, *cmd = NULL;
 490     char *ucase_appname = NULL, *ucase_appname_itr = NULL;
 491     char *lastcomponent_handler = NULL;
 492     int varnamelen = 0;
 493     char *local_lc_errfile;
 494     int local_lc_errline;
 495 
 496     /* Make sure we have an environment to screw with, if not,
 497        no arguments were found to be in error */
 498     if (environ == NULL || appname == NULL) {
 499         return(0);
 500     }
 501 
 502     local_lc_errfile = "<environment>";
 503     local_lc_errline = 0;
 504 
 505     /* Allocate and create our uppercase appname. */
 506     ucase_appname = strdup(appname);
 507     if (ucase_appname == NULL) {
 508         lc_errfile = local_lc_errfile;
 509         lc_errline = local_lc_errline;
 510         lc_errno = LC_ERR_ENOMEM;
 511         return(-1);
 512     }
 513     for (ucase_appname_itr = ucase_appname; *ucase_appname_itr != '\0'; ucase_appname_itr++) {
 514         *ucase_appname_itr = toupper(*ucase_appname_itr);
 515     }
 516 
 517     appnamelen = strlen(ucase_appname);
 518 
 519     for (currvar = environ; *currvar != NULL; currvar++) {
 520         /* If it doesn't begin with our appname ignore it completely. */
 521         if (strncmp(*currvar, ucase_appname, appnamelen) != 0) {
 522             continue;
 523         }
 524 
 525         /* Find our seperator. */
 526         sep = strchr(*currvar, '=');
 527         if (sep == NULL) {
 528             continue;
 529         }
 530 
 531         varnamelen = sep - *currvar;
 532 
 533         /* Skip variables that would overflow our buffer. */
 534         if (varnamelen >= sizeof(varnamebuf)) {
 535             continue;
 536         }
 537 
 538         strncpy(varnamebuf, *currvar, varnamelen);
 539 
 540         varnamebuf[varnamelen] = '\0';
 541         value = sep + 1;
 542 
 543         /* We ignore APPNAME by itself. */
 544         if (strlen(varnamebuf) <= appnamelen) {
 545             continue;
 546         }
 547 
 548         /* Further it must be <APPNAME>_ */
 549         if (varnamebuf[appnamelen] != '_') {
 550             continue;
 551         }
 552 
 553         cmd = varnamebuf + appnamelen + 1;
 554 
 555         /* We don't allow section specifiers, for reasons see notes in
 556            the cmdline processor (below). */
 557         if (strchr(cmd, '.') != NULL) {
 558             continue;
 559         }
 560 
 561         for (handler = varhandlers; handler != NULL; handler = handler->_next) {
 562             if (handler->var == NULL) {
 563                 continue;
 564             }
 565 
 566             /* Skip handlers which don't agree with being
 567                processed outside a config file */
 568             if (handler->type == LC_VAR_SECTION ||
 569                 handler->type == LC_VAR_SECTIONSTART ||
 570                 handler->type == LC_VAR_SECTIONEND ||
 571                 handler->type == LC_VAR_UNKNOWN) {
 572                 continue;
 573             }
 574 
 575             /* Find the last part of the variable and compare it with 
 576                the option being processed, if a wildcard is given. */
 577             if (handler->var[0] == '*' && handler->var[1] == '.') {
 578                 lastcomponent_handler = strrchr(handler->var, '.');
 579                 if (lastcomponent_handler == NULL) {
 580                     lastcomponent_handler = handler->var;
 581                 } else {
 582                     lastcomponent_handler++;
 583                 }
 584             } else {
 585                 lastcomponent_handler = handler->var;
 586             }
 587 
 588             /* Ignore this handler if they don't match. */
 589             if (strcasecmp(lastcomponent_handler, cmd) != 0) {
 590                 continue;
 591             }
 592 
 593             if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
 594                 value = NULL;
 595             }
 596 
 597             /* We ignore errors from the environment variables,
 598                they're mostly insignificant. */
 599             lc_handle(handler, cmd, NULL, value, LC_FLAGS_ENVIRON);
 600 
 601             break;
 602         }
 603     }
 604 
 605     free(ucase_appname);
 606 
 607 #endif
 608     return(0);
 609 }
 610 
 611 static int lc_process_cmdline(int argc, char **argv) {
 612     struct lc_varhandler_st *handler = NULL;
 613     char *cmdarg = NULL, *cmdoptarg = NULL;
 614     char *lastcomponent_handler = NULL;
 615     char **newargv = NULL;
 616     char *usedargv = NULL;
 617     int cmdargidx = 0;
 618     int newargvidx = 0;
 619     int retval = 0, chkretval = 0;
 620     int ch = 0;
 621     char *local_lc_errfile;
 622     int local_lc_errline;
 623 
 624     local_lc_errfile = "<cmdline>";
 625     local_lc_errline = 0;
 626 
 627     /* Allocate "argc + 1" (+1 for the NULL terminator) elements. */
 628     newargv = malloc((argc + 1) * sizeof(*newargv));
 629     if (newargv == NULL) {
 630         lc_errfile = local_lc_errfile;
 631         lc_errline = local_lc_errline;
 632         lc_errno = LC_ERR_ENOMEM;
 633         return(-1);
 634     }
 635     newargv[newargvidx++] = argv[0];
 636     newargv[argc] = NULL;
 637 
 638     /* Allocate space to indicate which arguments have been used. */
 639     usedargv = malloc(argc * sizeof(*usedargv));
 640     if (usedargv == NULL) {
 641         lc_errfile = local_lc_errfile;
 642         lc_errline = local_lc_errline;
 643         lc_errno = LC_ERR_ENOMEM;
 644         free(newargv);
 645         return(-1);
 646     }
 647     for (cmdargidx = 0; cmdargidx < argc; cmdargidx++) {
 648         usedargv[cmdargidx] = 0;
 649     }
 650 
 651     for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
 652         cmdarg = argv[cmdargidx];
 653 
 654         /* Make sure we have an argument here. */
 655         if (cmdarg == NULL) {
 656             break;
 657         }
 658 
 659         /* If the argument isn't an option, skip. */
 660         if (cmdarg[0] != '-') {
 661             continue;
 662         }
 663 
 664         /* Setup a pointer in the new array for the actual argument. */
 665         newargv[newargvidx++] = cmdarg;
 666         usedargv[cmdargidx] = 1;
 667 
 668         /* Then shift the argument past the '-' so we can ignore it. */
 669         cmdarg++;
 670 
 671         /* Handle long options. */
 672         if (cmdarg[0] == '-') {
 673             cmdarg++;
 674 
 675             /* Don't process arguments after the '--' option. */
 676             if (cmdarg[0] == '\0') {
 677                 break;
 678             }
 679 
 680             /* Look for a variable name that matches */
 681             for (handler = varhandlers; handler != NULL; handler = handler->_next) {
 682                 /* Skip handlers with no variable name. */
 683                 if (handler->var == NULL) {
 684                     continue;
 685                 }
 686                 /* Skip handlers which don't agree with being
 687                    processed on the command line. */
 688                 if (handler->type == LC_VAR_SECTION ||
 689                     handler->type == LC_VAR_SECTIONSTART ||
 690                     handler->type == LC_VAR_SECTIONEND ||
 691                     handler->type == LC_VAR_UNKNOWN) {
 692                     continue;
 693                 }
 694 
 695                 /* Find the last part of the variable and compare it with 
 696                    the option being processed, if a wildcard is given. */
 697                 if (handler->var[0] == '*' && handler->var[1] == '.') {
 698                     lastcomponent_handler = strrchr(handler->var, '.');
 699                     if (lastcomponent_handler == NULL) {
 700                         lastcomponent_handler = handler->var;
 701                     } else {
 702                         lastcomponent_handler++;
 703                     }
 704                 } else {
 705                     /* Disallow use of the fully qualified name
 706                        since there was no sectionstart portion
 707                        we cannot allow it to handle children of it. */
 708                     if (strchr(cmdarg, '.') != NULL) {
 709                         continue;
 710                     }
 711                     lastcomponent_handler = handler->var;
 712                 }
 713 
 714                 /* Ignore this handler if they don't match. */
 715                 if (strcasecmp(lastcomponent_handler, cmdarg) != 0) {
 716                     continue;
 717                 }
 718 
 719                 if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
 720                     cmdoptarg = NULL;
 721                 } else {
 722                     cmdargidx++;
 723                     if (cmdargidx >= argc) {
 724                         fprintf(stderr, "Argument required.\n");
 725                         lc_errfile = local_lc_errfile;
 726                         lc_errline = local_lc_errline;
 727                         lc_errno = LC_ERR_BADFORMAT;
 728                         free(usedargv);
 729                         free(newargv);
 730                         return(-1);
 731                     }
 732                     cmdoptarg = argv[cmdargidx];
 733                     newargv[newargvidx++] = cmdoptarg;
 734                     usedargv[cmdargidx] = 1;
 735                 }
 736 
 737                 chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE);
 738                 if (chkretval < 0) {
 739                     retval = -1;
 740                 }
 741 
 742                 break;
 743             }
 744 
 745             if (handler == NULL) {
 746                 fprintf(stderr, "Unknown option: --%s\n", cmdarg);
 747                 lc_errfile = local_lc_errfile;
 748                 lc_errline = local_lc_errline;
 749                 lc_errno = LC_ERR_INVCMD;
 750                 free(usedargv);
 751                 free(newargv);
 752                 return(-1);
 753             }
 754         } else {
 755             for (; *cmdarg != '\0'; cmdarg++) {
 756                 ch = *cmdarg;
 757 
 758                 for (handler = varhandlers; handler != NULL; handler = handler->_next) {
 759                     if (handler->opt != ch || handler->opt == '\0') {
 760                         continue;
 761                     }
 762                     /* Skip handlers which don't agree with being
 763                        processed on the command line. */
 764                     if (handler->type == LC_VAR_SECTION ||
 765                         handler->type == LC_VAR_SECTIONSTART ||
 766                         handler->type == LC_VAR_SECTIONEND ||
 767                         handler->type == LC_VAR_UNKNOWN) {
 768                         continue;
 769                     }
 770 
 771                     if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
 772                         cmdoptarg = NULL;
 773                     } else {
 774                         cmdargidx++;
 775                         if (cmdargidx >= argc) {
 776                             fprintf(stderr, "Argument required.\n");
 777                             lc_errfile = local_lc_errfile;
 778                             lc_errline = local_lc_errline;
 779                             lc_errno = LC_ERR_BADFORMAT;
 780                             free(usedargv);
 781                             free(newargv);
 782                             return(-1);
 783                         }
 784                         cmdoptarg = argv[cmdargidx];
 785                         newargv[newargvidx++] = cmdoptarg;
 786                         usedargv[cmdargidx] = 1;
 787                     }
 788 
 789                     chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE);
 790                     if (chkretval < 0) {
 791                         lc_errfile = local_lc_errfile;
 792                         lc_errline = local_lc_errline;
 793                         retval = -1;
 794                     }
 795 
 796                     break;
 797                 }
 798 
 799                 if (handler == NULL) {
 800                     fprintf(stderr, "Unknown option: -%c\n", ch);
 801                     lc_errfile = local_lc_errfile;
 802                     lc_errline = local_lc_errline;
 803                     lc_errno = LC_ERR_INVCMD;
 804                     free(usedargv);
 805                     free(newargv);
 806                     return(-1);
 807                 }
 808             }
 809         }
 810     }
 811 
 812     if (retval >= 0) {
 813         lc_optind = newargvidx;
 814         for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
 815             if (usedargv[cmdargidx] != 0) {
 816                 continue;
 817             }
 818             
 819             cmdarg = argv[cmdargidx];
 820 
 821             newargv[newargvidx++] = cmdarg;
 822         }
 823         for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
 824             argv[cmdargidx] = newargv[cmdargidx];
 825         }
 826     }
 827 
 828     free(usedargv);
 829     free(newargv);
 830 
 831     return(retval);
 832 }
 833 
 834 
 835 int lc_process_var(const char *var, const char *varargs, const char *value, lc_flags_t flags) {
 836     struct lc_varhandler_st *handler = NULL;
 837     const char *lastcomponent_handler = NULL, *lastcomponent_var = NULL;
 838 
 839     lastcomponent_var = strrchr(var, '.');
 840     if (lastcomponent_var == NULL) {
 841         lastcomponent_var = var;
 842     } else {
 843         lastcomponent_var++;
 844     }
 845 
 846     for (handler = varhandlers; handler != NULL; handler = handler->_next) {
 847         /* If either handler->var or var is NULL, skip, unless both are NULL. */
 848         if (handler->var != var && (handler->var == NULL || var == NULL)) {
 849             continue;
 850         }
 851 
 852         /* If both are not-NULL, compare them. */
 853         if (handler->var != NULL) {
 854             /* Wild-card-ish match. */
 855             if (handler->var[0] == '*' && handler->var[1] == '.') {
 856                 /* Only compare the last components */
 857 
 858                 lastcomponent_handler = strrchr(handler->var, '.') + 1; /* strrchr() won't return NULL, because we
	already checked it. */
 859 
 860                 if (strcasecmp(lastcomponent_handler, lastcomponent_var) != 0) {
 861                     continue;
 862                 }
 863             } else if (strcasecmp(handler->var, var) != 0) {
 864                 /* Exact (case-insensitive comparison) failed. */
 865                 continue;
 866             }
 867         }
 868 
 869         if (value == NULL &&
 870             handler->type != LC_VAR_NONE &&
 871             handler->type != LC_VAR_BOOL_BY_EXISTANCE &&
 872             handler->type != LC_VAR_SECTION &&
 873             handler->type != LC_VAR_SECTIONSTART &&
 874             handler->type != LC_VAR_SECTIONEND) {
 875             lc_errno = LC_ERR_BADFORMAT;
 876             break;
 877         }
 878 
 879         return(lc_handle(handler, var, varargs, value, flags));
 880     }
 881 
 882     return(-1);
 883 }
 884 
 885 int lc_register_callback(const char *var, char opt, lc_var_type_t type, int (*callback)(const char *, const char *,
	const char *, const char *, lc_flags_t, void *), void *extra) {
 886     struct lc_varhandler_st *newhandler = NULL;
 887 
 888     newhandler = malloc(sizeof(*newhandler));
 889 
 890     if (newhandler == NULL) {
 891         return(-1);
 892     }
 893 
 894     if (var == NULL) {
 895         newhandler->var = NULL;
 896     } else {
 897         newhandler->var = strdup(var);
 898     }
 899     newhandler->mode = LC_MODE_CALLBACK;
 900     newhandler->type = type;
 901     newhandler->callback = callback;
 902     newhandler->opt = opt;
 903     newhandler->extra = extra;
 904     newhandler->_next = varhandlers;
 905 
 906     varhandlers = newhandler;
 907 
 908     return(0);
 909 }
 910 
 911 int lc_register_var(const char *var, lc_var_type_t type, void *data, char opt) {
 912     struct lc_varhandler_st *newhandler = NULL;
 913 
 914     newhandler = malloc(sizeof(*newhandler));
 915 
 916     if (newhandler == NULL) {
 917         return(-1);
 918     }
 919 
 920     if (var == NULL) {
 921         newhandler->var = NULL;
 922     } else {
 923         newhandler->var = strdup(var);
 924     }
 925     newhandler->mode = LC_MODE_VAR;
 926     newhandler->type = type;
 927     newhandler->data = data;
 928     newhandler->opt = opt;
 929     newhandler->extra = NULL;
 930     newhandler->_next = varhandlers;
 931 
 932     varhandlers = newhandler;
 933 
 934     return(0);
 935 }
 936 
 937 int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type) {
 938     int chkretval = 0;
 939 
 940     switch (type) {
 941         case LC_CONF_SECTION:
 942             chkretval = lc_process_conf_section(appname, pathname);
 943             break;
 944         case LC_CONF_APACHE:
 945             chkretval = lc_process_conf_apache(appname, pathname);
 946             break;
 947         case LC_CONF_COLON:
 948             chkretval = lc_process_conf_colon(appname, pathname);
 949             break;
 950         case LC_CONF_EQUAL:
 951             chkretval = lc_process_conf_equal(appname, pathname);
 952             break;
 953         case LC_CONF_SPACE:
 954             chkretval = lc_process_conf_space(appname, pathname);
 955             break;
 956         case LC_CONF_XML:
 957             chkretval = lc_process_conf_xml(appname, pathname);
 958             break;
 959         default:
 960             chkretval = -1;
 961             lc_errno = LC_ERR_INVDATA;
 962             break;
 963     }
 964 
 965     return(chkretval);
 966 }
 967 
 968 static int lc_process_files(const char *appname, lc_conf_type_t type, const char *extraconfig) {
 969 #ifdef HAVE_GETPWUID
 970     struct passwd *pwinfo = NULL;
 971 #endif
 972     char configfiles[3][13][512] = {{{0}}};
 973     char *configfile = NULL;
 974     char *homedir = NULL;
 975     int configsetidx = 0, configidx = 0;
 976     int chkretval = 0, retval = 0;
 977 
 978     if (extraconfig != NULL) {
 979         snprintf(configfiles[0][0], sizeof(**configfiles) - 1, "%s", extraconfig);
 980     }
 981     snprintf(configfiles[1][0], sizeof(**configfiles) - 1, "/etc/%s.cfg", appname);
 982     snprintf(configfiles[1][1], sizeof(**configfiles) - 1, "/etc/%s.conf", appname);
 983     snprintf(configfiles[1][2], sizeof(**configfiles) - 1, "/etc/%s/%s.cfg", appname, appname);
 984     snprintf(configfiles[1][3], sizeof(**configfiles) - 1, "/etc/%s/%s.conf", appname, appname);
 985     snprintf(configfiles[1][4], sizeof(**configfiles) - 1, "/usr/etc/%s.cfg", appname);
 986     snprintf(configfiles[1][5], sizeof(**configfiles) - 1, "/usr/etc/%s.conf", appname);
 987     snprintf(configfiles[1][6], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.cfg", appname, appname);
 988     snprintf(configfiles[1][7], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.conf", appname, appname);
 989     snprintf(configfiles[1][8], sizeof(**configfiles) - 1, "/usr/local/etc/%s.cfg", appname);
 990     snprintf(configfiles[1][9], sizeof(**configfiles) - 1, "/usr/local/etc/%s.conf", appname);
 991     snprintf(configfiles[1][10], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.cfg", appname, appname);
 992     snprintf(configfiles[1][11], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.conf", appname, appname);
 993     if (getuid() != 0) {
 994         homedir = getenv("HOME");
 995 #ifdef HAVE_GETPWUID
 996         if (homedir == NULL) {
 997             pwinfo = getpwuid(getuid());
 998             if (pwinfo != NULL) {
 999                 homedir = pwinfo->pw_dir;
1000             }
1001         }
1002 #endif
1003         if (homedir != NULL) {
1004             if (strcmp(homedir, "/") != 0 && access(homedir, R_OK|W_OK|X_OK) == 0) {
1005                 snprintf(configfiles[2][0], sizeof(**configfiles) - 1, "%s/.%src", homedir, appname);
1006                 snprintf(configfiles[2][1], sizeof(**configfiles) - 1, "%s/.%s.cfg", homedir, appname);
1007                 snprintf(configfiles[2][2], sizeof(**configfiles) - 1, "%s/.%s.conf", homedir, appname);
1008                 snprintf(configfiles[2][3], sizeof(**configfiles) - 1, "%s/.%s/%s.cfg", homedir, appname, appname);
1009                 snprintf(configfiles[2][4], sizeof(**configfiles) - 1, "%s/.%s/%s.conf", homedir, appname, appname);
1010                 snprintf(configfiles[2][5], sizeof(**configfiles) - 1, "%s/.%s/config", homedir, appname);
1011             }
1012         }
1013     }
1014 
1015     for (configsetidx = 0; configsetidx < 3; configsetidx++) {
1016         for (configidx = 0; configidx < 13; configidx++) {
1017             configfile = configfiles[configsetidx][configidx];
1018             if (configfile[0] == '\0') {
1019                 break;
1020             }
1021             if (access(configfile, R_OK) == 0) {
1022                 chkretval = lc_process_file(appname, configfile, type);
1023                 if (chkretval < 0) {
1024                     retval = -1;
1025                 }
1026                 break;
1027             }
1028         }
1029     }
1030 
1031     return(retval);
1032 }
1033 
1034 void lc_cleanup(void) {
1035     struct lc_varhandler_st *handler = NULL, *next = NULL;
1036 
1037     handler = varhandlers;
1038     while (handler != NULL) {
1039         if (handler->var != NULL) {
1040             free(handler->var);
1041         }
1042 
1043         next = handler->_next;
1044 
1045         free(handler);
1046 
1047         handler = next;
1048     }
1049 
1050     if (lc_err_usererrmsg) {
1051         free((char *) lc_err_usererrmsg);
1052 
1053         lc_err_usererrmsg = NULL;
1054     }
1055 
1056     varhandlers = NULL;
1057 
1058     return;
1059 }
1060 
1061 int lc_process(int argc, char **argv, const char *appname, lc_conf_type_t type, const char *extra) {
1062     int retval = 0, chkretval = 0;
1063 
1064     /* Handle config files. */
1065     chkretval = lc_process_files(appname, type, extra);
1066     if (chkretval < 0) {
1067         retval = -1;
1068     }
1069 
1070     /* Handle environment variables.*/
1071     chkretval = lc_process_environment(appname);
1072     if (chkretval < 0) {
1073         retval = -1;
1074     }
1075 
1076     /* Handle command line arguments */
1077     chkretval = lc_process_cmdline(argc, argv);
1078     if (chkretval < 0) {
1079         retval = -1;
1080     }
1081 
1082     return(retval);
1083 }
1084 
1085 
1086 lc_err_t lc_geterrno(void) {
1087     lc_err_t retval;
1088 
1089     retval = lc_errno;
1090 
1091     return(retval);
1092 }
1093 
1094 void lc_seterrstr(const char *usererrmsg) {
1095     lc_err_usererrmsg = strdup(usererrmsg);
1096 }
1097 
1098 char *lc_geterrstr(void) {
1099     static char retval[512];
1100     const char *errmsg = NULL;
1101 
1102     switch (lc_errno) {
1103         case LC_ERR_NONE:
1104             errmsg = "Success";
1105             break;
1106         case LC_ERR_INVCMD:
1107             errmsg = "Invalid command or option";
1108             break;
1109         case LC_ERR_INVSECTION:
1110             errmsg = "Invalid section";
1111             break;
1112         case LC_ERR_INVDATA:
1113             errmsg = "Invalid application data (internal error)";
1114             break;
1115         case LC_ERR_BADFORMAT:
1116             errmsg = "Bad data specified or incorrect format.";
1117             break;
1118         case LC_ERR_CANTOPEN:
1119             errmsg = "Can't open file.";
1120             break;
1121         case LC_ERR_CALLBACK:
1122             if (lc_err_usererrmsg) {
1123                 errmsg = lc_err_usererrmsg;
1124             } else {
1125                 errmsg = "Error return from application handler.";
1126             }
1127             break;
1128         case LC_ERR_ENOMEM:
1129             errmsg = "Insuffcient memory.";
1130             break;
1131     }
1132 
1133     /*
1134      * This is not part of the switch statement so we will get warnings
1135      * about unhandled enum values.
1136      */
1137     if (errmsg == NULL) {
1138         errmsg = "Unknown error";
1139     }
1140 
1141     if (lc_errfile == NULL) {
1142         snprintf(retval, sizeof(retval), "%s:%i: %s", "<no file>", lc_errline, errmsg);
1143     } else {
1144         snprintf(retval, sizeof(retval), "%s:%i: %s", lc_errfile, lc_errline, errmsg);
1145     }
1146 
1147     retval[sizeof(retval) - 1] = '\0';
1148 
1149     return(retval);
1150 }
4576692 [rkeene@sledge /home/rkeene/devel/libconfig-0.2.5]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2007-01-17 14:05:18