Version 3.0.0.
[pwmd.git] / src / rcfile.c
blobac7bf12db377584e5e876f06777d211ff570bd17
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, "true"},
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, "true"},
71 { "cache_timeout", PARAM_INT, "-1"},
72 { "cache_push", PARAM_CHARPP, NULL},
73 { "disable_list_and_dump", PARAM_BOOL, "false"},
74 { "recursion_depth", PARAM_INT, "100"},
75 { "syslog", PARAM_BOOL, "false"},
76 { "xfer_progress", PARAM_INT, "8196"},
77 { "allowed", PARAM_CHARPP, NULL},
78 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
79 { "cipher", PARAM_CHARP, "aes256"},
80 { "kill_scd", PARAM_BOOL, "false"},
81 { "cipher_iterations", PARAM_ULONGLONG, "0"},
82 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
83 { "priority", PARAM_INT, INVALID_PRIORITY},
84 { "keepalive_interval", PARAM_INT, "5"},
85 { "tcp_port", PARAM_INT, "6466"},
86 { "enable_tcp", PARAM_BOOL, "false"},
87 { "tcp_require_key", PARAM_BOOL, "false"},
88 { "tcp_wait", PARAM_INT, "0"},
89 { "tcp_bind", PARAM_CHARP, "any"},
90 { "tcp_interface", PARAM_CHARP, NULL},
91 { "tls_timeout", PARAM_INT, "300"},
92 { "tls_cipher_suite", PARAM_CHARP, "SECURE256"},
93 { "tls_access", PARAM_CHARPP, NULL},
94 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
95 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
96 { "use_agent", PARAM_BOOL, "false"},
97 { "require_save_key", PARAM_BOOL, "true"},
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->name);
157 xfree (p);
158 break;
163 void
164 config_clear_keys ()
166 MUTEX_LOCK (&rcfile_mutex);
167 unsigned i, t = slist_length (global_config);
169 for (i = 0; i < t; i++)
171 struct section_s *s = slist_nth_data (global_config, i);
172 if (!s)
173 continue;
175 section_remove_param (s, "passphrase");
178 MUTEX_UNLOCK (&rcfile_mutex);
181 static struct param_s *
182 config_has_param (struct section_s *s, const char *what)
184 unsigned i, t = slist_length (s->params);
186 for (i = 0; i < t; i++)
188 struct param_s *p = slist_nth_data (s->params, i);
189 if (!p)
190 break;
192 if (!strcmp (p->name, what))
193 return p;
196 return NULL;
199 static struct param_s *
200 config_get_param (struct slist_s *config,
201 const char *section, const char *what, int *exists)
203 unsigned i, t = slist_length (config);
205 *exists = 0;
207 for (i = 0; i < t; i++)
209 struct param_s *p;
210 struct section_s *s = slist_nth_data (config, i);
212 if (!s)
213 break;
215 if (strcmp (s->name, section))
216 continue;
218 p = config_has_param (s, what);
219 if (!p)
220 return NULL;
222 *exists = 1;
223 return p;
226 return NULL;
229 static struct section_s *
230 new_section (struct slist_s **config, const char *name)
232 struct slist_s *tmp;
233 struct section_s *s = xcalloc (1, sizeof (struct section_s));
235 if (!s)
236 return NULL;
238 s->name = str_dup (name);
239 if (!s->name)
241 log_write ("%s", pwmd_strerror (ENOMEM));
242 xfree (s);
243 return NULL;
246 tmp = slist_append (*config, s);
247 if (!tmp)
249 log_write ("%s", pwmd_strerror (ENOMEM));
250 xfree (s->name);
251 xfree (s);
252 return NULL;
255 *config = tmp;
256 return s;
260 config_set_string_param (struct slist_s **config, const char *section,
261 const char *name, const char *value)
263 struct section_s *s = config_find_section (*config, section);
265 if (!s)
267 s = new_section (config, section);
268 if (!s)
269 return 1;
272 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
275 char *
276 config_get_string_param (struct slist_s *config, const char *section,
277 const char *what, int *exists)
279 struct param_s *p = config_get_param (config, section, what, exists);
280 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
284 config_set_int_param (struct slist_s **config, const char *section,
285 const char *name, const char *value)
287 struct section_s *s = config_find_section (*config, section);
289 if (!s)
291 s = new_section (config, section);
292 if (!s)
293 return 1;
296 return new_param (s, NULL, 0, name, value, PARAM_INT);
300 config_get_int_param (struct slist_s *config, const char *section,
301 const char *what, int *exists)
303 struct param_s *p = config_get_param (config, section, what, exists);
304 return *exists ? p->value.itype : -1;
308 config_set_bool_param (struct slist_s **config, const char *section,
309 const char *name, const char *value)
311 struct section_s *s = config_find_section (*config, section);
313 if (!s)
315 s = new_section (config, section);
316 if (!s)
317 return 1;
320 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
324 config_get_bool_param (struct slist_s *config, const char *section,
325 const char *what, int *exists)
327 return config_get_int_param (config, section, what, exists);
331 config_set_long_param (struct slist_s **config, const char *section,
332 const char *name, const char *value)
334 struct section_s *s = config_find_section (*config, section);
336 if (!s)
338 s = new_section (config, section);
339 if (!s)
340 return 1;
343 return new_param (s, NULL, 0, name, value, PARAM_LONG);
346 unsigned long
347 config_get_ulong_param (struct slist_s *config, const char *section,
348 const char *what, int *exists)
350 struct param_s *p = config_get_param (config, section, what, exists);
351 return *exists ? p->value.ultype : 0;
354 long
355 config_get_long_param (struct slist_s *config, const char *section,
356 const char *what, int *exists)
358 struct param_s *p = config_get_param (config, section, what, exists);
359 return *exists ? p->value.ltype : -1;
363 config_set_longlong_param (struct slist_s **config, const char *section,
364 const char *name, const char *value)
366 struct section_s *s = config_find_section (*config, section);
368 if (!s)
370 s = new_section (config, section);
371 if (!s)
372 return 1;
375 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
378 long long
379 config_get_longlong_param (struct slist_s *config,
380 const char *section, const char *what, int *exists)
382 struct param_s *p = config_get_param (config, section, what, exists);
383 return *exists ? p->value.lltype : -1;
386 unsigned long long
387 config_get_ulonglong_param (struct slist_s *config,
388 const char *section,
389 const char *what, int *exists)
391 struct param_s *p = config_get_param (config, section, what, exists);
392 return *exists ? p->value.ulltype : 0;
396 config_set_list_param (struct slist_s **config, const char *section,
397 const char *name, const char *value)
399 struct section_s *s = config_find_section (*config, section);
401 if (!s)
403 s = new_section (config, section);
404 if (!s)
405 return 1;
408 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
411 char **
412 config_get_list_param (struct slist_s *config, const char *section,
413 const char *what, int *exists)
415 struct param_s *p = config_get_param (config, section, what, exists);
416 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
419 char *
420 config_get_string (const char *section, const char *what)
422 char *val = NULL;
423 const char *where = section ? section : "global";
424 int exists = 0;
426 MUTEX_LOCK (&rcfile_mutex);
427 val = config_get_string_param (global_config, where, what, &exists);
428 if (!exists && strcmp (section ? section : "", "global"))
429 val = config_get_string_param (global_config, "global", what, &exists);
431 MUTEX_UNLOCK (&rcfile_mutex);
432 return val;
435 char **
436 config_get_list (const char *section, const char *what)
438 char **val = NULL;
439 const char *where = section ? section : "global";
440 int exists = 0;
442 MUTEX_LOCK (&rcfile_mutex);
443 val = config_get_list_param (global_config, where, what, &exists);
444 if (!exists && strcmp (section ? section : "", "global"))
445 val = config_get_list_param (global_config, "global", what, &exists);
447 MUTEX_UNLOCK (&rcfile_mutex);
448 return val;
452 config_get_integer (const char *section, const char *what)
454 int val = 0;
455 const char *where = section ? section : "global";
456 int exists = 0;
458 MUTEX_LOCK (&rcfile_mutex);
459 val = config_get_int_param (global_config, where, what, &exists);
460 if (!exists && strcmp (section ? section : "", "global"))
461 val = config_get_int_param (global_config, "global", what, &exists);
463 MUTEX_UNLOCK (&rcfile_mutex);
464 return val;
467 long long
468 config_get_longlong (const char *section, const char *what)
470 long long val = 0;
471 const char *where = section ? section : "global";
472 int exists = 0;
474 MUTEX_LOCK (&rcfile_mutex);
475 val = config_get_longlong_param (global_config, where, what, &exists);
476 if (!exists && strcmp (section ? section : "", "global"))
477 val = config_get_longlong_param (global_config, "global", what, &exists);
479 MUTEX_UNLOCK (&rcfile_mutex);
480 return val;
483 unsigned long long
484 config_get_ulonglong (const char *section, const char *what)
486 unsigned long long val = 0;
487 const char *where = section ? section : "global";
488 int exists = 0;
490 MUTEX_LOCK (&rcfile_mutex);
491 val = config_get_ulonglong_param (global_config, where, what, &exists);
492 if (!exists && strcmp (section ? section : "", "global"))
493 val = config_get_ulonglong_param (global_config, "global", what, &exists);
495 MUTEX_UNLOCK (&rcfile_mutex);
496 return val;
499 long
500 config_get_long (const char *section, const char *what)
502 long val = 0;
503 const char *where = section ? section : "global";
504 int exists = 0;
506 MUTEX_LOCK (&rcfile_mutex);
507 val = config_get_long_param (global_config, where, what, &exists);
508 if (!exists && strcmp (section ? section : "", "global"))
509 val = config_get_long_param (global_config, "global", what, &exists);
511 MUTEX_UNLOCK (&rcfile_mutex);
512 return val;
515 unsigned long
516 config_get_ulong (const char *section, const char *what)
518 unsigned long val = 0;
519 const char *where = section ? section : "global";
520 int exists = 0;
522 MUTEX_LOCK (&rcfile_mutex);
523 val = config_get_ulong_param (global_config, where, what, &exists);
524 if (!exists && strcmp (section ? section : "", "global"))
525 val = config_get_ulong_param (global_config, "global", what, &exists);
527 MUTEX_UNLOCK (&rcfile_mutex);
528 return val;
532 config_get_boolean (const char *section, const char *what)
534 return config_get_integer (section, what);
537 char *
538 config_get_value (const char *section, const char *what)
540 const char *where = section ? section : "global";
541 int exists = 0;
542 int i;
543 int ival;
544 long lval;
545 long long llval;
546 unsigned long ulval;
547 unsigned long long ullval;
548 char *cpval;
549 char **cppval;
550 char *result = NULL;
552 MUTEX_LOCK (&rcfile_mutex);
554 for (i = 0; config_params[i].name; i++)
556 if (!strcmp (config_params[i].name, what))
558 switch (config_params[i].type)
560 case PARAM_BOOL:
561 case PARAM_INT:
562 ival = config_get_int_param (global_config, where, what,
563 &exists);
564 if (!exists && strcmp (section ? section : "", "global"))
565 ival = config_get_int_param (global_config, "global", what,
566 &exists);
567 result = str_asprintf ("%i", ival);
568 break;
569 case PARAM_CHARP:
570 cpval = config_get_string_param (global_config, where, what,
571 &exists);
572 if (!exists && strcmp (section ? section : "", "global"))
573 cpval =
574 config_get_string_param (global_config, "global", what,
575 &exists);
576 result = cpval;
577 break;
578 case PARAM_LONG:
579 lval = config_get_long_param (global_config, where, what,
580 &exists);
581 if (!exists && strcmp (section ? section : "", "global"))
582 lval = config_get_long_param (global_config, "global", what,
583 &exists);
584 result = str_asprintf ("%li", lval);
585 break;
586 case PARAM_ULONG:
587 ulval = config_get_ulong_param (global_config, where, what,
588 &exists);
589 if (!exists && strcmp (section ? section : "", "global"))
590 ulval = config_get_ulong_param (global_config, "global", what,
591 &exists);
592 result = str_asprintf ("%lu", ulval);
593 break;
594 case PARAM_LONGLONG:
595 llval = config_get_longlong_param (global_config, where, what,
596 &exists);
597 if (!exists && strcmp (section ? section : "", "global"))
598 llval = config_get_longlong_param (global_config, "global",
599 what, &exists);
600 result = str_asprintf ("%lli", llval);
601 break;
602 case PARAM_ULONGLONG:
603 ullval = config_get_ulonglong_param (global_config, where, what,
604 &exists);
605 if (!exists && strcmp (section ? section : "", "global"))
606 ullval = config_get_ulonglong_param (global_config, "global",
607 what, &exists);
608 result = str_asprintf ("%llu", ullval);
609 break;
610 case PARAM_CHARPP:
611 cppval = config_get_list_param (global_config, where, what,
612 &exists);
613 if (!exists && strcmp (section ? section : "", "global"))
614 cppval = config_get_list_param (global_config, "global", what,
615 &exists);
617 if (cppval)
618 result = strv_join (",", cppval);
620 strv_free (cppval);
621 break;
626 MUTEX_UNLOCK (&rcfile_mutex);
627 return result;
630 static int
631 set_defaults (struct slist_s **config)
633 char *s;
634 char **list;
635 int exists;
636 int i;
638 for (i = 0; config_params[i].name; i++)
640 switch (config_params[i].type)
642 case PARAM_BOOL:
643 config_get_bool_param (*config, "global", config_params[i].name,
644 &exists);
645 if (!exists)
647 if (config_set_bool_param
648 (config, "global", config_params[i].name,
649 config_params[i].value))
650 goto fail;
652 break;
653 case PARAM_INT:
654 config_get_int_param (*config, "global", config_params[i].name,
655 &exists);
656 if (!exists)
658 if (config_set_int_param
659 (config, "global", config_params[i].name,
660 config_params[i].value))
661 goto fail;
663 break;
664 case PARAM_CHARP:
665 s = config_get_string_param (*config, "global",
666 config_params[i].name, &exists);
667 xfree (s);
668 if (!exists && config_params[i].value)
670 if (config_set_string_param (config, "global",
671 config_params[i].name,
672 config_params[i].value))
673 goto fail;
675 break;
676 case PARAM_CHARPP:
677 list = config_get_list_param (*config, "global",
678 config_params[i].name, &exists);
679 strv_free (list);
680 if (!exists && config_params[i].value)
682 if (config_set_list_param (config, "global",
683 config_params[i].name,
684 config_params[i].value))
685 goto fail;
687 break;
688 case PARAM_LONG:
689 config_get_long_param (*config, "global", config_params[i].name,
690 &exists);
691 if (!exists)
693 if (config_set_long_param
694 (config, "global", config_params[i].name,
695 config_params[i].value))
696 goto fail;
698 break;
699 case PARAM_LONGLONG:
700 config_get_longlong_param (*config, "global", config_params[i].name,
701 &exists);
702 if (!exists)
704 if (config_set_longlong_param (config, "global",
705 config_params[i].name,
706 config_params[i].value))
707 goto fail;
709 break;
713 list = config_get_list_param (*config, "global", "allowed", &exists);
714 strv_free (list);
715 if (!exists)
717 if (config_set_list_param
718 (config, "global", "allowed", get_username ()))
719 goto fail;
722 max_recursion_depth = config_get_int_param (*config, "global",
723 "recursion_depth", &exists);
724 disable_list_and_dump = config_get_bool_param (*config, "global",
725 "disable_list_and_dump",
726 &exists);
727 #ifdef HAVE_MLOCKALL
728 disable_mlock =
729 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
730 #endif
731 return 0;
733 fail:
734 return 1;
737 static struct section_s *
738 config_find_section (struct slist_s *config, const char *name)
740 unsigned i, t = slist_length (config);
742 for (i = 0; i < t; i++)
744 struct section_s *s = slist_nth_data (config, i);
746 if (!strcmp (s->name, name))
747 return s;
750 return NULL;
753 /* Append a new parameter to the list of parameters for a file
754 * section. When an existing parameter of the same name exists, its
755 * value is updated.
757 static int
758 new_param (struct section_s *section, const char *filename, int lineno,
759 const char *name, const char *value, int type)
761 struct param_s *param = NULL;
762 struct slist_s *tmp;
763 char *e;
764 unsigned i, t = slist_length (section->params);
765 int dup = 0;
767 for (i = 0; i < t; i++)
769 struct param_s *p = slist_nth_data (section->params, i);
770 if (!p)
771 break;
773 if (!strcmp (name, p->name))
775 param = p;
776 dup = 1;
777 break;
781 if (!param)
783 param = xcalloc (1, sizeof (struct param_s));
784 if (!param)
786 log_write ("%s", pwmd_strerror (ENOMEM));
787 return 1;
790 param->name = str_dup (name);
791 if (!param->name)
793 xfree (param);
794 log_write ("%s", pwmd_strerror (ENOMEM));
795 return 1;
799 param->type = type;
801 switch (type)
803 case PARAM_BOOL:
804 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
805 || !strcasecmp (value, "false"))
806 param->value.itype = 0;
807 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
808 || !strcasecmp (value, "true"))
809 param->value.itype = 1;
810 else
812 INVALID_VALUE (filename, lineno);
813 goto fail;
815 param->type = PARAM_INT;
816 break;
817 case PARAM_CHARP:
818 xfree (param->value.cptype);
819 param->value.cptype = value ? str_dup (value) : NULL;
820 if (value && !param->value.cptype)
822 log_write ("%s", pwmd_strerror (ENOMEM));
823 goto fail;
825 break;
826 case PARAM_CHARPP:
827 strv_free (param->value.cpptype);
828 param->value.cpptype = value ? str_split (value, ",", 0) : NULL;
829 if (value && !param->value.cpptype)
831 log_write ("%s", pwmd_strerror (ENOMEM));
832 goto fail;
834 break;
835 case PARAM_INT:
836 param->value.itype = strtol (value, &e, 10);
837 if (e && *e)
839 INVALID_VALUE (filename, lineno);
840 goto fail;
842 break;
843 case PARAM_LONG:
844 param->value.ltype = strtol (value, &e, 10);
845 if (e && *e)
847 INVALID_VALUE (filename, lineno);
848 goto fail;
850 break;
851 case PARAM_LONGLONG:
852 param->value.lltype = strtoll (value, &e, 10);
853 if (e && *e)
855 INVALID_VALUE (filename, lineno);
856 goto fail;
858 break;
859 case PARAM_ULONGLONG:
860 param->value.ulltype = strtoull (value, &e, 10);
861 if (e && *e)
863 INVALID_VALUE (filename, lineno);
864 goto fail;
866 break;
867 case PARAM_ULONG:
868 param->value.ultype = strtoul (value, &e, 10);
869 if (e && *e)
871 INVALID_VALUE (filename, lineno);
872 goto fail;
874 break;
877 if (dup)
878 return 0;
880 tmp = slist_append (section->params, param);
881 if (!tmp)
883 log_write ("%s", pwmd_strerror (ENOMEM));
884 goto fail;
887 section->params = tmp;
888 return 0;
890 fail:
891 xfree (param->name);
892 xfree (param);
893 return 1;
896 struct slist_s *
897 config_parse (const char *filename)
899 struct slist_s *tmpconfig = NULL, *tmp;
900 struct section_s *cur_section = NULL;
901 char buf[LINE_MAX];
902 char *s;
903 int lineno = 1;
904 int have_global = 0;
905 FILE *fp = fopen (filename, "r");
907 if (!fp)
909 log_write ("%s: %s", filename,
910 pwmd_strerror (gpg_error_from_errno (errno)));
912 if (errno != ENOENT)
913 return NULL;
915 log_write (_("Using defaults!"));
916 goto defaults;
919 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
921 char line[LINE_MAX] = { 0 };
922 size_t len = 0;
924 if (*s == '#')
925 continue;
927 s = str_chomp (s);
928 for (; s && *s; s++)
930 int match = 0;
932 /* New file section. */
933 if (*s == '[')
935 struct section_s *section;
936 char *p = strchr (++s, ']');
938 if (!p)
940 log_write (_("%s(%i): unbalanced braces"), filename,
941 lineno);
942 goto fail;
945 len = strlen (s) - strlen (p);
946 memcpy (line, s, len);
947 line[len] = 0;
949 section = config_find_section (tmpconfig, line);
950 if (section)
952 log_write (_("%s(%i): section '%s' already exists!"),
953 filename, lineno, line);
954 goto fail;
957 if (!strcmp (line, "global"))
958 have_global = 1;
960 section = xcalloc (1, sizeof (struct section_s));
961 section->name = str_dup (line);
963 if (cur_section)
965 tmp = slist_append (tmpconfig, cur_section);
966 if (!tmp)
968 log_write ("%s", pwmd_strerror (ENOMEM));
969 goto fail;
972 tmpconfig = tmp;
975 cur_section = section;
976 break;
979 if (!cur_section)
981 log_write (_("%s(%i): parameter outside of section!"), filename,
982 lineno);
983 goto fail;
986 /* Parameters for each section. */
987 for (int m = 0; config_params[m].name; m++)
989 size_t len = strlen (config_params[m].name);
991 if (!strncmp (s, config_params[m].name, len))
993 char *p = s + len;
995 while (*p && *p == ' ')
996 p++;
998 if (!*p || *p != '=')
999 continue;
1001 p++;
1002 while (*p && isspace (*p))
1003 p++;
1005 s[len] = 0;
1006 if (new_param (cur_section, filename, lineno, s, p,
1007 config_params[m].type))
1008 goto fail;
1010 match = 1;
1011 break;
1015 if (!match)
1017 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1018 goto fail;
1021 break;
1025 fclose (fp);
1027 if (cur_section)
1029 tmp = slist_append (tmpconfig, cur_section);
1030 if (!tmp)
1032 log_write ("%s", pwmd_strerror (ENOMEM));
1033 goto fail;
1036 cur_section = NULL;
1037 tmpconfig = tmp;
1040 if (!have_global)
1041 log_write (_
1042 ("WARNING: %s: could not find a [global] configuration section!"),
1043 filename);
1045 defaults:
1046 if (set_defaults (&tmpconfig))
1047 goto fail;
1049 return tmpconfig;
1051 fail:
1052 fclose (fp);
1053 config_free (tmpconfig);
1054 free_section (cur_section);
1055 return NULL;
1058 static void
1059 free_section (struct section_s *s)
1061 if (!s)
1062 return;
1064 for (;;)
1066 struct param_s *p = slist_nth_data (s->params, 0);
1068 if (!p)
1069 break;
1071 section_remove_param (s, p->name);
1074 s->params = NULL;
1075 xfree (s->name);
1076 s->name = NULL;
1079 void
1080 config_free (struct slist_s *config)
1082 for (;;)
1084 struct section_s *s = slist_nth_data (config, 0);
1085 if (!s)
1086 break;
1088 free_section (s);
1089 config = slist_remove (config, s);
1090 xfree (s);