0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include <ndrstandard.h>
0040 #include <time.h>
0041 #include <sys/time.h>
0042 #include <limits.h>
0043 #include <stdlib.h>
0044 #include <string.h>
0045 #include <stdio.h>
0046 #include <utlist.h>
0047 #include <nstdutil.h>
0048 #include <ndrx_ini.h>
0049 #include <inicfg.h>
0050 #include <nerror.h>
0051 #include <sys_unix.h>
0052 #include <errno.h>
0053 #include <ndebug.h>
0054 #include <nstd_int.h>
0055
0056
0057
0058 #define API_ENTRY {_Nunset_error();}
0059
0060
0061
0062
0063
0064
0065
0066 exprivate ndrx_inicfg_t * _ndrx_inicfg_new(int load_global_env);
0067 exprivate int _ndrx_inicfg_reload(ndrx_inicfg_t *cfg, char **section_start_with);
0068 exprivate void cfg_mark_not_loaded(ndrx_inicfg_t *cfg, char *resource);
0069 exprivate void cfg_remove_not_marked(ndrx_inicfg_t *cfg);
0070 exprivate ndrx_inicfg_section_t * cfg_section_new(ndrx_inicfg_section_t **sections_h, char *section);
0071 exprivate ndrx_inicfg_section_t * cfg_section_get(ndrx_inicfg_section_t **sections_h, char *section);
0072 exprivate int handler(void* cf_ptr, void *vsection_start_with, void *cfg_ptr,
0073 const char* section, const char* name, const char* value);
0074 exprivate int _ndrx_inicfg_load_single_file(ndrx_inicfg_t *cfg,
0075 char *resource, char *fullname, char **section_start_with);
0076 exprivate ndrx_inicfg_file_t* cfg_single_file_get(ndrx_inicfg_t *cfg, char *fullname);
0077 exprivate int _ndrx_inicfg_update_single_file(ndrx_inicfg_t *cfg,
0078 char *resource, char *fullname, char **section_start_with);
0079 exprivate int _ndrx_inicfg_add(ndrx_inicfg_t *cfg, char *resource, char **section_start_with);
0080 exprivate int _ndrx_keyval_hash_add(ndrx_inicfg_section_keyval_t **h,
0081 ndrx_inicfg_section_keyval_t *src);
0082 exprivate ndrx_inicfg_section_keyval_t * _ndrx_keyval_hash_get(
0083 ndrx_inicfg_section_keyval_t *h, char *key);
0084 exprivate void _ndrx_keyval_hash_free(ndrx_inicfg_section_keyval_t *h);
0085 exprivate int _ndrx_inicfg_resolve(ndrx_inicfg_t *cfg, char **resources, char *section,
0086 ndrx_inicfg_section_keyval_t **out);
0087 exprivate int _ndrx_inicfg_iterate(ndrx_inicfg_t *cfg,
0088 char **resources,
0089 char **section_start_with,
0090 ndrx_inicfg_section_t **out);
0091 exprivate void _ndrx_inicfg_sections_free(ndrx_inicfg_section_t *sections);
0092 exprivate void _ndrx_inicfg_file_free(ndrx_inicfg_t *cfg, ndrx_inicfg_file_t *cfgfile);
0093 exprivate void _ndrx_inicfg_free(ndrx_inicfg_t *cfg);
0094
0095
0096
0097
0098
0099 exprivate ndrx_inicfg_t * _ndrx_inicfg_new(int load_global_env)
0100 {
0101 ndrx_inicfg_t *ret = NULL;
0102
0103 if (NULL==(ret = NDRX_CALLOC(1, sizeof(ndrx_inicfg_t))))
0104 {
0105 _Nset_error_fmt(NEMALLOC, "Failed to malloc ndrx_inicfg_t: %s",
0106 strerror(errno));
0107 #ifdef INICFG_ENABLE_DEBUG
0108 fprintf(stderr, "Failed to alloc: ndrx_inicfg_t!\n");
0109 #endif
0110 goto out;
0111 }
0112
0113 ret->load_global_env = load_global_env;
0114
0115 NDRX_LOG_EARLY(log_debug, "%s: load_global_env: %d", __func__, load_global_env);
0116
0117 out:
0118 #ifdef INICFG_ENABLE_DEBUG
0119 fprintf(stderr, "ndrx_inicfg_new returns %p\n", ret);
0120 #endif
0121 return ret;
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131 exprivate int _ndrx_inicfg_reload(ndrx_inicfg_t *cfg, char **section_start_with)
0132 {
0133 int i;
0134 int ret = EXSUCCEED;
0135 char fn[] = "_ndrx_inicfg_reload";
0136 string_hash_t * r, *rt;
0137
0138
0139 EXHASH_ITER(hh, cfg->resource_hash, r, rt)
0140 {
0141 #ifdef INICFG_ENABLE_DEBUG
0142 fprintf(stderr, "%s: Reloading [%s]\n", fn, r->str);
0143 #endif
0144 if (EXSUCCEED!=_ndrx_inicfg_add(cfg, r->str, section_start_with))
0145 {
0146 EXFAIL_OUT(ret);
0147 }
0148 }
0149
0150 out:
0151
0152 #ifdef INICFG_ENABLE_DEBUG
0153 fprintf(stderr, "%s: returns %d\n", fn, ret);
0154 #endif
0155 return ret;
0156 }
0157
0158
0159
0160
0161
0162
0163
0164 exprivate void cfg_mark_not_loaded(ndrx_inicfg_t *cfg, char *resource)
0165 {
0166 ndrx_inicfg_file_t *f, *ftmp;
0167
0168 EXHASH_ITER(hh, cfg->cfgfile, f, ftmp)
0169 {
0170 if (0==strcmp(f->resource, resource))
0171 {
0172 #ifdef INICFG_ENABLE_DEBUG
0173 fprintf(stderr, "Unrefreshing resource [%s] file [%s]\n",
0174 f->resource, f->fullname);
0175 #endif
0176
0177 f->refreshed = EXFALSE;
0178 }
0179 }
0180 }
0181
0182
0183
0184
0185
0186
0187 exprivate void cfg_remove_not_marked(ndrx_inicfg_t *cfg)
0188 {
0189 ndrx_inicfg_file_t *f, *ftmp;
0190
0191 EXHASH_ITER(hh, cfg->cfgfile, f, ftmp)
0192 {
0193 if (!f->refreshed)
0194 {
0195 #ifdef INICFG_ENABLE_DEBUG
0196 fprintf(stderr, "Resource [%s]/file [%s] not refreshed - removing from mem\n",
0197 f->resource, f->fullname);
0198 #endif
0199 ndrx_inicfg_file_free(cfg, f);
0200 }
0201 }
0202 }
0203
0204
0205
0206
0207
0208
0209 exprivate ndrx_inicfg_section_t * cfg_section_new(ndrx_inicfg_section_t **sections_h, char *section)
0210 {
0211 ndrx_inicfg_section_t * ret = NDRX_CALLOC(1, sizeof(ndrx_inicfg_section_t));
0212
0213 if (NULL==ret)
0214 {
0215 int err = errno;
0216 _Nset_error_fmt(NEMALLOC, "Failed to malloc ndrx_inicfg_section_t: %s", strerror(err));
0217 goto out;
0218 }
0219
0220 if (NULL==(ret->section=strdup(section)))
0221 {
0222 int err = errno;
0223 _Nset_error_fmt(NEMALLOC, "Failed to malloc ndrx_inicfg_section_t: "
0224 "(section) %s", strerror(err));
0225 ret=NULL;
0226 goto out;
0227 }
0228
0229 #ifdef INICFG_ENABLE_DEBUG
0230 fprintf(stderr, "Adding new section [%s]\n", ret->section);
0231 #endif
0232
0233 EXHASH_ADD_KEYPTR(hh, (*sections_h), ret->section,
0234 strlen(ret->section), ret);
0235
0236 out:
0237 return ret;
0238 }
0239
0240
0241
0242
0243
0244
0245 exprivate ndrx_inicfg_section_t * cfg_section_get(ndrx_inicfg_section_t **sections_h, char *section)
0246 {
0247 ndrx_inicfg_section_t * ret = NULL;
0248
0249 EXHASH_FIND_STR( (*sections_h), section, ret);
0250
0251 if (NULL==ret)
0252 {
0253 ret = cfg_section_new(sections_h, section);
0254 }
0255
0256 return ret;
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 exprivate int handler(void* cf_ptr, void *vsection_start_with, void *cfg_ptr,
0268 const char* section, const char* name, const char* value)
0269 {
0270 int ret = 1;
0271 int value_len;
0272 ndrx_inicfg_file_t *cf = (ndrx_inicfg_file_t*)cf_ptr;
0273 char **section_start_with = (char **)vsection_start_with;
0274 int needed = EXTRUE;
0275
0276 ndrx_inicfg_section_t *mem_section = NULL;
0277 ndrx_inicfg_section_keyval_t * mem_value = NULL;
0278
0279
0280 #ifdef INICFG_ENABLE_DEBUG
0281 fprintf(stderr, "Handler got: resource [%s]/file [%s] section [%s]"
0282 " name [%s] value [%s] cf %p\n",
0283 cf->resource, cf->fullname, section, name, value, cf);
0284 #endif
0285
0286 if (NULL!=section_start_with)
0287 {
0288 needed = EXFALSE;
0289 if (NULL==section_start_with)
0290 {
0291 needed = EXTRUE;
0292 }
0293 else while (NULL!=*section_start_with)
0294 {
0295 int len = NDRX_MIN(strlen(*section_start_with), strlen(section));
0296
0297 if (0 == strncmp(*section_start_with, section, len))
0298 {
0299 needed = EXTRUE;
0300 break;
0301 }
0302 section_start_with++;
0303 }
0304 }
0305
0306
0307 if (!needed)
0308 {
0309 #ifdef INICFG_ENABLE_DEBUG
0310 fprintf(stderr, "Section not needed - skipping\n");
0311 #endif
0312 goto out;
0313 }
0314
0315
0316 mem_section = cfg_section_get(&(cf->sections), (char *)section);
0317 if (NULL==mem_section)
0318 {
0319 ret = 0;
0320 goto out;
0321 }
0322
0323 if (NULL!=_ndrx_keyval_hash_get(mem_section->values, (char *)name))
0324 {
0325
0326 ret=1;
0327 goto out;
0328 }
0329
0330 mem_value = NDRX_CALLOC(1, sizeof(ndrx_inicfg_section_keyval_t));
0331
0332 if (NULL==mem_value)
0333 {
0334 int err = errno;
0335 _Nset_error_fmt(NEMALLOC, "Failed to malloc ndrx_inicfg_section_t: %s", strerror(err));
0336 ret = 0;
0337 goto out;
0338 }
0339
0340 if (NULL==(mem_value->section = NDRX_STRDUP(section)))
0341 {
0342 int err = errno;
0343 _Nset_error_fmt(NEMALLOC, "Failed to malloc mem_value->section: %s", strerror(err));
0344 ret = 0;
0345 goto out;
0346 }
0347
0348
0349 if (NULL==(mem_value->key = NDRX_STRDUP(name)))
0350 {
0351 int err = errno;
0352 _Nset_error_fmt(NEMALLOC, "Failed to malloc mem_value->key: %s", strerror(err));
0353 ret = 0;
0354 goto out;
0355 }
0356
0357 if (NULL==(mem_value->val = NDRX_STRDUP(value)))
0358 {
0359 int err = errno;
0360 _Nset_error_fmt(NEMALLOC, "Failed to malloc mem_value->val: %s", strerror(err));
0361 ret = 0;
0362 goto out;
0363 }
0364
0365 value_len = strlen(mem_value->val) + PATH_MAX + 1;
0366
0367 if (NULL==(mem_value->val = NDRX_REALLOC(mem_value->val, value_len)))
0368 {
0369 int err = errno;
0370 _Nset_error_fmt(NEMALLOC, "Failed to malloc mem_value->val (new size: %d): %s",
0371 value_len, strerror(err));
0372 ret = 0;
0373 goto out;
0374 }
0375
0376 ndrx_str_env_subs_len(mem_value->val, value_len);
0377 value_len = strlen(mem_value->val) + 1;
0378
0379
0380 if (NULL==(mem_value->val = NDRX_REALLOC(mem_value->val, value_len)))
0381 {
0382 int err = errno;
0383 _Nset_error_fmt(NEMALLOC, "Failed to truncate mem_value->val to %d: %s",
0384 value_len, strerror(err));
0385
0386 ret = 0;
0387 goto out;
0388 }
0389
0390
0391
0392
0393
0394
0395 EXHASH_ADD_KEYPTR(hh, mem_section->values, mem_value->key,
0396
0397 strlen(mem_value->key)+1, mem_value);
0398
0399 #ifdef INICFG_ENABLE_DEBUG
0400 fprintf(stderr, "section/key/value added OK\n");
0401 #endif
0402
0403 out:
0404 return ret;
0405 }
0406
0407
0408
0409
0410
0411
0412
0413
0414 exprivate int _ndrx_inicfg_load_single_file(ndrx_inicfg_t *cfg,
0415 char *resource, char *fullname, char **section_start_with)
0416 {
0417 ndrx_inicfg_file_t *cf = NULL;
0418 int ret = EXSUCCEED;
0419 char fn[] = "_ndrx_inicfg_load_single_file";
0420
0421 if (NULL==(cf = NDRX_CALLOC(1, sizeof(ndrx_inicfg_file_t))))
0422 {
0423 _Nset_error_fmt(NEMALLOC, "%s: Failed to malloc ndrx_inicfg_file_t: %s",
0424 fn, strerror(errno));
0425 EXFAIL_OUT(ret);
0426 }
0427
0428
0429 NDRX_STRCPY_SAFE(cf->resource, resource);
0430
0431 NDRX_STRCPY_SAFE(cf->fullname, fullname);
0432
0433 cf->refreshed = EXTRUE;
0434
0435 if (EXSUCCEED!=stat(fullname, &cf->attr))
0436 {
0437 _Nset_error_fmt(NEUNIX, "%s: stat() failed for [%s]:%s",
0438 fn, fullname, strerror(errno));
0439 EXFAIL_OUT(ret);
0440 }
0441
0442 #ifdef INICFG_ENABLE_DEBUG
0443 fprintf(stderr, "Opened config file %p\n", cf);
0444 #endif
0445
0446
0447 if (EXSUCCEED!=(ret=ndrx_ini_parse(fullname, handler, (void *)cf,
0448 (void *)section_start_with, (void *)cfg)))
0449 {
0450 _Nset_error_fmt(NEINVALINI, "%s: Invalid ini file: [%s] error on line: %d",
0451 fn, fullname, ret);
0452 EXFAIL_OUT(ret);
0453 }
0454
0455 EXHASH_ADD_STR( cfg->cfgfile, fullname, cf );
0456
0457 out:
0458 return ret;
0459 }
0460
0461
0462
0463
0464
0465
0466
0467 exprivate ndrx_inicfg_file_t* cfg_single_file_get(ndrx_inicfg_t *cfg, char *fullname)
0468 {
0469 ndrx_inicfg_file_t * ret = NULL;
0470
0471 EXHASH_FIND_STR( cfg->cfgfile, fullname, ret);
0472
0473 return ret;
0474 }
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 exprivate int _ndrx_inicfg_update_single_file(ndrx_inicfg_t *cfg,
0486 char *resource, char *fullname, char **section_start_with)
0487 {
0488 int ret = EXSUCCEED;
0489 struct stat attr;
0490 char fn[] = "_ndrx_inicfg_update_single_file";
0491 int ferr = 0;
0492
0493 ndrx_inicfg_file_t *cf = cfg_single_file_get(cfg, fullname);
0494
0495 #ifdef INICFG_ENABLE_DEBUG
0496 fprintf(stderr, "%s: enter resource [%s]/file [%s]\n",
0497 fn, resource, fullname);
0498 #endif
0499
0500 if (EXSUCCEED!=stat(fullname, &attr))
0501 {
0502
0503 ferr = errno;
0504 }
0505
0506 #ifdef INICFG_ENABLE_DEBUG
0507 if (NULL!=cf)
0508 {
0509 fprintf(stderr, "%s: tstamp: cur: %ld vs prev: %ld\n",
0510 fn, attr.st_mtime, cf->attr.st_mtime);
0511 }
0512 #endif
0513
0514 if (NULL!=cf && EXSUCCEED==ferr &&
0515 0!=memcmp(&(attr.st_mtime), &(cf->attr.st_mtime), sizeof(attr.st_mtime)))
0516 {
0517 #ifdef INICFG_ENABLE_DEBUG
0518 fprintf(stderr, "%s: [%s]/file [%s] changed - reload\n",
0519 fn, resource, fullname);
0520 #endif
0521
0522 ndrx_inicfg_file_free(cfg, cf);
0523 if (EXSUCCEED!=_ndrx_inicfg_load_single_file(cfg, resource, fullname,
0524 section_start_with))
0525 {
0526 EXFAIL_OUT(ret);
0527 }
0528 }
0529 else if (NULL!=cf && EXSUCCEED==ferr)
0530 {
0531
0532 #ifdef INICFG_ENABLE_DEBUG
0533 fprintf(stderr, "%s: [%s]/file [%s] not-changed - do nothing\n",
0534 fn, resource, fullname);
0535 #endif
0536 cf->refreshed = EXTRUE;
0537 goto out;
0538 }
0539 else if (NULL==cf && EXSUCCEED==ferr)
0540 {
0541 #ifdef INICFG_ENABLE_DEBUG
0542 fprintf(stderr, "%s: [%s]/file [%s] config does not exists, "
0543 "but file exists - load\n",
0544 fn, resource, fullname);
0545 #endif
0546
0547 if (EXSUCCEED!=_ndrx_inicfg_load_single_file(cfg, resource, fullname,
0548 section_start_with))
0549 {
0550 EXFAIL_OUT(ret);
0551 }
0552 }
0553 else if (NULL!=cf && EXSUCCEED!=ferr)
0554 {
0555
0556 #ifdef INICFG_ENABLE_DEBUG
0557 fprintf(stderr, "%s: [%s]/file [%s] Config exits, "
0558 "file not, kill the config\n",
0559 fn, resource, fullname);
0560 #endif
0561 ndrx_inicfg_file_free(cfg, cf);
0562 }
0563
0564 out:
0565 return ret;
0566 }
0567
0568
0569
0570
0571
0572
0573
0574
0575 exprivate int _ndrx_inicfg_add(ndrx_inicfg_t *cfg, char *resource, char **section_start_with)
0576 {
0577 int ret = EXSUCCEED;
0578 char fn[] = "_ndrx_inicfg_add";
0579 cfg_mark_not_loaded(cfg, resource);
0580
0581
0582
0583
0584 if (ndrx_file_regular(resource))
0585 {
0586 #ifdef INICFG_ENABLE_DEBUG
0587 fprintf(stderr, "Resource: [%s] is regular file\n", resource);
0588 #endif
0589 if (EXSUCCEED!=_ndrx_inicfg_update_single_file(cfg, resource,
0590 resource, section_start_with))
0591 {
0592 EXFAIL_OUT(ret);
0593 }
0594 }
0595 else
0596 {
0597 string_list_t* flist = NULL;
0598 string_list_t* elt = NULL;
0599
0600 int return_status = EXSUCCEED;
0601
0602 #ifdef INICFG_ENABLE_DEBUG
0603 fprintf(stderr, "Resource: [%s] seems like directory "
0604 "(checking for *.ini, *.cfg, *.conf, *.config)\n", resource);
0605 #endif
0606
0607 if (NULL!=(flist=ndrx_sys_folder_list(resource, &return_status)))
0608 {
0609 LL_FOREACH(flist,elt)
0610 {
0611 int len = strlen(elt->qname);
0612 if ( (len >=4 && 0==strcmp(elt->qname+len-4, ".ini")) ||
0613 (len >=4 && 0==strcmp(elt->qname+len-4, ".cfg")) ||
0614 (len >=5 && 0==strcmp(elt->qname+len-5, ".conf")) ||
0615 (len >=7 && 0==strcmp(elt->qname+len-7, ".config"))
0616 )
0617 {
0618 char tmp[PATH_MAX+1];
0619 snprintf(tmp, sizeof(tmp), "%s/%s", resource, elt->qname);
0620
0621 if (EXSUCCEED!=_ndrx_inicfg_update_single_file(cfg, resource,
0622 tmp, section_start_with))
0623 {
0624 EXFAIL_OUT(ret);
0625 }
0626 }
0627 }
0628 }
0629
0630 ndrx_string_list_free(flist);
0631 }
0632
0633 cfg_remove_not_marked(cfg);
0634
0635
0636
0637
0638 if (NULL==ndrx_string_hash_get(cfg->resource_hash, resource))
0639 {
0640 #ifdef INICFG_ENABLE_DEBUG
0641 fprintf(stderr, "Registering resource [%s]\n", resource);
0642 #endif
0643 if (NULL==ndrx_string_hash_add(&(cfg->resource_hash), resource))
0644 {
0645 _Nset_error_fmt(NEMALLOC, "%s: ndrx_string_hash_add - malloc failed", fn);
0646 EXFAIL_OUT(ret);
0647 }
0648 }
0649
0650 out:
0651 return ret;
0652 }
0653
0654
0655
0656
0657
0658
0659
0660 exprivate int _ndrx_keyval_hash_add(ndrx_inicfg_section_keyval_t **h,
0661 ndrx_inicfg_section_keyval_t *src)
0662 {
0663 int ret = EXSUCCEED;
0664 char fn[]="_ndrx_keyval_hash_add";
0665 ndrx_inicfg_section_keyval_t * tmp = NDRX_CALLOC(1, sizeof(ndrx_inicfg_section_keyval_t));
0666
0667 if (NULL==tmp)
0668 {
0669 #ifdef INICFG_ENABLE_DEBUG
0670 fprintf(stderr, "alloc of ndrx_inicfg_section_keyval_t (%d) failed\n",
0671 (int)sizeof(ndrx_inicfg_section_keyval_t));
0672 #endif
0673 EXFAIL_OUT(ret);
0674 }
0675
0676 if (NULL==(tmp->key = strdup(src->key)))
0677 {
0678 #ifdef INICFG_ENABLE_DEBUG
0679 fprintf(stderr, "strdup() failed: %s\n", strerror(errno));
0680 _Nset_error_fmt(NEMALLOC, "%s: malloc failed", fn);
0681 #endif
0682 EXFAIL_OUT(ret);
0683 }
0684
0685 if (NULL==(tmp->val = strdup(src->val)))
0686 {
0687 #ifdef INICFG_ENABLE_DEBUG
0688 fprintf(stderr, "strdup() failed: %s\n", strerror(errno));
0689 _Nset_error_fmt(NEMALLOC, "%s: malloc failed", fn);
0690
0691 #endif
0692 EXFAIL_OUT(ret);
0693 }
0694
0695 if (NULL==(tmp->section = strdup(src->section)))
0696 {
0697 #ifdef INICFG_ENABLE_DEBUG
0698 fprintf(stderr, "strdup() failed: %s\n", strerror(errno));
0699 _Nset_error_fmt(NEMALLOC, "%s: malloc failed", fn);
0700 #endif
0701 EXFAIL_OUT(ret);
0702 }
0703
0704
0705 EXHASH_ADD_KEYPTR( hh, (*h), tmp->key, strlen(tmp->key), tmp );
0706
0707 out:
0708 return ret;
0709 }
0710
0711
0712
0713
0714
0715
0716
0717 exprivate ndrx_inicfg_section_keyval_t * _ndrx_keyval_hash_get(
0718 ndrx_inicfg_section_keyval_t *h, char *key)
0719 {
0720 ndrx_inicfg_section_keyval_t * r = NULL;
0721
0722 EXHASH_FIND_STR( h, key, r);
0723
0724 return r;
0725 }
0726
0727
0728
0729
0730
0731
0732 exprivate void _ndrx_keyval_hash_free(ndrx_inicfg_section_keyval_t *h)
0733 {
0734 ndrx_inicfg_section_keyval_t * r=NULL, *rt=NULL;
0735
0736 EXHASH_ITER(hh, h, r, rt)
0737 {
0738 EXHASH_DEL(h, r);
0739 NDRX_FREE(r->key);
0740 NDRX_FREE(r->val);
0741 NDRX_FREE(r->section);
0742 NDRX_FREE(r);
0743 }
0744 }
0745
0746
0747
0748
0749
0750
0751
0752
0753 exprivate int _ndrx_inicfg_resolve(ndrx_inicfg_t *cfg, char **resources, char *section,
0754 ndrx_inicfg_section_keyval_t **out)
0755 {
0756 int i;
0757 int found;
0758 int ret = EXSUCCEED;
0759 char fn[] = "_ndrx_inicfg_resolve";
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771 ndrx_inicfg_file_t * config_file=NULL, *config_file_temp=NULL;
0772 ndrx_inicfg_section_t *section_hash;
0773
0774 #ifdef INICFG_ENABLE_DEBUG
0775 fprintf(stderr, "%s: lookup section [%s]\n", fn, section);
0776 #endif
0777
0778
0779 EXHASH_ITER(hh, cfg->cfgfile, config_file, config_file_temp)
0780 {
0781 found = EXFALSE;
0782 i = 0;
0783
0784 #ifdef INICFG_ENABLE_DEBUG
0785 fprintf(stderr, "%s: Checking [%s]...\n", fn, config_file->fullname);
0786 #endif
0787
0788
0789 if (NULL==resources)
0790 {
0791 found = EXTRUE;
0792 #ifdef INICFG_ENABLE_DEBUG
0793 fprintf(stderr, "%s: Checking [%s] - accept any\n", fn, config_file->fullname);
0794 #endif
0795 }
0796 else
0797 {
0798 while(NULL!=resources[i])
0799 {
0800 if (0==strcmp(config_file->resource, resources[i]))
0801 {
0802 found = EXTRUE;
0803 break;
0804 }
0805 i++;
0806 }
0807 }
0808
0809 if (found)
0810 {
0811 #ifdef INICFG_ENABLE_DEBUG
0812 fprintf(stderr, "%s: Checking [%s] - accepted\n", fn, config_file->fullname);
0813 #endif
0814
0815 #ifdef INICFG_ENABLE_DEBUG
0816 fprintf(stderr, "%s: searching for section [%s] in %p\n",
0817 fn, section, config_file->sections);
0818 #endif
0819 EXHASH_FIND_STR(config_file->sections, section, section_hash);
0820 if (NULL!=section_hash)
0821 {
0822
0823 #ifdef INICFG_ENABLE_DEBUG
0824 fprintf(stderr, "%s: got section...\n", fn);
0825 #endif
0826 ndrx_inicfg_section_keyval_t *vals = NULL, *vals_tmp = NULL;
0827
0828 EXHASH_ITER(hh, (section_hash->values), vals, vals_tmp)
0829 {
0830 ndrx_inicfg_section_keyval_t *existing = NULL;
0831 #ifdef INICFG_ENABLE_DEBUG
0832 fprintf(stderr, "%s: got section[%s]/key[%s]/val[%s]\n", fn,
0833 vals->section, vals->key, vals->val);
0834 #endif
0835 existing = _ndrx_keyval_hash_get((*out), vals->key);
0836
0837 if (NULL==existing ||
0838 ndrx_nr_chars(vals->section, NDRX_INICFG_SUBSECT_SPERATOR) >
0839 ndrx_nr_chars(existing->section, NDRX_INICFG_SUBSECT_SPERATOR))
0840 {
0841 if (EXSUCCEED!=_ndrx_keyval_hash_add(out, vals))
0842 {
0843 EXFAIL_OUT(ret);
0844 }
0845 }
0846 }
0847 }
0848 }
0849 else
0850 {
0851 #ifdef INICFG_ENABLE_DEBUG
0852 fprintf(stderr, "%s: Checking [%s] - NOT accepted\n", fn, config_file->fullname);
0853 #endif
0854 }
0855 }
0856
0857
0858 out:
0859 #ifdef INICFG_ENABLE_DEBUG
0860 fprintf(stderr, "%s: returns %p\n", fn, *out);
0861 #endif
0862
0863 return ret;
0864 }
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879 expublic int ndrx_inicfg_get_subsect_int(ndrx_inicfg_t *cfg,
0880 char **resources, char *section, ndrx_inicfg_section_keyval_t **out)
0881 {
0882 int ret = EXSUCCEED;
0883 char *tmp = NULL;
0884 char *p;
0885
0886 if (NULL==cfg)
0887 {
0888 _Nset_error_fmt(NEINVAL, "%s: `cfg' cannot be NULL!", __func__);
0889 EXFAIL_OUT(ret);
0890 }
0891
0892 if (NULL==section)
0893 {
0894 _Nset_error_fmt(NEINVAL, "%s: `section' cannot be NULL!", __func__);
0895 EXFAIL_OUT(ret);
0896 }
0897
0898 tmp = strdup(section);
0899
0900 if (NULL==tmp)
0901 {
0902 _Nset_error_fmt(NEMALLOC, "%s: malloc failed", __func__);
0903 EXFAIL_OUT(ret);
0904 }
0905
0906 while (EXEOS!=tmp[0])
0907 {
0908 if (EXSUCCEED!=_ndrx_inicfg_resolve(cfg, resources, tmp, out))
0909 {
0910 EXFAIL_OUT(ret);
0911 }
0912 p = strrchr(tmp, NDRX_INICFG_SUBSECT_SPERATOR);
0913
0914 if (NULL!=p)
0915 {
0916 *p = EXEOS;
0917 }
0918 else
0919 {
0920 break;
0921 }
0922 }
0923
0924 out:
0925 if (NULL!=tmp)
0926 {
0927 NDRX_FREE(tmp);
0928 }
0929
0930 return ret;
0931 }
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941 exprivate int _ndrx_inicfg_iterate(ndrx_inicfg_t *cfg,
0942 char **resources,
0943 char **section_start_with,
0944 ndrx_inicfg_section_t **out)
0945 {
0946 int i;
0947 int found;
0948 int ret = EXSUCCEED;
0949 char fn[] = "_ndrx_inicfg_iterate";
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961 ndrx_inicfg_file_t * config_file=NULL, *config_file_temp=NULL;
0962 ndrx_inicfg_section_t *section = NULL, *section_temp=NULL;
0963 ndrx_inicfg_section_t *section_work = NULL;
0964
0965 #ifdef INICFG_ENABLE_DEBUG
0966 fprintf(stderr, "%s: enter\n", fn);
0967 #endif
0968
0969
0970 EXHASH_ITER(hh, cfg->cfgfile, config_file, config_file_temp)
0971 {
0972 found = EXFALSE;
0973 i = 0;
0974
0975
0976 if (NULL==resources)
0977 {
0978 found = EXTRUE;
0979 }
0980 else
0981 {
0982 while(NULL!=resources[i])
0983 {
0984 if (0==strcmp(config_file->resource, resources[i]))
0985 {
0986 found = EXTRUE;
0987 break;
0988 }
0989 i++;
0990 }
0991 }
0992
0993 #ifdef INICFG_ENABLE_DEBUG
0994 fprintf(stderr, "%s: resource [%s] %s for lookup\n", fn, config_file->resource,
0995 found?"ok":"not ok");
0996 #endif
0997
0998 if (found)
0999 {
1000
1001
1002
1003
1004
1005
1006 EXHASH_ITER(hh, (config_file->sections), section, section_temp)
1007 {
1008 int len;
1009
1010 found = EXFALSE;
1011 i = 0;
1012
1013 if (NULL==section_start_with)
1014 {
1015 found = EXTRUE;
1016 }
1017 else while (NULL!=section_start_with[i])
1018 {
1019 len = NDRX_MIN(strlen(section->section), strlen(section_start_with[i]));
1020 if (0==strncmp(section->section, section_start_with[i], len))
1021 {
1022 found = EXTRUE;
1023 break;
1024 }
1025 i++;
1026 }
1027
1028 #ifdef INICFG_ENABLE_DEBUG
1029 fprintf(stderr, "%s: section [%s] %s for lookup\n", fn, section->section,
1030 found?"ok":"not ok");
1031 #endif
1032 if (found)
1033 {
1034
1035 if (NULL==(section_work=cfg_section_get(out, section->section)))
1036 {
1037 EXFAIL_OUT(ret);
1038 }
1039
1040 ndrx_inicfg_section_keyval_t *vals = NULL, *vals_tmp = NULL;
1041
1042 EXHASH_ITER(hh, (section->values), vals, vals_tmp)
1043 {
1044 if (NULL==_ndrx_keyval_hash_get((section_work->values), vals->key))
1045 {
1046 if (EXSUCCEED!=_ndrx_keyval_hash_add(&(section_work->values), vals))
1047 {
1048 EXFAIL_OUT(ret);
1049 }
1050 }
1051 }
1052 }
1053 }
1054 }
1055 }
1056
1057
1058 out:
1059
1060 #ifdef INICFG_ENABLE_DEBUG
1061 fprintf(stderr, "%s: returns %p", fn, *out);
1062 #endif
1063
1064 return ret;
1065 }
1066
1067
1068
1069
1070
1071 exprivate void _ndrx_inicfg_sections_free(ndrx_inicfg_section_t *sections)
1072 {
1073 char fn[] = "_ndrx_inicfg_sections_free";
1074 ndrx_inicfg_section_t *section=NULL, *section_temp=NULL;
1075 #ifdef INICFG_ENABLE_DEBUG
1076 fprintf(stderr, "%s: enter %p\n", fn, sections);
1077 #endif
1078
1079
1080 EXHASH_ITER(hh, sections, section, section_temp)
1081 {
1082 EXHASH_DEL(sections, section);
1083 ndrx_keyval_hash_free(section->values);
1084 NDRX_FREE(section->section);
1085 NDRX_FREE(section);
1086 }
1087 }
1088
1089
1090
1091
1092
1093
1094
1095 exprivate void _ndrx_inicfg_file_free(ndrx_inicfg_t *cfg, ndrx_inicfg_file_t *cfgfile)
1096 {
1097 char fn[] = "_ndrx_inicfg_file_free";
1098 ndrx_inicfg_section_t *section=NULL, *section_temp=NULL;
1099
1100 #ifdef INICFG_ENABLE_DEBUG
1101 fprintf(stderr, "%s: enter cfg = %p cfgfile = %p\n", fn, cfg, cfgfile);
1102 #endif
1103
1104 EXHASH_DEL(cfg->cfgfile, cfgfile);
1105
1106 ndrx_inicfg_sections_free(cfgfile->sections);
1107
1108 NDRX_FREE(cfgfile);
1109 }
1110
1111
1112
1113
1114
1115
1116 exprivate void _ndrx_inicfg_free(ndrx_inicfg_t *cfg)
1117 {
1118 char fn[]="_ndrx_inicfg_free";
1119 ndrx_inicfg_file_t *cf=NULL, *cf_tmp=NULL;
1120
1121 #ifdef INICFG_ENABLE_DEBUG
1122 fprintf(stderr, "%s: enter cfg = %p\n", fn, cfg);
1123 #endif
1124
1125 EXHASH_ITER(hh, cfg->cfgfile, cf, cf_tmp)
1126 {
1127 _ndrx_inicfg_file_free(cfg, cf);
1128 }
1129
1130 ndrx_string_hash_free(cfg->resource_hash);
1131
1132 NDRX_FREE(cfg);
1133 }
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145 expublic int ndrx_inicfg_reload(ndrx_inicfg_t *cfg, char **section_start_with)
1146 {
1147 API_ENTRY;
1148 return _ndrx_inicfg_reload(cfg, section_start_with);
1149 }
1150
1151
1152
1153
1154
1155 expublic ndrx_inicfg_t * ndrx_inicfg_new(void)
1156 {
1157 API_ENTRY;
1158 return _ndrx_inicfg_new(EXFALSE);
1159 }
1160
1161
1162
1163
1164
1165 expublic ndrx_inicfg_t * ndrx_inicfg_new2(int load_global_env)
1166 {
1167 API_ENTRY;
1168 return _ndrx_inicfg_new(load_global_env);
1169 }
1170
1171
1172
1173
1174 expublic int ndrx_inicfg_load_single_file(ndrx_inicfg_t *cfg,
1175 char *resource, char *fullname, char **section_start_with)
1176 {
1177 API_ENTRY;
1178
1179 return _ndrx_inicfg_load_single_file(cfg, resource, fullname, section_start_with);
1180
1181 }
1182
1183
1184
1185
1186 expublic int ndrx_inicfg_update_single_file(ndrx_inicfg_t *cfg,
1187 char *resource, char *fullname, char **section_start_with)
1188 {
1189 API_ENTRY;
1190 return _ndrx_inicfg_update_single_file(cfg, resource, fullname, section_start_with);
1191 }
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201 expublic int ndrx_inicfg_add(ndrx_inicfg_t *cfg, char *resource, char **section_start_with)
1202 {
1203 API_ENTRY;
1204 return _ndrx_inicfg_add(cfg, resource, section_start_with);
1205 }
1206
1207
1208
1209
1210
1211
1212
1213 expublic int ndrx_keyval_hash_add(ndrx_inicfg_section_keyval_t **h,
1214 ndrx_inicfg_section_keyval_t *src)
1215 {
1216 API_ENTRY;
1217 return ndrx_keyval_hash_add(h, src);
1218 }
1219
1220
1221
1222
1223
1224
1225
1226 expublic ndrx_inicfg_section_keyval_t * ndrx_keyval_hash_get(
1227 ndrx_inicfg_section_keyval_t *h, char *key)
1228 {
1229 API_ENTRY;
1230 return _ndrx_keyval_hash_get(h, key);
1231 }
1232
1233
1234
1235
1236
1237
1238 expublic void ndrx_keyval_hash_free(ndrx_inicfg_section_keyval_t *h)
1239 {
1240 API_ENTRY;
1241 _ndrx_keyval_hash_free(h);
1242 }
1243
1244
1245
1246
1247
1248
1249
1250
1251 expublic int ndrx_inicfg_resolve(ndrx_inicfg_t *cfg, char **resources, char *section,
1252 ndrx_inicfg_section_keyval_t **out)
1253 {
1254 API_ENTRY;
1255 return _ndrx_inicfg_resolve(cfg, resources, section, out);
1256 }
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271 expublic int ndrx_inicfg_get_subsect(ndrx_inicfg_t *cfg,
1272 char **resources, char *section, ndrx_inicfg_section_keyval_t **out)
1273 {
1274 API_ENTRY;
1275
1276 return ndrx_inicfg_get_subsect_int(cfg, resources, section, out);
1277 }
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287 expublic int ndrx_inicfg_iterate(ndrx_inicfg_t *cfg,
1288 char **resources,
1289 char **section_start_with,
1290 ndrx_inicfg_section_t **out)
1291 {
1292 return _ndrx_inicfg_iterate(cfg, resources, section_start_with, out);
1293 }
1294
1295
1296
1297
1298
1299
1300 expublic void ndrx_inicfg_sections_free(ndrx_inicfg_section_t *sections)
1301 {
1302 API_ENTRY;
1303 _ndrx_inicfg_sections_free(sections);
1304 }
1305
1306
1307
1308
1309
1310
1311
1312
1313 expublic void ndrx_inicfg_file_free(ndrx_inicfg_t *cfg, ndrx_inicfg_file_t *cfgfile)
1314 {
1315 API_ENTRY;
1316 _ndrx_inicfg_file_free(cfg, cfgfile);
1317 }
1318
1319
1320
1321
1322
1323
1324
1325
1326 expublic void ndrx_inicfg_free(ndrx_inicfg_t *cfg)
1327 {
1328 API_ENTRY;
1329 _ndrx_inicfg_free(cfg);
1330 }
1331
1332