Reimplement the KEEPALIVE status message.
[pwmd.git] / src / rcfile.c
blob3322f99af165c07777ae66c86e8cdf9523886e8f
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_use_crl", PARAM_BOOL, "1"},
95 { "tls_access", PARAM_CHARPP, NULL},
96 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
97 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
98 { NULL, 0, NULL},
101 struct param_s
103 char *name;
104 int type;
105 union
107 int itype;
108 char *cptype;
109 char **cpptype;
110 long ltype;
111 long long lltype;
112 unsigned long ultype;
113 unsigned long long ulltype;
114 } value;
117 struct section_s
119 char *name;
120 struct slist_s *params;
123 static struct section_s *config_find_section (struct slist_s *config,
124 const char *name);
125 static int new_param (struct section_s *section, const char *filename,
126 int lineno, const char *name, const char *value,
127 int type);
128 static void free_section (struct section_s *s);
129 static int set_defaults (struct slist_s **config);
131 static void
132 section_remove_param (struct section_s *section, const char *name)
134 unsigned i, t = slist_length (section->params);
136 for (i = 0; i < t; i++)
138 struct param_s *p = slist_nth_data (section->params, i);
140 if (!p)
141 continue;
143 if (!strcmp (p->name, name))
145 switch (p->type)
147 case PARAM_CHARP:
148 xfree (p->value.cptype);
149 break;
150 case PARAM_CHARPP:
151 strv_free (p->value.cpptype);
152 break;
155 section->params = slist_remove (section->params, p);
156 xfree (p);
157 break;
162 void
163 config_clear_keys ()
165 MUTEX_LOCK (&rcfile_mutex);
166 unsigned i, t = slist_length (global_config);
168 for (i = 0; i < t; i++)
170 struct section_s *s = slist_nth_data (global_config, i);
171 if (!s)
172 continue;
174 section_remove_param (s, "passphrase");
177 MUTEX_UNLOCK (&rcfile_mutex);
180 static struct param_s *
181 config_has_param (struct section_s *s, const char *what)
183 unsigned i, t = slist_length (s->params);
185 for (i = 0; i < t; i++)
187 struct param_s *p = slist_nth_data (s->params, i);
188 if (!p)
189 break;
191 if (!strcmp (p->name, what))
192 return p;
195 return NULL;
198 static struct param_s *
199 config_get_param (struct slist_s *config,
200 const char *section, const char *what, int *exists)
202 unsigned i, t = slist_length (config);
204 *exists = 0;
206 for (i = 0; i < t; i++)
208 struct param_s *p;
209 struct section_s *s = slist_nth_data (config, i);
211 if (!s)
212 break;
214 if (strcmp (s->name, section))
215 continue;
217 p = config_has_param (s, what);
218 if (!p)
219 return NULL;
221 *exists = 1;
222 return p;
225 return NULL;
228 static struct section_s *
229 new_section (struct slist_s **config, const char *name)
231 struct slist_s *tmp;
232 struct section_s *s = xcalloc (1, sizeof (struct section_s));
234 if (!s)
235 return NULL;
237 s->name = str_dup (name);
238 if (!s->name)
240 log_write ("%s", pwmd_strerror (ENOMEM));
241 xfree (s);
242 return NULL;
245 tmp = slist_append (*config, s);
246 if (!tmp)
248 log_write ("%s", pwmd_strerror (ENOMEM));
249 xfree (s->name);
250 xfree (s);
251 return NULL;
254 *config = tmp;
255 return s;
259 config_set_string_param (struct slist_s **config, const char *section,
260 const char *name, const char *value)
262 struct section_s *s = config_find_section (*config, section);
264 if (!s)
266 s = new_section (config, section);
267 if (!s)
268 return 1;
271 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
274 char *
275 config_get_string_param (struct slist_s *config, const char *section,
276 const char *what, int *exists)
278 struct param_s *p = config_get_param (config, section, what, exists);
279 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
283 config_set_int_param (struct slist_s **config, const char *section,
284 const char *name, const char *value)
286 struct section_s *s = config_find_section (*config, section);
288 if (!s)
290 s = new_section (config, section);
291 if (!s)
292 return 1;
295 return new_param (s, NULL, 0, name, value, PARAM_INT);
299 config_get_int_param (struct slist_s *config, const char *section,
300 const char *what, int *exists)
302 struct param_s *p = config_get_param (config, section, what, exists);
303 return *exists ? p->value.itype : -1;
307 config_set_bool_param (struct slist_s **config, const char *section,
308 const char *name, const char *value)
310 struct section_s *s = config_find_section (*config, section);
312 if (!s)
314 s = new_section (config, section);
315 if (!s)
316 return 1;
319 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
323 config_get_bool_param (struct slist_s *config, const char *section,
324 const char *what, int *exists)
326 return config_get_int_param (config, section, what, exists);
330 config_set_long_param (struct slist_s **config, const char *section,
331 const char *name, const char *value)
333 struct section_s *s = config_find_section (*config, section);
335 if (!s)
337 s = new_section (config, section);
338 if (!s)
339 return 1;
342 return new_param (s, NULL, 0, name, value, PARAM_LONG);
345 unsigned long
346 config_get_ulong_param (struct slist_s *config, const char *section,
347 const char *what, int *exists)
349 struct param_s *p = config_get_param (config, section, what, exists);
350 return *exists ? p->value.ultype : 0;
353 long
354 config_get_long_param (struct slist_s *config, const char *section,
355 const char *what, int *exists)
357 struct param_s *p = config_get_param (config, section, what, exists);
358 return *exists ? p->value.ltype : -1;
362 config_set_longlong_param (struct slist_s **config, const char *section,
363 const char *name, const char *value)
365 struct section_s *s = config_find_section (*config, section);
367 if (!s)
369 s = new_section (config, section);
370 if (!s)
371 return 1;
374 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
377 long long
378 config_get_longlong_param (struct slist_s *config,
379 const char *section, const char *what, int *exists)
381 struct param_s *p = config_get_param (config, section, what, exists);
382 return *exists ? p->value.lltype : -1;
385 unsigned long long
386 config_get_ulonglong_param (struct slist_s *config,
387 const char *section,
388 const char *what, int *exists)
390 struct param_s *p = config_get_param (config, section, what, exists);
391 return *exists ? p->value.ulltype : 0;
395 config_set_list_param (struct slist_s **config, const char *section,
396 const char *name, const char *value)
398 struct section_s *s = config_find_section (*config, section);
400 if (!s)
402 s = new_section (config, section);
403 if (!s)
404 return 1;
407 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
410 char **
411 config_get_list_param (struct slist_s *config, const char *section,
412 const char *what, int *exists)
414 struct param_s *p = config_get_param (config, section, what, exists);
415 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
418 char *
419 config_get_string (const char *section, const char *what)
421 char *val = NULL;
422 const char *where = section ? section : "global";
423 int exists = 0;
425 MUTEX_LOCK (&rcfile_mutex);
426 val = config_get_string_param (global_config, where, what, &exists);
427 if (!exists && strcmp (section ? section : "", "global"))
428 val = config_get_string_param (global_config, "global", what, &exists);
430 MUTEX_UNLOCK (&rcfile_mutex);
431 return val;
434 char **
435 config_get_list (const char *section, const char *what)
437 char **val = NULL;
438 const char *where = section ? section : "global";
439 int exists = 0;
441 MUTEX_LOCK (&rcfile_mutex);
442 val = config_get_list_param (global_config, where, what, &exists);
443 if (!exists && strcmp (section ? section : "", "global"))
444 val = config_get_list_param (global_config, "global", what, &exists);
446 MUTEX_UNLOCK (&rcfile_mutex);
447 return val;
451 config_get_integer (const char *section, const char *what)
453 int val = 0;
454 const char *where = section ? section : "global";
455 int exists = 0;
457 MUTEX_LOCK (&rcfile_mutex);
458 val = config_get_int_param (global_config, where, what, &exists);
459 if (!exists && strcmp (section ? section : "", "global"))
460 val = config_get_int_param (global_config, "global", what, &exists);
462 MUTEX_UNLOCK (&rcfile_mutex);
463 return val;
466 long long
467 config_get_longlong (const char *section, const char *what)
469 long long val = 0;
470 const char *where = section ? section : "global";
471 int exists = 0;
473 MUTEX_LOCK (&rcfile_mutex);
474 val = config_get_longlong_param (global_config, where, what, &exists);
475 if (!exists && strcmp (section ? section : "", "global"))
476 val = config_get_longlong_param (global_config, "global", what, &exists);
478 MUTEX_UNLOCK (&rcfile_mutex);
479 return val;
482 unsigned long long
483 config_get_ulonglong (const char *section, const char *what)
485 unsigned long long val = 0;
486 const char *where = section ? section : "global";
487 int exists = 0;
489 MUTEX_LOCK (&rcfile_mutex);
490 val = config_get_ulonglong_param (global_config, where, what, &exists);
491 if (!exists && strcmp (section ? section : "", "global"))
492 val = config_get_ulonglong_param (global_config, "global", what, &exists);
494 MUTEX_UNLOCK (&rcfile_mutex);
495 return val;
498 long
499 config_get_long (const char *section, const char *what)
501 long val = 0;
502 const char *where = section ? section : "global";
503 int exists = 0;
505 MUTEX_LOCK (&rcfile_mutex);
506 val = config_get_long_param (global_config, where, what, &exists);
507 if (!exists && strcmp (section ? section : "", "global"))
508 val = config_get_long_param (global_config, "global", what, &exists);
510 MUTEX_UNLOCK (&rcfile_mutex);
511 return val;
514 unsigned long
515 config_get_ulong (const char *section, const char *what)
517 unsigned long val = 0;
518 const char *where = section ? section : "global";
519 int exists = 0;
521 MUTEX_LOCK (&rcfile_mutex);
522 val = config_get_ulong_param (global_config, where, what, &exists);
523 if (!exists && strcmp (section ? section : "", "global"))
524 val = config_get_ulong_param (global_config, "global", what, &exists);
526 MUTEX_UNLOCK (&rcfile_mutex);
527 return val;
531 config_get_boolean (const char *section, const char *what)
533 return config_get_integer (section, what);
536 char *
537 config_get_value (const char *section, const char *what)
539 const char *where = section ? section : "global";
540 int exists = 0;
541 int i;
542 int ival;
543 long lval;
544 long long llval;
545 unsigned long ulval;
546 unsigned long long ullval;
547 char *cpval;
548 char **cppval;
549 char *result = NULL;
551 MUTEX_LOCK (&rcfile_mutex);
553 for (i = 0; config_params[i].name; i++)
555 if (!strcmp (config_params[i].name, what))
557 switch (config_params[i].type)
559 case PARAM_BOOL:
560 case PARAM_INT:
561 ival = config_get_int_param (global_config, where, what,
562 &exists);
563 if (!exists && strcmp (section ? section : "", "global"))
564 ival = config_get_int_param (global_config, "global", what,
565 &exists);
566 result = str_asprintf ("%i", ival);
567 break;
568 case PARAM_CHARP:
569 cpval = config_get_string_param (global_config, where, what,
570 &exists);
571 if (!exists && strcmp (section ? section : "", "global"))
572 cpval =
573 config_get_string_param (global_config, "global", what,
574 &exists);
575 result = cpval;
576 break;
577 case PARAM_LONG:
578 lval = config_get_long_param (global_config, where, what,
579 &exists);
580 if (!exists && strcmp (section ? section : "", "global"))
581 lval = config_get_long_param (global_config, "global", what,
582 &exists);
583 result = str_asprintf ("%li", lval);
584 break;
585 case PARAM_ULONG:
586 ulval = config_get_ulong_param (global_config, where, what,
587 &exists);
588 if (!exists && strcmp (section ? section : "", "global"))
589 ulval = config_get_ulong_param (global_config, "global", what,
590 &exists);
591 result = str_asprintf ("%lu", ulval);
592 break;
593 case PARAM_LONGLONG:
594 llval = config_get_longlong_param (global_config, where, what,
595 &exists);
596 if (!exists && strcmp (section ? section : "", "global"))
597 llval = config_get_longlong_param (global_config, "global",
598 what, &exists);
599 result = str_asprintf ("%lli", llval);
600 break;
601 case PARAM_ULONGLONG:
602 ullval = config_get_ulonglong_param (global_config, where, what,
603 &exists);
604 if (!exists && strcmp (section ? section : "", "global"))
605 ullval = config_get_ulonglong_param (global_config, "global",
606 what, &exists);
607 result = str_asprintf ("%llu", ullval);
608 break;
609 case PARAM_CHARPP:
610 cppval = config_get_list_param (global_config, where, what,
611 &exists);
612 if (!exists && strcmp (section ? section : "", "global"))
613 cppval = config_get_list_param (global_config, "global", what,
614 &exists);
616 if (cppval)
617 result = strv_join (",", cppval);
619 strv_free (cppval);
620 break;
625 MUTEX_UNLOCK (&rcfile_mutex);
626 return result;
629 static int
630 set_defaults (struct slist_s **config)
632 char *s;
633 char **list;
634 int exists;
635 int i;
637 for (i = 0; config_params[i].name; i++)
639 switch (config_params[i].type)
641 case PARAM_BOOL:
642 config_get_bool_param (*config, "global", config_params[i].name,
643 &exists);
644 if (!exists)
646 if (config_set_bool_param
647 (config, "global", config_params[i].name,
648 config_params[i].value))
649 goto fail;
651 break;
652 case PARAM_INT:
653 config_get_int_param (*config, "global", config_params[i].name,
654 &exists);
655 if (!exists)
657 if (config_set_int_param
658 (config, "global", config_params[i].name,
659 config_params[i].value))
660 goto fail;
662 break;
663 case PARAM_CHARP:
664 s = config_get_string_param (*config, "global",
665 config_params[i].name, &exists);
666 xfree (s);
667 if (!exists && config_params[i].value)
669 if (config_set_string_param (config, "global",
670 config_params[i].name,
671 config_params[i].value))
672 goto fail;
674 break;
675 case PARAM_CHARPP:
676 list = config_get_list_param (*config, "global",
677 config_params[i].name, &exists);
678 strv_free (list);
679 if (!exists && config_params[i].value)
681 if (config_set_list_param (config, "global",
682 config_params[i].name,
683 config_params[i].value))
684 goto fail;
686 break;
687 case PARAM_LONG:
688 config_get_long_param (*config, "global", config_params[i].name,
689 &exists);
690 if (!exists)
692 if (config_set_long_param
693 (config, "global", config_params[i].name,
694 config_params[i].value))
695 goto fail;
697 break;
698 case PARAM_LONGLONG:
699 config_get_longlong_param (*config, "global", config_params[i].name,
700 &exists);
701 if (!exists)
703 if (config_set_longlong_param (config, "global",
704 config_params[i].name,
705 config_params[i].value))
706 goto fail;
708 break;
712 list = config_get_list_param (*config, "global", "allowed", &exists);
713 strv_free (list);
714 if (!exists)
716 if (config_set_list_param
717 (config, "global", "allowed", get_username ()))
718 goto fail;
721 max_recursion_depth = config_get_int_param (*config, "global",
722 "recursion_depth", &exists);
723 disable_list_and_dump = config_get_bool_param (*config, "global",
724 "disable_list_and_dump",
725 &exists);
726 #ifdef HAVE_MLOCKALL
727 disable_mlock =
728 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
729 #endif
730 return 0;
732 fail:
733 return 1;
736 static struct section_s *
737 config_find_section (struct slist_s *config, const char *name)
739 unsigned i, t = slist_length (config);
741 for (i = 0; i < t; i++)
743 struct section_s *s = slist_nth_data (config, i);
745 if (!strcmp (s->name, name))
746 return s;
749 return NULL;
752 /* Append a new parameter to the list of parameters for a file
753 * section. When an existing parameter of the same name exists, its
754 * value is updated.
756 static int
757 new_param (struct section_s *section, const char *filename, int lineno,
758 const char *name, const char *value, int type)
760 struct param_s *param = NULL;
761 struct slist_s *tmp;
762 char *e;
763 unsigned i, t = slist_length (section->params);
764 int dup = 0;
766 for (i = 0; i < t; i++)
768 struct param_s *p = slist_nth_data (section->params, i);
769 if (!p)
770 break;
772 if (!strcmp (name, p->name))
774 param = p;
775 dup = 1;
776 break;
780 if (!param)
782 param = xcalloc (1, sizeof (struct param_s));
783 if (!param)
785 log_write ("%s", pwmd_strerror (ENOMEM));
786 return 1;
789 param->name = str_dup (name);
790 if (!param->name)
792 xfree (param);
793 log_write ("%s", pwmd_strerror (ENOMEM));
794 return 1;
798 param->type = type;
800 switch (type)
802 case PARAM_BOOL:
803 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
804 || !strcasecmp (value, "false"))
805 param->value.itype = 0;
806 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
807 || !strcasecmp (value, "true"))
808 param->value.itype = 1;
809 else
811 INVALID_VALUE (filename, lineno);
812 goto fail;
814 param->type = PARAM_INT;
815 break;
816 case PARAM_CHARP:
817 xfree (param->value.cptype);
818 param->value.cptype = value ? str_dup (value) : NULL;
819 if (value && !param->value.cptype)
821 log_write ("%s", pwmd_strerror (ENOMEM));
822 goto fail;
824 break;
825 case PARAM_CHARPP:
826 strv_free (param->value.cpptype);
827 param->value.cpptype = value ? str_split (value, ",", 0) : NULL;
828 if (value && !param->value.cpptype)
830 log_write ("%s", pwmd_strerror (ENOMEM));
831 goto fail;
833 break;
834 case PARAM_INT:
835 param->value.itype = strtol (value, &e, 10);
836 if (e && *e)
838 INVALID_VALUE (filename, lineno);
839 goto fail;
841 break;
842 case PARAM_LONG:
843 param->value.ltype = strtol (value, &e, 10);
844 if (e && *e)
846 INVALID_VALUE (filename, lineno);
847 goto fail;
849 break;
850 case PARAM_LONGLONG:
851 param->value.lltype = strtoll (value, &e, 10);
852 if (e && *e)
854 INVALID_VALUE (filename, lineno);
855 goto fail;
857 break;
858 case PARAM_ULONGLONG:
859 param->value.ulltype = strtoull (value, &e, 10);
860 if (e && *e)
862 INVALID_VALUE (filename, lineno);
863 goto fail;
865 break;
866 case PARAM_ULONG:
867 param->value.ultype = strtoul (value, &e, 10);
868 if (e && *e)
870 INVALID_VALUE (filename, lineno);
871 goto fail;
873 break;
876 if (dup)
877 return 0;
879 tmp = slist_append (section->params, param);
880 if (!tmp)
882 log_write ("%s", pwmd_strerror (ENOMEM));
883 goto fail;
886 section->params = tmp;
887 return 0;
889 fail:
890 xfree (param->name);
891 xfree (param);
892 return 1;
895 struct slist_s *
896 config_parse (const char *filename)
898 struct slist_s *tmpconfig = NULL, *tmp;
899 struct section_s *cur_section = NULL;
900 char buf[LINE_MAX];
901 char *s;
902 int lineno = 1;
903 int have_global = 0;
904 FILE *fp = fopen (filename, "r");
906 if (!fp)
908 log_write ("%s: %s", filename,
909 pwmd_strerror (gpg_error_from_syserror ()));
911 if (errno != ENOENT)
912 return NULL;
914 log_write (_("Using defaults!"));
915 goto defaults;
918 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
920 char line[LINE_MAX] = { 0 };
921 size_t len = 0;
923 if (*s == '#')
924 continue;
926 s = str_chomp (s);
927 for (; s && *s; s++)
929 int match = 0;
931 /* New file section. */
932 if (*s == '[')
934 struct section_s *section;
935 char *p = strchr (++s, ']');
937 if (!p)
939 log_write (_("%s(%i): unbalanced braces"), filename,
940 lineno);
941 goto fail;
944 len = strlen (s) - strlen (p);
945 memcpy (line, s, len);
946 line[len] = 0;
948 section = config_find_section (tmpconfig, line);
949 if (section)
951 log_write (_("%s(%i): section '%s' already exists!"),
952 filename, lineno, line);
953 goto fail;
956 if (!strcmp (line, "global"))
957 have_global = 1;
959 section = xcalloc (1, sizeof (struct section_s));
960 section->name = str_dup (line);
962 if (cur_section)
964 tmp = slist_append (tmpconfig, cur_section);
965 if (!tmp)
967 log_write ("%s", pwmd_strerror (ENOMEM));
968 goto fail;
971 tmpconfig = tmp;
974 cur_section = section;
975 break;
978 if (!cur_section)
980 log_write (_("%s(%i): parameter outside of section!"), filename,
981 lineno);
982 goto fail;
985 /* Parameters for each section. */
986 for (int m = 0; config_params[m].name; m++)
988 size_t len = strlen (config_params[m].name);
990 if (!strncmp (s, config_params[m].name, len))
992 char *p = s + len;
994 while (*p && *p == ' ')
995 p++;
997 if (!*p || *p != '=')
998 continue;
1000 p++;
1001 while (*p && isspace (*p))
1002 p++;
1004 s[len] = 0;
1005 if (new_param (cur_section, filename, lineno, s, p,
1006 config_params[m].type))
1007 goto fail;
1009 match = 1;
1010 break;
1014 if (!match)
1016 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1017 goto fail;
1020 break;
1024 fclose (fp);
1026 if (cur_section)
1028 tmp = slist_append (tmpconfig, cur_section);
1029 if (!tmp)
1031 log_write ("%s", pwmd_strerror (ENOMEM));
1032 goto fail;
1035 cur_section = NULL;
1036 tmpconfig = tmp;
1039 if (!have_global)
1040 log_write (_
1041 ("WARNING: %s: could not find a [global] configuration section!"),
1042 filename);
1044 defaults:
1045 if (set_defaults (&tmpconfig))
1046 goto fail;
1048 return tmpconfig;
1050 fail:
1051 fclose (fp);
1052 config_free (tmpconfig);
1053 free_section (cur_section);
1054 return NULL;
1057 static void
1058 free_section (struct section_s *s)
1060 if (!s)
1061 return;
1063 for (;;)
1065 struct param_s *p = slist_nth_data (s->params, 0);
1067 if (!p)
1068 break;
1070 section_remove_param (s, p->name);
1073 s->params = NULL;
1076 void
1077 config_free (struct slist_s *config)
1079 for (;;)
1081 struct section_s *s = slist_nth_data (config, 0);
1082 if (!s)
1083 break;
1085 free_section (s);
1086 config = slist_remove (config, s);
1087 xfree (s);