Fix caching issue in commit 1175663.
[pwmd.git] / src / rcfile.c
blob5c0051bd63283e1d8dca9209b5c41e6031f59021
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <ctype.h>
32 #include "pwmd-error.h"
33 #include <gcrypt.h>
34 #include "mutex.h"
35 #include "rcfile.h"
36 #include "util-misc.h"
37 #include "common.h"
38 #include "util-slist.h"
39 #include "util-string.h"
40 #include "mem.h"
42 #define DEFAULT_PINENTRY_TIMEOUT "30"
43 #define DEFAULT_CACHE_TIMEOUT "600"
44 #define DEFAULT_KEEPALIVE_INTERVAL "60"
46 #define INVALID_VALUE(file, line) do { \
47 if (file) \
48 log_write(_("%s(%i): invalid value for parameter."), file, line); \
49 } while (0);
51 enum
53 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
54 PARAM_BOOL, PARAM_ULONG, PARAM_ULONGLONG
57 static struct config_params_s
59 char *name;
60 int type;
61 char *value;
62 } config_params[] = {
63 { "backup", PARAM_BOOL, "true"},
64 { "socket_path", PARAM_CHARP, NULL},
65 { "socket_perms", PARAM_CHARP, NULL},
66 { "passphrase", PARAM_CHARP, NULL},
67 { "passphrase_file", PARAM_CHARP, NULL},
68 { "agent_env_file", PARAM_CHARP, NULL},
69 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
70 { "enable_logging", PARAM_BOOL, "0"},
71 { "log_level", PARAM_INT, "0"},
72 { "disable_mlockall", PARAM_BOOL, "true"},
73 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
74 { "cache_push", PARAM_CHARPP, NULL},
75 { "disable_list_and_dump", PARAM_BOOL, "false"},
76 { "recursion_depth", PARAM_INT, "100"},
77 { "syslog", PARAM_BOOL, "false"},
78 { "xfer_progress", PARAM_INT, "8196"},
79 { "allowed", PARAM_CHARPP, NULL},
80 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
81 { "cipher", PARAM_CHARP, "aes256"},
82 { "kill_scd", PARAM_BOOL, "false"},
83 { "cipher_iterations", PARAM_ULONGLONG, "0"},
84 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
85 { "priority", PARAM_INT, INVALID_PRIORITY},
86 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
87 { "tcp_port", PARAM_INT, "6466"},
88 { "enable_tcp", PARAM_BOOL, "false"},
89 { "tcp_require_key", PARAM_BOOL, "false"},
90 { "tcp_wait", PARAM_INT, "0"},
91 { "tcp_bind", PARAM_CHARP, "any"},
92 { "tcp_interface", PARAM_CHARP, NULL},
93 { "tls_timeout", PARAM_INT, "300"},
94 { "tls_cipher_suite", PARAM_CHARP, "SECURE256"},
95 { "tls_access", PARAM_CHARPP, NULL},
96 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
97 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
98 { "use_agent", PARAM_BOOL, "false"},
99 { "require_save_key", PARAM_BOOL, "true"},
100 { NULL, 0, NULL},
103 struct config_param_s
105 char *name;
106 int type;
107 union
109 int itype;
110 char *cptype;
111 char **cpptype;
112 long ltype;
113 long long lltype;
114 unsigned long ultype;
115 unsigned long long ulltype;
116 } value;
119 static struct config_section_s *config_find_section (struct slist_s *config,
120 const char *name);
121 static int new_param (struct config_section_s *section, const char *filename,
122 int lineno, const char *name, const char *value,
123 int type);
124 static void free_section (struct config_section_s *s);
125 static int set_defaults (struct slist_s **config);
127 static void
128 section_remove_param (struct config_section_s *section, const char *name)
130 unsigned i, t = slist_length (section->params);
132 for (i = 0; i < t; i++)
134 struct config_param_s *p = slist_nth_data (section->params, i);
136 if (!p)
137 continue;
139 if (!strcmp (p->name, name))
141 switch (p->type)
143 case PARAM_CHARP:
144 xfree (p->value.cptype);
145 break;
146 case PARAM_CHARPP:
147 strv_free (p->value.cpptype);
148 break;
151 section->params = slist_remove (section->params, p);
152 xfree (p->name);
153 xfree (p);
154 break;
159 void
160 config_clear_keys ()
162 MUTEX_LOCK (&rcfile_mutex);
163 unsigned i, t = slist_length (global_config);
165 for (i = 0; i < t; i++)
167 struct config_section_s *s = slist_nth_data (global_config, i);
168 if (!s)
169 continue;
171 section_remove_param (s, "passphrase");
174 MUTEX_UNLOCK (&rcfile_mutex);
177 static struct config_param_s *
178 config_has_param (struct config_section_s *s, const char *what)
180 unsigned i, t = slist_length (s->params);
182 for (i = 0; i < t; i++)
184 struct config_param_s *p = slist_nth_data (s->params, i);
185 if (!p)
186 break;
188 if (!strcmp (p->name, what))
189 return p;
192 return NULL;
195 static struct config_param_s *
196 config_get_param (struct slist_s *config,
197 const char *section, const char *what, int *exists)
199 unsigned i, t = slist_length (config);
201 *exists = 0;
203 for (i = 0; i < t; i++)
205 struct config_param_s *p;
206 struct config_section_s *s = slist_nth_data (config, i);
208 if (!s)
209 break;
211 if (strcmp (s->name, section))
212 continue;
214 p = config_has_param (s, what);
215 if (!p)
216 return NULL;
218 *exists = 1;
219 return p;
222 return NULL;
225 static struct config_section_s *
226 new_section (struct slist_s **config, const char *name)
228 struct slist_s *tmp;
229 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
231 if (!s)
232 return NULL;
234 s->name = str_dup (name);
235 if (!s->name)
237 log_write ("%s", pwmd_strerror (ENOMEM));
238 xfree (s);
239 return NULL;
242 tmp = slist_append (*config, s);
243 if (!tmp)
245 log_write ("%s", pwmd_strerror (ENOMEM));
246 xfree (s->name);
247 xfree (s);
248 return NULL;
251 *config = tmp;
252 return s;
256 config_set_string_param (struct slist_s **config, const char *section,
257 const char *name, const char *value)
259 struct config_section_s *s = config_find_section (*config, section);
261 if (!s)
263 s = new_section (config, section);
264 if (!s)
265 return 1;
268 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
271 char *
272 config_get_string_param (struct slist_s *config, const char *section,
273 const char *what, int *exists)
275 struct config_param_s *p = config_get_param (config, section, what, exists);
276 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
280 config_set_int_param (struct slist_s **config, const char *section,
281 const char *name, const char *value)
283 struct config_section_s *s = config_find_section (*config, section);
285 if (!s)
287 s = new_section (config, section);
288 if (!s)
289 return 1;
292 return new_param (s, NULL, 0, name, value, PARAM_INT);
296 config_get_int_param (struct slist_s *config, const char *section,
297 const char *what, int *exists)
299 struct config_param_s *p = config_get_param (config, section, what, exists);
300 return *exists ? p->value.itype : -1;
304 config_set_bool_param (struct slist_s **config, const char *section,
305 const char *name, const char *value)
307 struct config_section_s *s = config_find_section (*config, section);
309 if (!s)
311 s = new_section (config, section);
312 if (!s)
313 return 1;
316 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
320 config_get_bool_param (struct slist_s *config, const char *section,
321 const char *what, int *exists)
323 return config_get_int_param (config, section, what, exists);
327 config_set_long_param (struct slist_s **config, const char *section,
328 const char *name, const char *value)
330 struct config_section_s *s = config_find_section (*config, section);
332 if (!s)
334 s = new_section (config, section);
335 if (!s)
336 return 1;
339 return new_param (s, NULL, 0, name, value, PARAM_LONG);
342 unsigned long
343 config_get_ulong_param (struct slist_s *config, const char *section,
344 const char *what, int *exists)
346 struct config_param_s *p = config_get_param (config, section, what, exists);
347 return *exists ? p->value.ultype : 0;
350 long
351 config_get_long_param (struct slist_s *config, const char *section,
352 const char *what, int *exists)
354 struct config_param_s *p = config_get_param (config, section, what, exists);
355 return *exists ? p->value.ltype : -1;
359 config_set_longlong_param (struct slist_s **config, const char *section,
360 const char *name, const char *value)
362 struct config_section_s *s = config_find_section (*config, section);
364 if (!s)
366 s = new_section (config, section);
367 if (!s)
368 return 1;
371 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
374 long long
375 config_get_longlong_param (struct slist_s *config,
376 const char *section, const char *what, int *exists)
378 struct config_param_s *p = config_get_param (config, section, what, exists);
379 return *exists ? p->value.lltype : -1;
382 unsigned long long
383 config_get_ulonglong_param (struct slist_s *config,
384 const char *section,
385 const char *what, int *exists)
387 struct config_param_s *p = config_get_param (config, section, what, exists);
388 return *exists ? p->value.ulltype : 0;
392 config_set_list_param (struct slist_s **config, const char *section,
393 const char *name, const char *value)
395 struct config_section_s *s = config_find_section (*config, section);
397 if (!s)
399 s = new_section (config, section);
400 if (!s)
401 return 1;
404 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
407 char **
408 config_get_list_param (struct slist_s *config, const char *section,
409 const char *what, int *exists)
411 struct config_param_s *p = config_get_param (config, section, what, exists);
412 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
415 char *
416 config_get_string (const char *section, const char *what)
418 char *val = NULL;
419 const char *where = section ? section : "global";
420 int exists = 0;
422 MUTEX_LOCK (&rcfile_mutex);
423 val = config_get_string_param (global_config, where, what, &exists);
424 if (!exists && strcmp (section ? section : "", "global"))
425 val = config_get_string_param (global_config, "global", what, &exists);
427 MUTEX_UNLOCK (&rcfile_mutex);
428 return val;
431 char **
432 config_get_list (const char *section, const char *what)
434 char **val = NULL;
435 const char *where = section ? section : "global";
436 int exists = 0;
438 MUTEX_LOCK (&rcfile_mutex);
439 val = config_get_list_param (global_config, where, what, &exists);
440 if (!exists && strcmp (section ? section : "", "global"))
441 val = config_get_list_param (global_config, "global", what, &exists);
443 MUTEX_UNLOCK (&rcfile_mutex);
444 return val;
448 config_get_integer (const char *section, const char *what)
450 int val = 0;
451 const char *where = section ? section : "global";
452 int exists = 0;
454 MUTEX_LOCK (&rcfile_mutex);
455 val = config_get_int_param (global_config, where, what, &exists);
456 if (!exists && strcmp (section ? section : "", "global"))
457 val = config_get_int_param (global_config, "global", what, &exists);
459 MUTEX_UNLOCK (&rcfile_mutex);
460 return val;
463 long long
464 config_get_longlong (const char *section, const char *what)
466 long long val = 0;
467 const char *where = section ? section : "global";
468 int exists = 0;
470 MUTEX_LOCK (&rcfile_mutex);
471 val = config_get_longlong_param (global_config, where, what, &exists);
472 if (!exists && strcmp (section ? section : "", "global"))
473 val = config_get_longlong_param (global_config, "global", what, &exists);
475 MUTEX_UNLOCK (&rcfile_mutex);
476 return val;
479 unsigned long long
480 config_get_ulonglong (const char *section, const char *what)
482 unsigned long long val = 0;
483 const char *where = section ? section : "global";
484 int exists = 0;
486 MUTEX_LOCK (&rcfile_mutex);
487 val = config_get_ulonglong_param (global_config, where, what, &exists);
488 if (!exists && strcmp (section ? section : "", "global"))
489 val = config_get_ulonglong_param (global_config, "global", what, &exists);
491 MUTEX_UNLOCK (&rcfile_mutex);
492 return val;
495 long
496 config_get_long (const char *section, const char *what)
498 long val = 0;
499 const char *where = section ? section : "global";
500 int exists = 0;
502 MUTEX_LOCK (&rcfile_mutex);
503 val = config_get_long_param (global_config, where, what, &exists);
504 if (!exists && strcmp (section ? section : "", "global"))
505 val = config_get_long_param (global_config, "global", what, &exists);
507 MUTEX_UNLOCK (&rcfile_mutex);
508 return val;
511 unsigned long
512 config_get_ulong (const char *section, const char *what)
514 unsigned long val = 0;
515 const char *where = section ? section : "global";
516 int exists = 0;
518 MUTEX_LOCK (&rcfile_mutex);
519 val = config_get_ulong_param (global_config, where, what, &exists);
520 if (!exists && strcmp (section ? section : "", "global"))
521 val = config_get_ulong_param (global_config, "global", what, &exists);
523 MUTEX_UNLOCK (&rcfile_mutex);
524 return val;
528 config_get_boolean (const char *section, const char *what)
530 return config_get_integer (section, what);
533 char *
534 config_get_value (const char *section, const char *what)
536 const char *where = section ? section : "global";
537 int exists = 0;
538 int i;
539 int ival;
540 long lval;
541 long long llval;
542 unsigned long ulval;
543 unsigned long long ullval;
544 char *cpval;
545 char **cppval;
546 char *result = NULL;
548 MUTEX_LOCK (&rcfile_mutex);
550 for (i = 0; config_params[i].name; i++)
552 if (!strcmp (config_params[i].name, what))
554 switch (config_params[i].type)
556 case PARAM_BOOL:
557 case PARAM_INT:
558 ival = config_get_int_param (global_config, where, what,
559 &exists);
560 if (!exists && strcmp (section ? section : "", "global"))
561 ival = config_get_int_param (global_config, "global", what,
562 &exists);
563 result = str_asprintf ("%i", ival);
564 break;
565 case PARAM_CHARP:
566 cpval = config_get_string_param (global_config, where, what,
567 &exists);
568 if (!exists && strcmp (section ? section : "", "global"))
569 cpval =
570 config_get_string_param (global_config, "global", what,
571 &exists);
572 result = cpval;
573 break;
574 case PARAM_LONG:
575 lval = config_get_long_param (global_config, where, what,
576 &exists);
577 if (!exists && strcmp (section ? section : "", "global"))
578 lval = config_get_long_param (global_config, "global", what,
579 &exists);
580 result = str_asprintf ("%li", lval);
581 break;
582 case PARAM_ULONG:
583 ulval = config_get_ulong_param (global_config, where, what,
584 &exists);
585 if (!exists && strcmp (section ? section : "", "global"))
586 ulval = config_get_ulong_param (global_config, "global", what,
587 &exists);
588 result = str_asprintf ("%lu", ulval);
589 break;
590 case PARAM_LONGLONG:
591 llval = config_get_longlong_param (global_config, where, what,
592 &exists);
593 if (!exists && strcmp (section ? section : "", "global"))
594 llval = config_get_longlong_param (global_config, "global",
595 what, &exists);
596 result = str_asprintf ("%lli", llval);
597 break;
598 case PARAM_ULONGLONG:
599 ullval = config_get_ulonglong_param (global_config, where, what,
600 &exists);
601 if (!exists && strcmp (section ? section : "", "global"))
602 ullval = config_get_ulonglong_param (global_config, "global",
603 what, &exists);
604 result = str_asprintf ("%llu", ullval);
605 break;
606 case PARAM_CHARPP:
607 cppval = config_get_list_param (global_config, where, what,
608 &exists);
609 if (!exists && strcmp (section ? section : "", "global"))
610 cppval = config_get_list_param (global_config, "global", what,
611 &exists);
613 if (cppval)
614 result = strv_join (",", cppval);
616 strv_free (cppval);
617 break;
622 MUTEX_UNLOCK (&rcfile_mutex);
623 return result;
626 static int
627 set_defaults (struct slist_s **config)
629 char *s;
630 char **list;
631 int exists;
632 int i;
634 for (i = 0; config_params[i].name; i++)
636 switch (config_params[i].type)
638 case PARAM_BOOL:
639 config_get_bool_param (*config, "global", config_params[i].name,
640 &exists);
641 if (!exists)
643 if (config_set_bool_param
644 (config, "global", config_params[i].name,
645 config_params[i].value))
646 goto fail;
648 break;
649 case PARAM_INT:
650 config_get_int_param (*config, "global", config_params[i].name,
651 &exists);
652 if (!exists)
654 if (config_set_int_param
655 (config, "global", config_params[i].name,
656 config_params[i].value))
657 goto fail;
659 break;
660 case PARAM_CHARP:
661 s = config_get_string_param (*config, "global",
662 config_params[i].name, &exists);
663 xfree (s);
664 if (!exists && config_params[i].value)
666 if (config_set_string_param (config, "global",
667 config_params[i].name,
668 config_params[i].value))
669 goto fail;
671 break;
672 case PARAM_CHARPP:
673 list = config_get_list_param (*config, "global",
674 config_params[i].name, &exists);
675 strv_free (list);
676 if (!exists && config_params[i].value)
678 if (config_set_list_param (config, "global",
679 config_params[i].name,
680 config_params[i].value))
681 goto fail;
683 break;
684 case PARAM_LONG:
685 config_get_long_param (*config, "global", config_params[i].name,
686 &exists);
687 if (!exists)
689 if (config_set_long_param
690 (config, "global", config_params[i].name,
691 config_params[i].value))
692 goto fail;
694 break;
695 case PARAM_LONGLONG:
696 config_get_longlong_param (*config, "global", config_params[i].name,
697 &exists);
698 if (!exists)
700 if (config_set_longlong_param (config, "global",
701 config_params[i].name,
702 config_params[i].value))
703 goto fail;
705 break;
709 list = config_get_list_param (*config, "global", "allowed", &exists);
710 strv_free (list);
711 if (!exists)
713 if (config_set_list_param
714 (config, "global", "allowed", get_username ()))
715 goto fail;
718 max_recursion_depth = config_get_int_param (*config, "global",
719 "recursion_depth", &exists);
720 disable_list_and_dump = config_get_bool_param (*config, "global",
721 "disable_list_and_dump",
722 &exists);
723 #ifdef HAVE_MLOCKALL
724 disable_mlock =
725 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
726 #endif
727 return 0;
729 fail:
730 return 1;
733 static struct config_section_s *
734 config_find_section (struct slist_s *config, const char *name)
736 unsigned i, t = slist_length (config);
738 for (i = 0; i < t; i++)
740 struct config_section_s *s = slist_nth_data (config, i);
742 if (!strcmp (s->name, name))
743 return s;
746 return NULL;
749 /* Append a new parameter to the list of parameters for a file
750 * section. When an existing parameter of the same name exists, its
751 * value is updated.
753 static int
754 new_param (struct config_section_s *section, const char *filename, int lineno,
755 const char *name, const char *value, int type)
757 struct config_param_s *param = NULL;
758 struct slist_s *tmp;
759 char *e;
760 unsigned i, t = slist_length (section->params);
761 int dup = 0;
763 for (i = 0; i < t; i++)
765 struct config_param_s *p = slist_nth_data (section->params, i);
766 if (!p)
767 break;
769 if (!strcmp (name, p->name))
771 param = p;
772 dup = 1;
773 break;
777 if (!param)
779 param = xcalloc (1, sizeof (struct config_param_s));
780 if (!param)
782 log_write ("%s", pwmd_strerror (ENOMEM));
783 return 1;
786 param->name = str_dup (name);
787 if (!param->name)
789 xfree (param);
790 log_write ("%s", pwmd_strerror (ENOMEM));
791 return 1;
795 param->type = type;
797 switch (type)
799 case PARAM_BOOL:
800 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
801 || !strcasecmp (value, "false"))
802 param->value.itype = 0;
803 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
804 || !strcasecmp (value, "true"))
805 param->value.itype = 1;
806 else
808 INVALID_VALUE (filename, lineno);
809 goto fail;
811 param->type = PARAM_INT;
812 break;
813 case PARAM_CHARP:
814 xfree (param->value.cptype);
815 param->value.cptype = value ? str_dup (value) : NULL;
816 if (value && !param->value.cptype)
818 log_write ("%s", pwmd_strerror (ENOMEM));
819 goto fail;
821 break;
822 case PARAM_CHARPP:
823 strv_free (param->value.cpptype);
824 param->value.cpptype = value ? str_split (value, ",", 0) : NULL;
825 if (value && !param->value.cpptype)
827 log_write ("%s", pwmd_strerror (ENOMEM));
828 goto fail;
830 break;
831 case PARAM_INT:
832 param->value.itype = strtol (value, &e, 10);
833 if (e && *e)
835 INVALID_VALUE (filename, lineno);
836 goto fail;
838 break;
839 case PARAM_LONG:
840 param->value.ltype = strtol (value, &e, 10);
841 if (e && *e)
843 INVALID_VALUE (filename, lineno);
844 goto fail;
846 break;
847 case PARAM_LONGLONG:
848 param->value.lltype = strtoll (value, &e, 10);
849 if (e && *e)
851 INVALID_VALUE (filename, lineno);
852 goto fail;
854 break;
855 case PARAM_ULONGLONG:
856 param->value.ulltype = strtoull (value, &e, 10);
857 if (e && *e)
859 INVALID_VALUE (filename, lineno);
860 goto fail;
862 break;
863 case PARAM_ULONG:
864 param->value.ultype = strtoul (value, &e, 10);
865 if (e && *e)
867 INVALID_VALUE (filename, lineno);
868 goto fail;
870 break;
873 if (dup)
874 return 0;
876 tmp = slist_append (section->params, param);
877 if (!tmp)
879 log_write ("%s", pwmd_strerror (ENOMEM));
880 goto fail;
883 section->params = tmp;
884 return 0;
886 fail:
887 xfree (param->name);
888 xfree (param);
889 return 1;
892 struct slist_s *
893 config_parse (const char *filename)
895 struct slist_s *tmpconfig = NULL, *tmp;
896 struct config_section_s *cur_section = NULL;
897 char buf[LINE_MAX];
898 char *s;
899 int lineno = 1;
900 int have_global = 0;
901 FILE *fp = fopen (filename, "r");
903 if (!fp)
905 log_write ("%s: %s", filename,
906 pwmd_strerror (gpg_error_from_errno (errno)));
908 if (errno != ENOENT)
909 return NULL;
911 log_write (_("Using defaults!"));
912 goto defaults;
915 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
917 char line[LINE_MAX] = { 0 };
918 size_t len = 0;
920 if (*s == '#')
921 continue;
923 s = str_chomp (s);
924 for (; s && *s; s++)
926 int match = 0;
928 /* New file section. */
929 if (*s == '[')
931 struct config_section_s *section;
932 char *p = strchr (++s, ']');
934 if (!p)
936 log_write (_("%s(%i): unbalanced braces"), filename,
937 lineno);
938 goto fail;
941 len = strlen (s) - strlen (p);
942 memcpy (line, s, len);
943 line[len] = 0;
945 section = config_find_section (tmpconfig, line);
946 if (section)
948 log_write (_("%s(%i): section '%s' already exists!"),
949 filename, lineno, line);
950 goto fail;
953 if (!strcmp (line, "global"))
954 have_global = 1;
956 section = xcalloc (1, sizeof (struct config_section_s));
957 section->name = str_dup (line);
959 if (cur_section)
961 tmp = slist_append (tmpconfig, cur_section);
962 if (!tmp)
964 log_write ("%s", pwmd_strerror (ENOMEM));
965 goto fail;
968 tmpconfig = tmp;
971 cur_section = section;
972 break;
975 if (!cur_section)
977 log_write (_("%s(%i): parameter outside of section!"), filename,
978 lineno);
979 goto fail;
982 /* Parameters for each section. */
983 for (int m = 0; config_params[m].name; m++)
985 size_t len = strlen (config_params[m].name);
987 if (!strncmp (s, config_params[m].name, len))
989 char *p = s + len;
991 while (*p && *p == ' ')
992 p++;
994 if (!*p || *p != '=')
995 continue;
997 p++;
998 while (*p && isspace (*p))
999 p++;
1001 s[len] = 0;
1002 if (new_param (cur_section, filename, lineno, s, p,
1003 config_params[m].type))
1004 goto fail;
1006 match = 1;
1007 break;
1011 if (!match)
1013 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1014 goto fail;
1017 break;
1021 fclose (fp);
1023 if (cur_section)
1025 tmp = slist_append (tmpconfig, cur_section);
1026 if (!tmp)
1028 log_write ("%s", pwmd_strerror (ENOMEM));
1029 goto fail;
1032 cur_section = NULL;
1033 tmpconfig = tmp;
1036 if (!have_global)
1037 log_write (_
1038 ("WARNING: %s: could not find a [global] configuration section!"),
1039 filename);
1041 defaults:
1042 if (set_defaults (&tmpconfig))
1043 goto fail;
1045 return tmpconfig;
1047 fail:
1048 fclose (fp);
1049 config_free (tmpconfig);
1050 free_section (cur_section);
1051 return NULL;
1054 static void
1055 free_section (struct config_section_s *s)
1057 if (!s)
1058 return;
1060 for (;;)
1062 struct config_param_s *p = slist_nth_data (s->params, 0);
1064 if (!p)
1065 break;
1067 section_remove_param (s, p->name);
1070 s->params = NULL;
1071 xfree (s->name);
1072 s->name = NULL;
1075 void
1076 config_free (struct slist_s *config)
1078 for (;;)
1080 struct config_section_s *s = slist_nth_data (config, 0);
1081 if (!s)
1082 break;
1084 free_section (s);
1085 config = slist_remove (config, s);
1086 xfree (s);