Remove the "tls_use_crl" configuration parameter.
[pwmd.git] / src / rcfile.c
blobaf55f86c7e1a6b82e8c214c4f716eb372e74a115
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"
44 #define INVALID_VALUE(file, line) do { \
45 if (file) \
46 log_write(_("%s(%i): invalid value for parameter."), file, line); \
47 } while (0);
49 enum
51 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
52 PARAM_BOOL, PARAM_ULONG, PARAM_ULONGLONG
55 static struct config_params_s
57 char *name;
58 int type;
59 char *value;
60 } config_params[] = {
61 { "backup", PARAM_BOOL, "1"},
62 { "socket_path", PARAM_CHARP, NULL},
63 { "socket_perms", PARAM_CHARP, NULL},
64 { "passphrase", PARAM_CHARP, NULL},
65 { "passphrase_file", PARAM_CHARP, NULL},
66 { "agent_env_file", PARAM_CHARP, NULL},
67 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
68 { "enable_logging", PARAM_BOOL, "0"},
69 { "log_level", PARAM_INT, "0"},
70 { "disable_mlockall", PARAM_BOOL, "1"},
71 { "cache_timeout", PARAM_INT, "-1"},
72 { "cache_push", PARAM_CHARPP, NULL},
73 { "disable_list_and_dump", PARAM_BOOL, "0"},
74 { "recursion_depth", PARAM_INT, "100"},
75 { "syslog", PARAM_BOOL, "0"},
76 { "xfer_progress", PARAM_INT, "8196"},
77 { "allowed", PARAM_CHARPP, NULL},
78 { "nbits", PARAM_INT, "2048"},
79 { "algo", PARAM_CHARP, "rsa"},
80 { "cipher", PARAM_CHARP, "aes256"},
81 { "kill_scd", PARAM_BOOL, "0"},
82 { "cipher_iterations", PARAM_ULONGLONG, "0"},
83 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
84 { "priority", PARAM_INT, INVALID_PRIORITY},
85 { "keepalive_interval", PARAM_INT, "5"},
86 { "tcp_port", PARAM_INT, "6466"},
87 { "enable_tcp", PARAM_BOOL, "0"},
88 { "tcp_require_key", PARAM_BOOL, "0"},
89 { "tcp_wait", PARAM_INT, "0"},
90 { "tcp_bind", PARAM_CHARP, "any"},
91 { "tcp_interface", PARAM_CHARP, NULL},
92 { "tls_timeout", PARAM_INT, "300"},
93 { "tls_cipher_suite", PARAM_CHARP, "SECURE256"},
94 { "tls_access", PARAM_CHARPP, NULL},
95 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
96 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
97 { NULL, 0, NULL},
100 struct param_s
102 char *name;
103 int type;
104 union
106 int itype;
107 char *cptype;
108 char **cpptype;
109 long ltype;
110 long long lltype;
111 unsigned long ultype;
112 unsigned long long ulltype;
113 } value;
116 struct section_s
118 char *name;
119 struct slist_s *params;
122 static struct section_s *config_find_section (struct slist_s *config,
123 const char *name);
124 static int new_param (struct section_s *section, const char *filename,
125 int lineno, const char *name, const char *value,
126 int type);
127 static void free_section (struct section_s *s);
128 static int set_defaults (struct slist_s **config);
130 static void
131 section_remove_param (struct section_s *section, const char *name)
133 unsigned i, t = slist_length (section->params);
135 for (i = 0; i < t; i++)
137 struct param_s *p = slist_nth_data (section->params, i);
139 if (!p)
140 continue;
142 if (!strcmp (p->name, name))
144 switch (p->type)
146 case PARAM_CHARP:
147 xfree (p->value.cptype);
148 break;
149 case PARAM_CHARPP:
150 strv_free (p->value.cpptype);
151 break;
154 section->params = slist_remove (section->params, p);
155 xfree (p);
156 break;
161 void
162 config_clear_keys ()
164 MUTEX_LOCK (&rcfile_mutex);
165 unsigned i, t = slist_length (global_config);
167 for (i = 0; i < t; i++)
169 struct section_s *s = slist_nth_data (global_config, i);
170 if (!s)
171 continue;
173 section_remove_param (s, "passphrase");
176 MUTEX_UNLOCK (&rcfile_mutex);
179 static struct param_s *
180 config_has_param (struct section_s *s, const char *what)
182 unsigned i, t = slist_length (s->params);
184 for (i = 0; i < t; i++)
186 struct param_s *p = slist_nth_data (s->params, i);
187 if (!p)
188 break;
190 if (!strcmp (p->name, what))
191 return p;
194 return NULL;
197 static struct param_s *
198 config_get_param (struct slist_s *config,
199 const char *section, const char *what, int *exists)
201 unsigned i, t = slist_length (config);
203 *exists = 0;
205 for (i = 0; i < t; i++)
207 struct param_s *p;
208 struct section_s *s = slist_nth_data (config, i);
210 if (!s)
211 break;
213 if (strcmp (s->name, section))
214 continue;
216 p = config_has_param (s, what);
217 if (!p)
218 return NULL;
220 *exists = 1;
221 return p;
224 return NULL;
227 static struct section_s *
228 new_section (struct slist_s **config, const char *name)
230 struct slist_s *tmp;
231 struct section_s *s = xcalloc (1, sizeof (struct section_s));
233 if (!s)
234 return NULL;
236 s->name = str_dup (name);
237 if (!s->name)
239 log_write ("%s", pwmd_strerror (ENOMEM));
240 xfree (s);
241 return NULL;
244 tmp = slist_append (*config, s);
245 if (!tmp)
247 log_write ("%s", pwmd_strerror (ENOMEM));
248 xfree (s->name);
249 xfree (s);
250 return NULL;
253 *config = tmp;
254 return s;
258 config_set_string_param (struct slist_s **config, const char *section,
259 const char *name, const char *value)
261 struct section_s *s = config_find_section (*config, section);
263 if (!s)
265 s = new_section (config, section);
266 if (!s)
267 return 1;
270 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
273 char *
274 config_get_string_param (struct slist_s *config, const char *section,
275 const char *what, int *exists)
277 struct param_s *p = config_get_param (config, section, what, exists);
278 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
282 config_set_int_param (struct slist_s **config, const char *section,
283 const char *name, const char *value)
285 struct section_s *s = config_find_section (*config, section);
287 if (!s)
289 s = new_section (config, section);
290 if (!s)
291 return 1;
294 return new_param (s, NULL, 0, name, value, PARAM_INT);
298 config_get_int_param (struct slist_s *config, const char *section,
299 const char *what, int *exists)
301 struct param_s *p = config_get_param (config, section, what, exists);
302 return *exists ? p->value.itype : -1;
306 config_set_bool_param (struct slist_s **config, const char *section,
307 const char *name, const char *value)
309 struct section_s *s = config_find_section (*config, section);
311 if (!s)
313 s = new_section (config, section);
314 if (!s)
315 return 1;
318 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
322 config_get_bool_param (struct slist_s *config, const char *section,
323 const char *what, int *exists)
325 return config_get_int_param (config, section, what, exists);
329 config_set_long_param (struct slist_s **config, const char *section,
330 const char *name, const char *value)
332 struct section_s *s = config_find_section (*config, section);
334 if (!s)
336 s = new_section (config, section);
337 if (!s)
338 return 1;
341 return new_param (s, NULL, 0, name, value, PARAM_LONG);
344 unsigned long
345 config_get_ulong_param (struct slist_s *config, const char *section,
346 const char *what, int *exists)
348 struct param_s *p = config_get_param (config, section, what, exists);
349 return *exists ? p->value.ultype : 0;
352 long
353 config_get_long_param (struct slist_s *config, const char *section,
354 const char *what, int *exists)
356 struct param_s *p = config_get_param (config, section, what, exists);
357 return *exists ? p->value.ltype : -1;
361 config_set_longlong_param (struct slist_s **config, const char *section,
362 const char *name, const char *value)
364 struct section_s *s = config_find_section (*config, section);
366 if (!s)
368 s = new_section (config, section);
369 if (!s)
370 return 1;
373 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
376 long long
377 config_get_longlong_param (struct slist_s *config,
378 const char *section, const char *what, int *exists)
380 struct param_s *p = config_get_param (config, section, what, exists);
381 return *exists ? p->value.lltype : -1;
384 unsigned long long
385 config_get_ulonglong_param (struct slist_s *config,
386 const char *section,
387 const char *what, int *exists)
389 struct param_s *p = config_get_param (config, section, what, exists);
390 return *exists ? p->value.ulltype : 0;
394 config_set_list_param (struct slist_s **config, const char *section,
395 const char *name, const char *value)
397 struct section_s *s = config_find_section (*config, section);
399 if (!s)
401 s = new_section (config, section);
402 if (!s)
403 return 1;
406 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
409 char **
410 config_get_list_param (struct slist_s *config, const char *section,
411 const char *what, int *exists)
413 struct param_s *p = config_get_param (config, section, what, exists);
414 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
417 char *
418 config_get_string (const char *section, const char *what)
420 char *val = NULL;
421 const char *where = section ? section : "global";
422 int exists = 0;
424 MUTEX_LOCK (&rcfile_mutex);
425 val = config_get_string_param (global_config, where, what, &exists);
426 if (!exists && strcmp (section ? section : "", "global"))
427 val = config_get_string_param (global_config, "global", what, &exists);
429 MUTEX_UNLOCK (&rcfile_mutex);
430 return val;
433 char **
434 config_get_list (const char *section, const char *what)
436 char **val = NULL;
437 const char *where = section ? section : "global";
438 int exists = 0;
440 MUTEX_LOCK (&rcfile_mutex);
441 val = config_get_list_param (global_config, where, what, &exists);
442 if (!exists && strcmp (section ? section : "", "global"))
443 val = config_get_list_param (global_config, "global", what, &exists);
445 MUTEX_UNLOCK (&rcfile_mutex);
446 return val;
450 config_get_integer (const char *section, const char *what)
452 int val = 0;
453 const char *where = section ? section : "global";
454 int exists = 0;
456 MUTEX_LOCK (&rcfile_mutex);
457 val = config_get_int_param (global_config, where, what, &exists);
458 if (!exists && strcmp (section ? section : "", "global"))
459 val = config_get_int_param (global_config, "global", what, &exists);
461 MUTEX_UNLOCK (&rcfile_mutex);
462 return val;
465 long long
466 config_get_longlong (const char *section, const char *what)
468 long long val = 0;
469 const char *where = section ? section : "global";
470 int exists = 0;
472 MUTEX_LOCK (&rcfile_mutex);
473 val = config_get_longlong_param (global_config, where, what, &exists);
474 if (!exists && strcmp (section ? section : "", "global"))
475 val = config_get_longlong_param (global_config, "global", what, &exists);
477 MUTEX_UNLOCK (&rcfile_mutex);
478 return val;
481 unsigned long long
482 config_get_ulonglong (const char *section, const char *what)
484 unsigned long long val = 0;
485 const char *where = section ? section : "global";
486 int exists = 0;
488 MUTEX_LOCK (&rcfile_mutex);
489 val = config_get_ulonglong_param (global_config, where, what, &exists);
490 if (!exists && strcmp (section ? section : "", "global"))
491 val = config_get_ulonglong_param (global_config, "global", what, &exists);
493 MUTEX_UNLOCK (&rcfile_mutex);
494 return val;
497 long
498 config_get_long (const char *section, const char *what)
500 long val = 0;
501 const char *where = section ? section : "global";
502 int exists = 0;
504 MUTEX_LOCK (&rcfile_mutex);
505 val = config_get_long_param (global_config, where, what, &exists);
506 if (!exists && strcmp (section ? section : "", "global"))
507 val = config_get_long_param (global_config, "global", what, &exists);
509 MUTEX_UNLOCK (&rcfile_mutex);
510 return val;
513 unsigned long
514 config_get_ulong (const char *section, const char *what)
516 unsigned long val = 0;
517 const char *where = section ? section : "global";
518 int exists = 0;
520 MUTEX_LOCK (&rcfile_mutex);
521 val = config_get_ulong_param (global_config, where, what, &exists);
522 if (!exists && strcmp (section ? section : "", "global"))
523 val = config_get_ulong_param (global_config, "global", what, &exists);
525 MUTEX_UNLOCK (&rcfile_mutex);
526 return val;
530 config_get_boolean (const char *section, const char *what)
532 return config_get_integer (section, what);
535 char *
536 config_get_value (const char *section, const char *what)
538 const char *where = section ? section : "global";
539 int exists = 0;
540 int i;
541 int ival;
542 long lval;
543 long long llval;
544 unsigned long ulval;
545 unsigned long long ullval;
546 char *cpval;
547 char **cppval;
548 char *result = NULL;
550 MUTEX_LOCK (&rcfile_mutex);
552 for (i = 0; config_params[i].name; i++)
554 if (!strcmp (config_params[i].name, what))
556 switch (config_params[i].type)
558 case PARAM_BOOL:
559 case PARAM_INT:
560 ival = config_get_int_param (global_config, where, what,
561 &exists);
562 if (!exists && strcmp (section ? section : "", "global"))
563 ival = config_get_int_param (global_config, "global", what,
564 &exists);
565 result = str_asprintf ("%i", ival);
566 break;
567 case PARAM_CHARP:
568 cpval = config_get_string_param (global_config, where, what,
569 &exists);
570 if (!exists && strcmp (section ? section : "", "global"))
571 cpval =
572 config_get_string_param (global_config, "global", what,
573 &exists);
574 result = cpval;
575 break;
576 case PARAM_LONG:
577 lval = config_get_long_param (global_config, where, what,
578 &exists);
579 if (!exists && strcmp (section ? section : "", "global"))
580 lval = config_get_long_param (global_config, "global", what,
581 &exists);
582 result = str_asprintf ("%li", lval);
583 break;
584 case PARAM_ULONG:
585 ulval = config_get_ulong_param (global_config, where, what,
586 &exists);
587 if (!exists && strcmp (section ? section : "", "global"))
588 ulval = config_get_ulong_param (global_config, "global", what,
589 &exists);
590 result = str_asprintf ("%lu", ulval);
591 break;
592 case PARAM_LONGLONG:
593 llval = config_get_longlong_param (global_config, where, what,
594 &exists);
595 if (!exists && strcmp (section ? section : "", "global"))
596 llval = config_get_longlong_param (global_config, "global",
597 what, &exists);
598 result = str_asprintf ("%lli", llval);
599 break;
600 case PARAM_ULONGLONG:
601 ullval = config_get_ulonglong_param (global_config, where, what,
602 &exists);
603 if (!exists && strcmp (section ? section : "", "global"))
604 ullval = config_get_ulonglong_param (global_config, "global",
605 what, &exists);
606 result = str_asprintf ("%llu", ullval);
607 break;
608 case PARAM_CHARPP:
609 cppval = config_get_list_param (global_config, where, what,
610 &exists);
611 if (!exists && strcmp (section ? section : "", "global"))
612 cppval = config_get_list_param (global_config, "global", what,
613 &exists);
615 if (cppval)
616 result = strv_join (",", cppval);
618 strv_free (cppval);
619 break;
624 MUTEX_UNLOCK (&rcfile_mutex);
625 return result;
628 static int
629 set_defaults (struct slist_s **config)
631 char *s;
632 char **list;
633 int exists;
634 int i;
636 for (i = 0; config_params[i].name; i++)
638 switch (config_params[i].type)
640 case PARAM_BOOL:
641 config_get_bool_param (*config, "global", config_params[i].name,
642 &exists);
643 if (!exists)
645 if (config_set_bool_param
646 (config, "global", config_params[i].name,
647 config_params[i].value))
648 goto fail;
650 break;
651 case PARAM_INT:
652 config_get_int_param (*config, "global", config_params[i].name,
653 &exists);
654 if (!exists)
656 if (config_set_int_param
657 (config, "global", config_params[i].name,
658 config_params[i].value))
659 goto fail;
661 break;
662 case PARAM_CHARP:
663 s = config_get_string_param (*config, "global",
664 config_params[i].name, &exists);
665 xfree (s);
666 if (!exists && config_params[i].value)
668 if (config_set_string_param (config, "global",
669 config_params[i].name,
670 config_params[i].value))
671 goto fail;
673 break;
674 case PARAM_CHARPP:
675 list = config_get_list_param (*config, "global",
676 config_params[i].name, &exists);
677 strv_free (list);
678 if (!exists && config_params[i].value)
680 if (config_set_list_param (config, "global",
681 config_params[i].name,
682 config_params[i].value))
683 goto fail;
685 break;
686 case PARAM_LONG:
687 config_get_long_param (*config, "global", config_params[i].name,
688 &exists);
689 if (!exists)
691 if (config_set_long_param
692 (config, "global", config_params[i].name,
693 config_params[i].value))
694 goto fail;
696 break;
697 case PARAM_LONGLONG:
698 config_get_longlong_param (*config, "global", config_params[i].name,
699 &exists);
700 if (!exists)
702 if (config_set_longlong_param (config, "global",
703 config_params[i].name,
704 config_params[i].value))
705 goto fail;
707 break;
711 list = config_get_list_param (*config, "global", "allowed", &exists);
712 strv_free (list);
713 if (!exists)
715 if (config_set_list_param
716 (config, "global", "allowed", get_username ()))
717 goto fail;
720 max_recursion_depth = config_get_int_param (*config, "global",
721 "recursion_depth", &exists);
722 disable_list_and_dump = config_get_bool_param (*config, "global",
723 "disable_list_and_dump",
724 &exists);
725 #ifdef HAVE_MLOCKALL
726 disable_mlock =
727 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
728 #endif
729 return 0;
731 fail:
732 return 1;
735 static struct section_s *
736 config_find_section (struct slist_s *config, const char *name)
738 unsigned i, t = slist_length (config);
740 for (i = 0; i < t; i++)
742 struct section_s *s = slist_nth_data (config, i);
744 if (!strcmp (s->name, name))
745 return s;
748 return NULL;
751 /* Append a new parameter to the list of parameters for a file
752 * section. When an existing parameter of the same name exists, its
753 * value is updated.
755 static int
756 new_param (struct section_s *section, const char *filename, int lineno,
757 const char *name, const char *value, int type)
759 struct param_s *param = NULL;
760 struct slist_s *tmp;
761 char *e;
762 unsigned i, t = slist_length (section->params);
763 int dup = 0;
765 for (i = 0; i < t; i++)
767 struct param_s *p = slist_nth_data (section->params, i);
768 if (!p)
769 break;
771 if (!strcmp (name, p->name))
773 param = p;
774 dup = 1;
775 break;
779 if (!param)
781 param = xcalloc (1, sizeof (struct param_s));
782 if (!param)
784 log_write ("%s", pwmd_strerror (ENOMEM));
785 return 1;
788 param->name = str_dup (name);
789 if (!param->name)
791 xfree (param);
792 log_write ("%s", pwmd_strerror (ENOMEM));
793 return 1;
797 param->type = type;
799 switch (type)
801 case PARAM_BOOL:
802 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
803 || !strcasecmp (value, "false"))
804 param->value.itype = 0;
805 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
806 || !strcasecmp (value, "true"))
807 param->value.itype = 1;
808 else
810 INVALID_VALUE (filename, lineno);
811 goto fail;
813 param->type = PARAM_INT;
814 break;
815 case PARAM_CHARP:
816 xfree (param->value.cptype);
817 param->value.cptype = value ? str_dup (value) : NULL;
818 if (value && !param->value.cptype)
820 log_write ("%s", pwmd_strerror (ENOMEM));
821 goto fail;
823 break;
824 case PARAM_CHARPP:
825 strv_free (param->value.cpptype);
826 param->value.cpptype = value ? str_split (value, ",", 0) : NULL;
827 if (value && !param->value.cpptype)
829 log_write ("%s", pwmd_strerror (ENOMEM));
830 goto fail;
832 break;
833 case PARAM_INT:
834 param->value.itype = strtol (value, &e, 10);
835 if (e && *e)
837 INVALID_VALUE (filename, lineno);
838 goto fail;
840 break;
841 case PARAM_LONG:
842 param->value.ltype = strtol (value, &e, 10);
843 if (e && *e)
845 INVALID_VALUE (filename, lineno);
846 goto fail;
848 break;
849 case PARAM_LONGLONG:
850 param->value.lltype = strtoll (value, &e, 10);
851 if (e && *e)
853 INVALID_VALUE (filename, lineno);
854 goto fail;
856 break;
857 case PARAM_ULONGLONG:
858 param->value.ulltype = strtoull (value, &e, 10);
859 if (e && *e)
861 INVALID_VALUE (filename, lineno);
862 goto fail;
864 break;
865 case PARAM_ULONG:
866 param->value.ultype = strtoul (value, &e, 10);
867 if (e && *e)
869 INVALID_VALUE (filename, lineno);
870 goto fail;
872 break;
875 if (dup)
876 return 0;
878 tmp = slist_append (section->params, param);
879 if (!tmp)
881 log_write ("%s", pwmd_strerror (ENOMEM));
882 goto fail;
885 section->params = tmp;
886 return 0;
888 fail:
889 xfree (param->name);
890 xfree (param);
891 return 1;
894 struct slist_s *
895 config_parse (const char *filename)
897 struct slist_s *tmpconfig = NULL, *tmp;
898 struct section_s *cur_section = NULL;
899 char buf[LINE_MAX];
900 char *s;
901 int lineno = 1;
902 int have_global = 0;
903 FILE *fp = fopen (filename, "r");
905 if (!fp)
907 log_write ("%s: %s", filename,
908 pwmd_strerror (gpg_error_from_syserror ()));
910 if (errno != ENOENT)
911 return NULL;
913 log_write (_("Using defaults!"));
914 goto defaults;
917 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
919 char line[LINE_MAX] = { 0 };
920 size_t len = 0;
922 if (*s == '#')
923 continue;
925 s = str_chomp (s);
926 for (; s && *s; s++)
928 int match = 0;
930 /* New file section. */
931 if (*s == '[')
933 struct section_s *section;
934 char *p = strchr (++s, ']');
936 if (!p)
938 log_write (_("%s(%i): unbalanced braces"), filename,
939 lineno);
940 goto fail;
943 len = strlen (s) - strlen (p);
944 memcpy (line, s, len);
945 line[len] = 0;
947 section = config_find_section (tmpconfig, line);
948 if (section)
950 log_write (_("%s(%i): section '%s' already exists!"),
951 filename, lineno, line);
952 goto fail;
955 if (!strcmp (line, "global"))
956 have_global = 1;
958 section = xcalloc (1, sizeof (struct section_s));
959 section->name = str_dup (line);
961 if (cur_section)
963 tmp = slist_append (tmpconfig, cur_section);
964 if (!tmp)
966 log_write ("%s", pwmd_strerror (ENOMEM));
967 goto fail;
970 tmpconfig = tmp;
973 cur_section = section;
974 break;
977 if (!cur_section)
979 log_write (_("%s(%i): parameter outside of section!"), filename,
980 lineno);
981 goto fail;
984 /* Parameters for each section. */
985 for (int m = 0; config_params[m].name; m++)
987 size_t len = strlen (config_params[m].name);
989 if (!strncmp (s, config_params[m].name, len))
991 char *p = s + len;
993 while (*p && *p == ' ')
994 p++;
996 if (!*p || *p != '=')
997 continue;
999 p++;
1000 while (*p && isspace (*p))
1001 p++;
1003 s[len] = 0;
1004 if (new_param (cur_section, filename, lineno, s, p,
1005 config_params[m].type))
1006 goto fail;
1008 match = 1;
1009 break;
1013 if (!match)
1015 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1016 goto fail;
1019 break;
1023 fclose (fp);
1025 if (cur_section)
1027 tmp = slist_append (tmpconfig, cur_section);
1028 if (!tmp)
1030 log_write ("%s", pwmd_strerror (ENOMEM));
1031 goto fail;
1034 cur_section = NULL;
1035 tmpconfig = tmp;
1038 if (!have_global)
1039 log_write (_
1040 ("WARNING: %s: could not find a [global] configuration section!"),
1041 filename);
1043 defaults:
1044 if (set_defaults (&tmpconfig))
1045 goto fail;
1047 return tmpconfig;
1049 fail:
1050 fclose (fp);
1051 config_free (tmpconfig);
1052 free_section (cur_section);
1053 return NULL;
1056 static void
1057 free_section (struct section_s *s)
1059 if (!s)
1060 return;
1062 for (;;)
1064 struct param_s *p = slist_nth_data (s->params, 0);
1066 if (!p)
1067 break;
1069 section_remove_param (s, p->name);
1072 s->params = NULL;
1075 void
1076 config_free (struct slist_s *config)
1078 for (;;)
1080 struct 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);