]> git.zerfleddert.de Git - amt/blob - parseconfig.c
fix order of OEMparameters to enable BIOS SOL on newer AMT generations
[amt] / parseconfig.c
1 /*
2 * functions to read and write config files
3 *
4 * Copyright (C) 2007 Gerd Hoffmann <kraxel@redhat.com
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <errno.h>
27
28 #include <sys/stat.h>
29 #include <sys/types.h>
30
31 #include "list.h"
32 #include "parseconfig.h"
33
34 struct cfg_entry {
35 struct list_head next;
36 char *name;
37 unsigned int flags;
38 char *value;
39 };
40
41 struct cfg_section {
42 struct list_head next;
43 char *name;
44 unsigned int flags;
45 struct list_head entries;
46 };
47
48 struct cfg_domain {
49 struct list_head next;
50 char *name;
51 struct list_head sections;
52 };
53
54 LIST_HEAD(domains);
55
56 /* ------------------------------------------------------------------------ */
57 /* internal stuff */
58
59 static struct cfg_domain *d_last;
60 static struct cfg_section *s_last;
61 static struct cfg_entry *e_last;
62
63 static struct cfg_domain*
64 cfg_find_domain(char *dname)
65 {
66 struct list_head *item;
67 struct cfg_domain *domain;
68
69 if (d_last && 0 == strcmp(d_last->name,dname))
70 return d_last;
71 d_last = NULL;
72 s_last = NULL;
73 e_last = NULL;
74
75 list_for_each(item,&domains) {
76 domain = list_entry(item, struct cfg_domain, next);
77 if (0 == strcasecmp(domain->name,dname)) {
78 d_last = domain;
79 return domain;
80 }
81 }
82 return NULL;
83 }
84
85 static struct cfg_domain*
86 cfg_get_domain(char *dname)
87 {
88 struct cfg_domain *domain;
89
90 domain = cfg_find_domain(dname);
91 if (NULL == domain) {
92 domain = malloc(sizeof(*domain));
93 memset(domain,0,sizeof(*domain));
94 domain->name = strdup(dname);
95 INIT_LIST_HEAD(&domain->sections);
96 list_add_tail(&domain->next,&domains);
97 }
98 d_last = domain;
99 return domain;
100 }
101
102 static struct cfg_section*
103 cfg_find_section(struct cfg_domain *domain, char *sname)
104 {
105 struct list_head *item;
106 struct cfg_section *section;
107
108 if (s_last && 0 == strcmp(s_last->name,sname))
109 return s_last;
110 s_last = NULL;
111 e_last = NULL;
112
113 list_for_each(item,&domain->sections) {
114 section = list_entry(item, struct cfg_section, next);
115 if (0 == strcasecmp(section->name,sname)) {
116 s_last = section;
117 return section;
118 }
119 }
120 return NULL;
121 }
122
123 static struct cfg_section*
124 cfg_get_section(struct cfg_domain *domain, char *sname)
125 {
126 struct cfg_section *section;
127
128 section = cfg_find_section(domain,sname);
129 if (NULL == section) {
130 section = malloc(sizeof(*section));
131 memset(section,0,sizeof(*section));
132 section->name = strdup(sname);
133 INIT_LIST_HEAD(&section->entries);
134 list_add_tail(&section->next,&domain->sections);
135 }
136 s_last = section;
137 return section;
138 }
139
140 static struct cfg_entry*
141 cfg_find_entry(struct cfg_section *section, char *ename)
142 {
143 struct list_head *item;
144 struct cfg_entry *entry;
145
146 if (e_last && 0 == strcmp(e_last->name,ename))
147 return e_last;
148 e_last = NULL;
149
150 list_for_each(item,&section->entries) {
151 entry = list_entry(item, struct cfg_entry, next);
152 if (0 == strcasecmp(entry->name,ename)) {
153 e_last = entry;
154 return entry;
155 }
156 }
157 return NULL;
158 }
159
160 static struct cfg_entry*
161 cfg_get_entry(struct cfg_section *section, char *ename)
162 {
163 struct cfg_entry *entry;
164
165 entry = cfg_find_entry(section,ename);
166 if (NULL == entry) {
167 entry = malloc(sizeof(*entry));
168 memset(entry,0,sizeof(*entry));
169 entry->name = strdup(ename);
170 list_add_tail(&entry->next,&section->entries);
171 }
172 e_last = entry;
173 return entry;
174 }
175
176 static void
177 cfg_set_entry(struct cfg_section *section, char *name, const char *value)
178 {
179 struct cfg_entry *entry;
180
181 entry = cfg_get_entry(section,name);
182 if (entry->value)
183 free(entry->value);
184 entry->value = strdup(value);
185 }
186
187 static struct cfg_section*
188 cfg_get_sec(char *dname, char *sname)
189 {
190 struct cfg_domain *domain;
191
192 domain = cfg_find_domain(dname);
193 if (NULL == domain)
194 return NULL;
195 return cfg_find_section(domain,sname);
196 }
197
198 static struct cfg_entry*
199 cfg_get_ent(char *dname, char *sname, char *ename)
200 {
201 struct cfg_section *section;
202
203 section = cfg_get_sec(dname,sname);
204 if (NULL == section)
205 return NULL;
206 return cfg_find_entry(section,ename);
207 }
208
209 /* ------------------------------------------------------------------------ */
210 /* import / add / del config data */
211
212 int
213 cfg_parse_file(char *dname, char *filename)
214 {
215 struct cfg_domain *domain = NULL;
216 struct cfg_section *section = NULL;
217 char line[256],tag[64],value[192];
218 FILE *fp;
219 int nr;
220
221 if (NULL == (fp = fopen(filename,"r")))
222 return -1;
223
224 nr = 0;
225 domain = cfg_get_domain(dname);
226 while (NULL != fgets(line,255,fp)) {
227 nr++;
228 if (1 == sscanf(line,"# include \"%[^\"]\"",value)) {
229 /* includes */
230 char *h,*inc;
231 inc = malloc(strlen(filename)+strlen(value));
232 strcpy(inc,filename);
233 h = strrchr(inc,'/');
234 if (h)
235 h++;
236 else
237 h = inc;
238 strcpy(h,value);
239 cfg_parse_file(dname,inc);
240 free(inc);
241 continue;
242 }
243 if (line[0] == '\n' || line[0] == '#' || line[0] == '%')
244 continue;
245 if (1 == sscanf(line,"[%99[^]]]",value)) {
246 /* [section] */
247 section = cfg_get_section(domain,value);
248 } else if (2 == sscanf(line," %63[^= ] = %191[^\n]",tag,value)) {
249 /* foo = bar */
250 if (NULL == section) {
251 fprintf(stderr,"%s:%d: error: no section\n",filename,nr);
252 } else {
253 char *c = value + strlen(value)-1;
254 while (c > value && (*c == ' ' || *c == '\t'))
255 *(c--) = 0;
256 cfg_set_entry(section,tag,value);
257 }
258 } else {
259 /* Huh ? */
260 fprintf(stderr,"%s:%d: syntax error\n",filename,nr);
261 }
262 }
263 fclose(fp);
264 return 0;
265 }
266
267 void
268 cfg_set_str(char *dname, char *sname, char *ename, const char *value)
269 {
270 struct cfg_domain *domain = NULL;
271 struct cfg_section *section = NULL;
272
273 if (NULL == value) {
274 cfg_del_entry(dname, sname, ename);
275 } else {
276 domain = cfg_get_domain(dname);
277 section = cfg_get_section(domain,sname);
278 cfg_set_entry(section,ename,value);
279 }
280 }
281
282 void
283 cfg_set_int(char *dname, char *sname, char *ename, int value)
284 {
285 char str[32];
286
287 snprintf(str,sizeof(str),"%d",value);
288 cfg_set_str(dname,sname,ename,str);
289 }
290
291 void
292 cfg_set_bool(char *dname, char *sname, char *ename, int value)
293 {
294 cfg_set_str(dname,sname,ename, value ? "true" : "false");
295 }
296
297 void
298 cfg_del_section(char *dname, char *sname)
299 {
300 struct cfg_section *section;
301 struct cfg_entry *entry;
302
303 section= cfg_get_sec(dname,sname);
304 if (!section)
305 return;
306 list_del(&section->next);
307 while (!list_empty(&section->entries)) {
308 entry = list_entry(section->entries.next, struct cfg_entry, next);
309 list_del(&entry->next);
310 free(entry->name);
311 free(entry->value);
312 free(entry);
313 }
314 s_last = NULL;
315 e_last = NULL;
316 free(section->name);
317 free(section);
318 }
319
320 void
321 cfg_del_entry(char *dname, char *sname, char *ename)
322 {
323 struct cfg_entry *entry;
324
325 entry = cfg_get_ent(dname,sname,ename);
326 if (!entry)
327 return;
328 e_last = NULL;
329 list_del(&entry->next);
330 free(entry->name);
331 free(entry->value);
332 free(entry);
333 }
334
335 void
336 cfg_parse_cmdline(int *argc, char **argv, struct cfg_cmdline *opt)
337 {
338 int i,j,o,shift,len;
339 char sopt,*lopt;
340
341 for (i = 1; i < *argc;) {
342 if (argv[i][0] != '-') {
343 i++;
344 continue;
345 }
346 if (argv[i][1] == 0) {
347 i++;
348 continue;
349 }
350
351 sopt = 0;
352 lopt = NULL;
353 if (argv[i][1] != '-' &&
354 argv[i][2] == 0) {
355 /* short option: -f */
356 sopt = argv[i][1];
357 }
358 if (argv[i][1] != '-') {
359 /* long option: -foo */
360 lopt = argv[i]+1;
361 } else {
362 /* also accept gnu-style: --foo */
363 lopt = argv[i]+2;
364 }
365
366 for (shift = 0, o = 0;
367 0 == shift && opt[o].cmdline != NULL;
368 o++) {
369 len = strlen(opt[o].cmdline);
370
371 if (opt[o].yesno && sopt && sopt == opt[o].letter) {
372 /* yesno: -f */
373 cfg_set_bool(opt[o].option.domain,
374 opt[o].option.section,
375 opt[o].option.entry,
376 1);
377 shift = 1;
378
379 } else if (opt[o].needsarg && sopt && sopt == opt[o].letter &&
380 i+1 < *argc) {
381 /* arg: -f bar */
382 cfg_set_str(opt[o].option.domain,
383 opt[o].option.section,
384 opt[o].option.entry,
385 argv[i+1]);
386 shift = 2;
387
388 } else if (opt[o].value && sopt && sopt == opt[o].letter) {
389 /* -f sets fixed value */
390 cfg_set_str(opt[o].option.domain,
391 opt[o].option.section,
392 opt[o].option.entry,
393 opt[o].value);
394 shift = 1;
395
396 } else if (opt[o].yesno && lopt &&
397 0 == strcmp(lopt,opt[o].cmdline)) {
398 /* yesno: -foo */
399 cfg_set_bool(opt[o].option.domain,
400 opt[o].option.section,
401 opt[o].option.entry,
402 1);
403 shift = 1;
404
405 } else if (opt[o].yesno && lopt &&
406 0 == strncmp(lopt,"no",2) &&
407 0 == strcmp(lopt+2,opt[o].cmdline)) {
408 /* yesno: -nofoo */
409 cfg_set_bool(opt[o].option.domain,
410 opt[o].option.section,
411 opt[o].option.entry,
412 0);
413 shift = 1;
414
415 } else if (opt[o].needsarg && lopt &&
416 0 == strcmp(lopt,opt[o].cmdline) &&
417 i+1 < *argc) {
418 /* arg: -foo bar */
419 cfg_set_str(opt[o].option.domain,
420 opt[o].option.section,
421 opt[o].option.entry,
422 argv[i+1]);
423 shift = 2;
424
425 } else if (opt[o].needsarg && lopt &&
426 0 == strncmp(lopt,opt[o].cmdline,len) &&
427 0 == strncmp(lopt+len,"=",1)) {
428 /* arg: -foo=bar */
429 cfg_set_str(opt[o].option.domain,
430 opt[o].option.section,
431 opt[o].option.entry,
432 argv[i]+2+len);
433 shift = 1;
434
435 } else if (opt[o].value && lopt &&
436 0 == strcmp(lopt,opt[o].cmdline)) {
437 /* -foo sets some fixed value */
438 cfg_set_str(opt[o].option.domain,
439 opt[o].option.section,
440 opt[o].option.entry,
441 opt[o].value);
442 shift = 1;
443 }
444 }
445
446 if (shift) {
447 /* remove processed args */
448 for (j = i; j < *argc+1-shift; j++)
449 argv[j] = argv[j+shift];
450 (*argc) -= shift;
451 } else
452 i++;
453 }
454 }
455
456 void
457 cfg_help_cmdline(FILE *fp, struct cfg_cmdline *opt, int w1, int w2, int w3)
458 {
459 char *val;
460 int o,len;
461
462 for (o = 0; opt[o].cmdline != NULL; o++) {
463 fprintf(fp,"%*s",w1,"");
464 if (opt[o].letter) {
465 fprintf(fp,"-%c ",opt[o].letter);
466 } else {
467 fprintf(fp," ");
468 }
469
470 if (opt[o].yesno) {
471 len = fprintf(fp,"-(no)%s ",opt[o].cmdline);
472 } else if (opt[o].needsarg) {
473 len = fprintf(fp,"-%s <arg> ",opt[o].cmdline);
474 } else {
475 len = fprintf(fp,"-%s ",opt[o].cmdline);
476 }
477 if (len < w2)
478 fprintf(fp,"%*s",w2-len,"");
479
480 len = fprintf(fp,"%s ",opt[o].desc);
481
482 if (w3) {
483 if (len < w3)
484 fprintf(fp,"%*s",w3-len,"");
485 val = cfg_get_str(opt[o].option.domain,
486 opt[o].option.section,
487 opt[o].option.entry);
488 if (val)
489 fprintf(fp,"[%s]",val);
490 }
491 fprintf(fp,"\n");
492 }
493 }
494
495 /* ------------------------------------------------------------------------ */
496 /* export config data */
497
498 static int cfg_mkdir(char *filename)
499 {
500 char *h;
501 int rc;
502
503 h = strrchr(filename,'/');
504 if (!h || h == filename)
505 return -1;
506 *h = '\0';
507 rc = mkdir(filename,0777);
508 if (-1 == rc && ENOENT == errno) {
509 cfg_mkdir(filename);
510 rc = mkdir(filename,0777);
511 }
512 if (-1 == rc)
513 fprintf(stderr,"mkdir(%s): %s\n",filename,strerror(errno));
514 *h = '/';
515 return rc;
516 }
517
518 int
519 cfg_write_file(char *dname, char *filename)
520 {
521 struct list_head *item1,*item2;
522 struct cfg_domain *domain;
523 struct cfg_section *section;
524 struct cfg_entry *entry;
525 char *bfile, *tfile;
526 int len;
527 FILE *fp;
528
529 len = strlen(filename)+10;
530 bfile = malloc(len);
531 tfile = malloc(len);
532 sprintf(bfile,"%s~",filename);
533 sprintf(tfile,"%s.$$$",filename);
534
535 fp = fopen(tfile,"w");
536 if (NULL == fp && ENOENT == errno) {
537 cfg_mkdir(tfile);
538 fp = fopen(tfile,"w");
539 }
540 if (NULL == fp) {
541 fprintf(stderr,"open(%s): %s\n",tfile,strerror(errno));
542 return -1;
543 }
544
545 domain = cfg_find_domain(dname);
546 if (NULL != domain) {
547 list_for_each(item1,&domain->sections) {
548 section = list_entry(item1, struct cfg_section, next);
549 fprintf(fp,"[%s]\n",section->name);
550 list_for_each(item2,&section->entries) {
551 entry = list_entry(item2, struct cfg_entry, next);
552 fprintf(fp,"%s = %s\n",entry->name,entry->value);
553 }
554 fprintf(fp,"\n");
555 }
556 }
557 fclose(fp);
558
559 if (-1 == unlink(bfile) && ENOENT != errno) {
560 fprintf(stderr,"unlink(%s): %s\n",bfile,strerror(errno));
561 return -1;
562 }
563 if (-1 == rename(filename,bfile) && ENOENT != errno) {
564 fprintf(stderr,"rename(%s,%s): %s\n",filename,bfile,strerror(errno));
565 return -1;
566 }
567 if (-1 == rename(tfile,filename)) {
568 fprintf(stderr,"rename(%s,%s): %s\n",tfile,filename,strerror(errno));
569 return -1;
570 }
571 return 0;
572 }
573
574 /* ------------------------------------------------------------------------ */
575 /* list / search config data */
576
577 char*
578 cfg_sections_first(char *dname)
579 {
580 struct list_head *item;
581 struct cfg_domain *domain;
582 struct cfg_section *section;
583
584 domain = cfg_find_domain(dname);
585 if (NULL == domain)
586 return NULL;
587
588 item = &domain->sections;
589 if (item->next == &domain->sections)
590 return NULL;
591 section = list_entry(item->next, struct cfg_section, next);
592 s_last = section;
593 e_last = NULL;
594 return section->name;
595 }
596
597 char*
598 cfg_sections_next(char *dname, char *current)
599 {
600 struct list_head *item;
601 struct cfg_domain *domain;
602 struct cfg_section *section;
603
604 domain = cfg_find_domain(dname);
605 if (NULL == domain)
606 return NULL;
607 section = cfg_find_section(domain,current);
608 if (NULL == section)
609 return NULL;
610 item = &section->next;
611
612 if (item->next == &domain->sections)
613 return NULL;
614 section = list_entry(item->next, struct cfg_section, next);
615 s_last = section;
616 e_last = NULL;
617 return section->name;
618 }
619
620 char*
621 cfg_sections_prev(char *dname, char *current)
622 {
623 struct list_head *item;
624 struct cfg_domain *domain;
625 struct cfg_section *section;
626
627 domain = cfg_find_domain(dname);
628 if (NULL == domain)
629 return NULL;
630 section = cfg_find_section(domain,current);
631 if (NULL == section)
632 return NULL;
633 item = &section->next;
634
635 if (item->prev == &domain->sections)
636 return NULL;
637 section = list_entry(item->prev, struct cfg_section, next);
638 s_last = section;
639 e_last = NULL;
640 return section->name;
641 }
642
643 unsigned int cfg_sections_count(char *dname)
644 {
645 struct list_head *item;
646 struct cfg_domain *domain;
647 int count = 0;
648
649 domain = cfg_find_domain(dname);
650 if (NULL != domain)
651 list_for_each(item,&domain->sections)
652 count++;
653 return count;
654 }
655
656 char* cfg_sections_index(char *dname, int i)
657 {
658 struct list_head *item;
659 struct cfg_domain *domain;
660 struct cfg_section *section;
661 int count = 0;
662
663 domain = cfg_find_domain(dname);
664 if (NULL == domain)
665 return NULL;
666
667 list_for_each(item,&domain->sections) {
668 if (i == count) {
669 section = list_entry(item, struct cfg_section, next);
670 s_last = section;
671 e_last = NULL;
672 return section->name;
673 }
674 count++;
675 }
676 return NULL;
677 }
678
679 char*
680 cfg_entries_first(char *dname, char *sname)
681 {
682 struct list_head *item;
683 struct cfg_section *section;
684 struct cfg_entry *entry;
685
686 section = cfg_get_sec(dname,sname);
687 if (NULL == section)
688 return NULL;
689
690 item = &section->entries;
691 if (item->next == &section->entries)
692 return NULL;
693 entry = list_entry(item->next, struct cfg_entry, next);
694 e_last = entry;
695 return entry->name;
696 }
697
698 char*
699 cfg_entries_next(char *dname, char *sname, char *current)
700 {
701 struct list_head *item;
702 struct cfg_section *section;
703 struct cfg_entry *entry;
704
705 section = cfg_get_sec(dname,sname);
706 if (NULL == section)
707 return NULL;
708 entry = cfg_find_entry(section,current);
709 if (NULL == entry)
710 return NULL;
711 item = &entry->next;
712
713 if (item->next == &section->entries)
714 return NULL;
715 entry = list_entry(item->next, struct cfg_entry, next);
716 e_last = entry;
717 return entry->name;
718 }
719
720 char*
721 cfg_entries_prev(char *dname, char *sname, char *current)
722 {
723 struct list_head *item;
724 struct cfg_section *section;
725 struct cfg_entry *entry;
726
727 section = cfg_get_sec(dname,sname);
728 if (NULL == section)
729 return NULL;
730 entry = cfg_find_entry(section,current);
731 if (NULL == entry)
732 return NULL;
733 item = &entry->next;
734
735 if (item->prev == &section->entries)
736 return NULL;
737 entry = list_entry(item->prev, struct cfg_entry, next);
738 e_last = entry;
739 return entry->name;
740 }
741
742 unsigned int cfg_entries_count(char *dname, char *sname)
743 {
744 struct list_head *item;
745 struct cfg_section *section;
746 int count = 0;
747
748 section = cfg_get_sec(dname,sname);
749 if (NULL != section)
750 list_for_each(item,&section->entries)
751 count++;
752 return count;
753 }
754
755 char* cfg_entries_index(char *dname, char *sname, int i)
756 {
757 struct list_head *item;
758 struct cfg_section *section;
759 struct cfg_entry *entry;
760 int count = 0;
761
762 section = cfg_get_sec(dname,sname);
763 if (NULL == section)
764 return NULL;
765
766 list_for_each(item,&section->entries) {
767 if (i == count) {
768 entry = list_entry(item, struct cfg_entry, next);
769 e_last = entry;
770 return entry->name;
771 }
772 count++;
773 }
774 return NULL;
775 }
776
777 char* cfg_search(char *dname, char *sname, char *ename, char *value)
778 {
779 struct list_head *item1,*item2;
780 struct cfg_domain *domain;
781 struct cfg_section *section;
782 struct cfg_entry *entry;
783
784 domain = cfg_find_domain(dname);
785 if (NULL == domain)
786 return NULL;
787 list_for_each(item1,&domain->sections) {
788 section = list_entry(item1, struct cfg_section, next);
789 if (sname && 0 != strcasecmp(section->name,sname))
790 continue;
791 if (!ename)
792 return section->name;
793 list_for_each(item2,&section->entries) {
794 entry = list_entry(item2, struct cfg_entry, next);
795 if (0 != strcasecmp(entry->name,ename))
796 continue;
797 if (0 == strcasecmp(entry->value,value))
798 return section->name;
799 }
800 }
801 return NULL;
802 }
803
804 /* ------------------------------------------------------------------------ */
805 /* get config data */
806
807 char*
808 cfg_get_str(char *dname, char *sname, char *ename)
809 {
810 struct cfg_entry *entry;
811
812 entry = cfg_get_ent(dname, sname, ename);
813 if (NULL == entry)
814 return NULL;
815 return entry->value;
816 }
817
818 unsigned int
819 cfg_get_int(char *dname, char *sname, char *ename, unsigned int def)
820 {
821 char *val;
822
823 val = cfg_get_str(dname,sname,ename);
824 if (NULL == val)
825 return def;
826 return atoi(val);
827 }
828
829 signed int
830 cfg_get_signed_int(char *dname, char *sname, char *ename, signed int def)
831 {
832 char *val;
833
834 val = cfg_get_str(dname,sname,ename);
835 if (NULL == val)
836 return def;
837 return atoi(val);
838 }
839
840 float
841 cfg_get_float(char *dname, char *sname, char *ename, float def)
842 {
843 char *val;
844
845 val = cfg_get_str(dname,sname,ename);
846 if (NULL == val)
847 return def;
848 return atof(val);
849 }
850
851 int
852 cfg_get_bool(char *dname, char *sname, char *ename, int def)
853 {
854 static char *yes[] = { "true", "yes", "on", "1" };
855 char *val;
856 int i;
857 int retval = 0;
858
859 val = cfg_get_str(dname,sname,ename);
860 if (NULL == val)
861 return def;
862 for (i = 0; i < sizeof(yes)/sizeof(yes[0]); i++)
863 if (0 == strcasecmp(val,yes[i]))
864 retval = 1;
865 return retval;
866 }
867
868 /* ------------------------------------------------------------------------ */
869 /* get/set flags */
870
871 unsigned int cfg_get_sflags(char *dname, char *sname)
872 {
873 struct cfg_section *section;
874
875 section = cfg_get_sec(dname, sname);
876 if (NULL == section)
877 return 0;
878 return section->flags;
879 }
880
881 unsigned int cfg_get_eflags(char *dname, char *sname, char *ename)
882 {
883 struct cfg_entry *entry;
884
885 entry = cfg_get_ent(dname, sname, ename);
886 if (NULL == entry)
887 return 0;
888 return entry->flags;
889 }
890
891 unsigned int cfg_set_sflags(char *dname, char *sname,
892 unsigned int mask, unsigned int bits)
893 {
894 struct cfg_section *section;
895
896 section = cfg_get_sec(dname, sname);
897 if (NULL == section)
898 return 0;
899 section->flags &= ~mask;
900 section->flags |= bits;
901 return section->flags;
902 }
903
904 unsigned int cfg_set_eflags(char *dname, char *sname, char *ename,
905 unsigned int mask, unsigned int bits)
906 {
907 struct cfg_entry *entry;
908
909 entry = cfg_get_ent(dname, sname, ename);
910 if (NULL == entry)
911 return 0;
912 entry->flags &= ~mask;
913 entry->flags |= bits;
914 return entry->flags;
915 }
Impressum, Datenschutz