Add configuration parameter "log_keepopen".
[pwmd.git] / src / rcfile.c
blob6f82e8df48de765464134a3baeba81b1415e9258
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_keepopen", PARAM_BOOL, "true"},
72 { "log_level", PARAM_INT, "0"},
73 { "disable_mlockall", PARAM_BOOL, "true"},
74 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
75 { "cache_push", PARAM_CHARPP, NULL},
76 { "disable_list_and_dump", PARAM_BOOL, "false"},
77 { "recursion_depth", PARAM_INT, "100"},
78 { "syslog", PARAM_BOOL, "false"},
79 { "xfer_progress", PARAM_INT, "8196"},
80 { "allowed", PARAM_CHARPP, NULL},
81 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
82 { "cipher", PARAM_CHARP, "aes256"},
83 { "kill_scd", PARAM_BOOL, "false"},
84 { "cipher_iterations", PARAM_ULONGLONG, "0"},
85 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
86 { "priority", PARAM_INT, INVALID_PRIORITY},
87 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
88 { "tcp_port", PARAM_INT, "6466"},
89 { "enable_tcp", PARAM_BOOL, "false"},
90 { "tcp_require_key", PARAM_BOOL, "false"},
91 { "tcp_wait", PARAM_INT, "0"},
92 { "tcp_bind", PARAM_CHARP, "any"},
93 { "tcp_interface", PARAM_CHARP, NULL},
94 { "tls_timeout", PARAM_INT, "300"},
95 { "tls_cipher_suite", PARAM_CHARP, "SECURE256"},
96 { "tls_access", PARAM_CHARPP, NULL},
97 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
98 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
99 { "use_agent", PARAM_BOOL, "false"},
100 { "require_save_key", PARAM_BOOL, "true"},
101 { NULL, 0, NULL},
104 struct config_param_s
106 char *name;
107 int type;
108 union
110 int itype;
111 char *cptype;
112 char **cpptype;
113 long ltype;
114 long long lltype;
115 unsigned long ultype;
116 unsigned long long ulltype;
117 } value;
120 static struct config_section_s *config_find_section (struct slist_s *config,
121 const char *name);
122 static int new_param (struct config_section_s *section, const char *filename,
123 int lineno, const char *name, const char *value,
124 int type);
125 static void free_section (struct config_section_s *s);
126 static int set_defaults (struct slist_s **config);
128 static void
129 section_remove_param (struct config_section_s *section, const char *name)
131 unsigned i, t = slist_length (section->params);
133 for (i = 0; i < t; i++)
135 struct config_param_s *p = slist_nth_data (section->params, i);
137 if (!p)
138 continue;
140 if (!strcmp (p->name, name))
142 switch (p->type)
144 case PARAM_CHARP:
145 xfree (p->value.cptype);
146 break;
147 case PARAM_CHARPP:
148 strv_free (p->value.cpptype);
149 break;
152 section->params = slist_remove (section->params, p);
153 xfree (p->name);
154 xfree (p);
155 break;
160 void
161 config_clear_keys ()
163 MUTEX_LOCK (&rcfile_mutex);
164 unsigned i, t = slist_length (global_config);
166 for (i = 0; i < t; i++)
168 struct config_section_s *s = slist_nth_data (global_config, i);
169 if (!s)
170 continue;
172 section_remove_param (s, "passphrase");
175 MUTEX_UNLOCK (&rcfile_mutex);
178 static struct config_param_s *
179 config_has_param (struct config_section_s *s, const char *what)
181 unsigned i, t = slist_length (s->params);
183 for (i = 0; i < t; i++)
185 struct config_param_s *p = slist_nth_data (s->params, i);
186 if (!p)
187 break;
189 if (!strcmp (p->name, what))
190 return p;
193 return NULL;
196 static struct config_param_s *
197 config_get_param (struct slist_s *config,
198 const char *section, const char *what, int *exists)
200 unsigned i, t = slist_length (config);
202 *exists = 0;
204 for (i = 0; i < t; i++)
206 struct config_param_s *p;
207 struct config_section_s *s = slist_nth_data (config, i);
209 if (!s)
210 break;
212 if (strcmp (s->name, section))
213 continue;
215 p = config_has_param (s, what);
216 if (!p)
217 return NULL;
219 *exists = 1;
220 return p;
223 return NULL;
226 static struct config_section_s *
227 new_section (struct slist_s **config, const char *name)
229 struct slist_s *tmp;
230 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
232 if (!s)
233 return NULL;
235 s->name = str_dup (name);
236 if (!s->name)
238 log_write ("%s", pwmd_strerror (ENOMEM));
239 xfree (s);
240 return NULL;
243 tmp = slist_append (*config, s);
244 if (!tmp)
246 log_write ("%s", pwmd_strerror (ENOMEM));
247 xfree (s->name);
248 xfree (s);
249 return NULL;
252 *config = tmp;
253 return s;
257 config_set_string_param (struct slist_s **config, const char *section,
258 const char *name, const char *value)
260 struct config_section_s *s = config_find_section (*config, section);
262 if (!s)
264 s = new_section (config, section);
265 if (!s)
266 return 1;
269 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
272 char *
273 config_get_string_param (struct slist_s *config, const char *section,
274 const char *what, int *exists)
276 struct config_param_s *p = config_get_param (config, section, what, exists);
277 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
281 config_set_int_param (struct slist_s **config, const char *section,
282 const char *name, const char *value)
284 struct config_section_s *s = config_find_section (*config, section);
286 if (!s)
288 s = new_section (config, section);
289 if (!s)
290 return 1;
293 return new_param (s, NULL, 0, name, value, PARAM_INT);
297 config_get_int_param (struct slist_s *config, const char *section,
298 const char *what, int *exists)
300 struct config_param_s *p = config_get_param (config, section, what, exists);
301 return *exists ? p->value.itype : -1;
305 config_set_bool_param (struct slist_s **config, const char *section,
306 const char *name, const char *value)
308 struct config_section_s *s = config_find_section (*config, section);
310 if (!s)
312 s = new_section (config, section);
313 if (!s)
314 return 1;
317 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
321 config_get_bool_param (struct slist_s *config, const char *section,
322 const char *what, int *exists)
324 return config_get_int_param (config, section, what, exists);
328 config_set_long_param (struct slist_s **config, const char *section,
329 const char *name, const char *value)
331 struct config_section_s *s = config_find_section (*config, section);
333 if (!s)
335 s = new_section (config, section);
336 if (!s)
337 return 1;
340 return new_param (s, NULL, 0, name, value, PARAM_LONG);
343 unsigned long
344 config_get_ulong_param (struct slist_s *config, const char *section,
345 const char *what, int *exists)
347 struct config_param_s *p = config_get_param (config, section, what, exists);
348 return *exists ? p->value.ultype : 0;
351 long
352 config_get_long_param (struct slist_s *config, const char *section,
353 const char *what, int *exists)
355 struct config_param_s *p = config_get_param (config, section, what, exists);
356 return *exists ? p->value.ltype : -1;
360 config_set_longlong_param (struct slist_s **config, const char *section,
361 const char *name, const char *value)
363 struct config_section_s *s = config_find_section (*config, section);
365 if (!s)
367 s = new_section (config, section);
368 if (!s)
369 return 1;
372 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
375 long long
376 config_get_longlong_param (struct slist_s *config,
377 const char *section, const char *what, int *exists)
379 struct config_param_s *p = config_get_param (config, section, what, exists);
380 return *exists ? p->value.lltype : -1;
383 unsigned long long
384 config_get_ulonglong_param (struct slist_s *config,
385 const char *section,
386 const char *what, int *exists)
388 struct config_param_s *p = config_get_param (config, section, what, exists);
389 return *exists ? p->value.ulltype : 0;
393 config_set_list_param (struct slist_s **config, const char *section,
394 const char *name, const char *value)
396 struct config_section_s *s = config_find_section (*config, section);
398 if (!s)
400 s = new_section (config, section);
401 if (!s)
402 return 1;
405 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
408 char **
409 config_get_list_param (struct slist_s *config, const char *section,
410 const char *what, int *exists)
412 struct config_param_s *p = config_get_param (config, section, what, exists);
413 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
416 char *
417 config_get_string (const char *section, const char *what)
419 char *val = NULL;
420 const char *where = section ? section : "global";
421 int exists = 0;
423 MUTEX_LOCK (&rcfile_mutex);
424 val = config_get_string_param (global_config, where, what, &exists);
425 if (!exists && strcmp (section ? section : "", "global"))
426 val = config_get_string_param (global_config, "global", what, &exists);
428 MUTEX_UNLOCK (&rcfile_mutex);
429 return val;
432 char **
433 config_get_list (const char *section, const char *what)
435 char **val = NULL;
436 const char *where = section ? section : "global";
437 int exists = 0;
439 MUTEX_LOCK (&rcfile_mutex);
440 val = config_get_list_param (global_config, where, what, &exists);
441 if (!exists && strcmp (section ? section : "", "global"))
442 val = config_get_list_param (global_config, "global", what, &exists);
444 MUTEX_UNLOCK (&rcfile_mutex);
445 return val;
449 config_get_integer (const char *section, const char *what)
451 int val = 0;
452 const char *where = section ? section : "global";
453 int exists = 0;
455 MUTEX_LOCK (&rcfile_mutex);
456 val = config_get_int_param (global_config, where, what, &exists);
457 if (!exists && strcmp (section ? section : "", "global"))
458 val = config_get_int_param (global_config, "global", what, &exists);
460 MUTEX_UNLOCK (&rcfile_mutex);
461 return val;
464 long long
465 config_get_longlong (const char *section, const char *what)
467 long long val = 0;
468 const char *where = section ? section : "global";
469 int exists = 0;
471 MUTEX_LOCK (&rcfile_mutex);
472 val = config_get_longlong_param (global_config, where, what, &exists);
473 if (!exists && strcmp (section ? section : "", "global"))
474 val = config_get_longlong_param (global_config, "global", what, &exists);
476 MUTEX_UNLOCK (&rcfile_mutex);
477 return val;
480 unsigned long long
481 config_get_ulonglong (const char *section, const char *what)
483 unsigned long long val = 0;
484 const char *where = section ? section : "global";
485 int exists = 0;
487 MUTEX_LOCK (&rcfile_mutex);
488 val = config_get_ulonglong_param (global_config, where, what, &exists);
489 if (!exists && strcmp (section ? section : "", "global"))
490 val = config_get_ulonglong_param (global_config, "global", what, &exists);
492 MUTEX_UNLOCK (&rcfile_mutex);
493 return val;
496 long
497 config_get_long (const char *section, const char *what)
499 long val = 0;
500 const char *where = section ? section : "global";
501 int exists = 0;
503 MUTEX_LOCK (&rcfile_mutex);
504 val = config_get_long_param (global_config, where, what, &exists);
505 if (!exists && strcmp (section ? section : "", "global"))
506 val = config_get_long_param (global_config, "global", what, &exists);
508 MUTEX_UNLOCK (&rcfile_mutex);
509 return val;
512 unsigned long
513 config_get_ulong (const char *section, const char *what)
515 unsigned long val = 0;
516 const char *where = section ? section : "global";
517 int exists = 0;
519 MUTEX_LOCK (&rcfile_mutex);
520 val = config_get_ulong_param (global_config, where, what, &exists);
521 if (!exists && strcmp (section ? section : "", "global"))
522 val = config_get_ulong_param (global_config, "global", what, &exists);
524 MUTEX_UNLOCK (&rcfile_mutex);
525 return val;
529 config_get_boolean (const char *section, const char *what)
531 return config_get_integer (section, what);
534 char *
535 config_get_value (const char *section, const char *what)
537 const char *where = section ? section : "global";
538 int exists = 0;
539 int i;
540 int ival;
541 long lval;
542 long long llval;
543 unsigned long ulval;
544 unsigned long long ullval;
545 char *cpval;
546 char **cppval;
547 char *result = NULL;
549 MUTEX_LOCK (&rcfile_mutex);
551 for (i = 0; config_params[i].name; i++)
553 if (!strcmp (config_params[i].name, what))
555 switch (config_params[i].type)
557 case PARAM_BOOL:
558 case PARAM_INT:
559 ival = config_get_int_param (global_config, where, what,
560 &exists);
561 if (!exists && strcmp (section ? section : "", "global"))
562 ival = config_get_int_param (global_config, "global", what,
563 &exists);
564 result = str_asprintf ("%i", ival);
565 break;
566 case PARAM_CHARP:
567 cpval = config_get_string_param (global_config, where, what,
568 &exists);
569 if (!exists && strcmp (section ? section : "", "global"))
570 cpval =
571 config_get_string_param (global_config, "global", what,
572 &exists);
573 result = cpval;
574 break;
575 case PARAM_LONG:
576 lval = config_get_long_param (global_config, where, what,
577 &exists);
578 if (!exists && strcmp (section ? section : "", "global"))
579 lval = config_get_long_param (global_config, "global", what,
580 &exists);
581 result = str_asprintf ("%li", lval);
582 break;
583 case PARAM_ULONG:
584 ulval = config_get_ulong_param (global_config, where, what,
585 &exists);
586 if (!exists && strcmp (section ? section : "", "global"))
587 ulval = config_get_ulong_param (global_config, "global", what,
588 &exists);
589 result = str_asprintf ("%lu", ulval);
590 break;
591 case PARAM_LONGLONG:
592 llval = config_get_longlong_param (global_config, where, what,
593 &exists);
594 if (!exists && strcmp (section ? section : "", "global"))
595 llval = config_get_longlong_param (global_config, "global",
596 what, &exists);
597 result = str_asprintf ("%lli", llval);
598 break;
599 case PARAM_ULONGLONG:
600 ullval = config_get_ulonglong_param (global_config, where, what,
601 &exists);
602 if (!exists && strcmp (section ? section : "", "global"))
603 ullval = config_get_ulonglong_param (global_config, "global",
604 what, &exists);
605 result = str_asprintf ("%llu", ullval);
606 break;
607 case PARAM_CHARPP:
608 cppval = config_get_list_param (global_config, where, what,
609 &exists);
610 if (!exists && strcmp (section ? section : "", "global"))
611 cppval = config_get_list_param (global_config, "global", what,
612 &exists);
614 if (cppval)
615 result = strv_join (",", cppval);
617 strv_free (cppval);
618 break;
623 MUTEX_UNLOCK (&rcfile_mutex);
624 return result;
627 static int
628 set_defaults (struct slist_s **config)
630 char *s;
631 char **list;
632 int exists;
633 int i;
635 for (i = 0; config_params[i].name; i++)
637 switch (config_params[i].type)
639 case PARAM_BOOL:
640 config_get_bool_param (*config, "global", config_params[i].name,
641 &exists);
642 if (!exists)
644 if (config_set_bool_param
645 (config, "global", config_params[i].name,
646 config_params[i].value))
647 goto fail;
649 break;
650 case PARAM_INT:
651 config_get_int_param (*config, "global", config_params[i].name,
652 &exists);
653 if (!exists)
655 if (config_set_int_param
656 (config, "global", config_params[i].name,
657 config_params[i].value))
658 goto fail;
660 break;
661 case PARAM_CHARP:
662 s = config_get_string_param (*config, "global",
663 config_params[i].name, &exists);
664 xfree (s);
665 if (!exists && config_params[i].value)
667 if (config_set_string_param (config, "global",
668 config_params[i].name,
669 config_params[i].value))
670 goto fail;
672 break;
673 case PARAM_CHARPP:
674 list = config_get_list_param (*config, "global",
675 config_params[i].name, &exists);
676 strv_free (list);
677 if (!exists && config_params[i].value)
679 if (config_set_list_param (config, "global",
680 config_params[i].name,
681 config_params[i].value))
682 goto fail;
684 break;
685 case PARAM_LONG:
686 config_get_long_param (*config, "global", config_params[i].name,
687 &exists);
688 if (!exists)
690 if (config_set_long_param
691 (config, "global", config_params[i].name,
692 config_params[i].value))
693 goto fail;
695 break;
696 case PARAM_LONGLONG:
697 config_get_longlong_param (*config, "global", config_params[i].name,
698 &exists);
699 if (!exists)
701 if (config_set_longlong_param (config, "global",
702 config_params[i].name,
703 config_params[i].value))
704 goto fail;
706 break;
710 list = config_get_list_param (*config, "global", "allowed", &exists);
711 strv_free (list);
712 if (!exists)
714 if (config_set_list_param
715 (config, "global", "allowed", get_username ()))
716 goto fail;
719 max_recursion_depth = config_get_int_param (*config, "global",
720 "recursion_depth", &exists);
721 disable_list_and_dump = config_get_bool_param (*config, "global",
722 "disable_list_and_dump",
723 &exists);
724 #ifdef HAVE_MLOCKALL
725 disable_mlock =
726 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
727 #endif
728 return 0;
730 fail:
731 return 1;
734 static struct config_section_s *
735 config_find_section (struct slist_s *config, const char *name)
737 unsigned i, t = slist_length (config);
739 for (i = 0; i < t; i++)
741 struct config_section_s *s = slist_nth_data (config, i);
743 if (!strcmp (s->name, name))
744 return s;
747 return NULL;
750 /* Append a new parameter to the list of parameters for a file
751 * section. When an existing parameter of the same name exists, its
752 * value is updated.
754 static int
755 new_param (struct config_section_s *section, const char *filename, int lineno,
756 const char *name, const char *value, int type)
758 struct config_param_s *param = NULL;
759 struct slist_s *tmp;
760 char *e;
761 unsigned i, t = slist_length (section->params);
762 int dup = 0;
764 for (i = 0; i < t; i++)
766 struct config_param_s *p = slist_nth_data (section->params, i);
767 if (!p)
768 break;
770 if (!strcmp (name, p->name))
772 param = p;
773 dup = 1;
774 break;
778 if (!param)
780 param = xcalloc (1, sizeof (struct config_param_s));
781 if (!param)
783 log_write ("%s", pwmd_strerror (ENOMEM));
784 return 1;
787 param->name = str_dup (name);
788 if (!param->name)
790 xfree (param);
791 log_write ("%s", pwmd_strerror (ENOMEM));
792 return 1;
796 param->type = type;
798 switch (type)
800 case PARAM_BOOL:
801 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
802 || !strcasecmp (value, "false"))
803 param->value.itype = 0;
804 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
805 || !strcasecmp (value, "true"))
806 param->value.itype = 1;
807 else
809 INVALID_VALUE (filename, lineno);
810 goto fail;
812 param->type = PARAM_INT;
813 break;
814 case PARAM_CHARP:
815 xfree (param->value.cptype);
816 param->value.cptype = value ? str_dup (value) : NULL;
817 if (value && !param->value.cptype)
819 log_write ("%s", pwmd_strerror (ENOMEM));
820 goto fail;
822 break;
823 case PARAM_CHARPP:
824 strv_free (param->value.cpptype);
825 param->value.cpptype = value ? str_split (value, ",", 0) : NULL;
826 if (value && !param->value.cpptype)
828 log_write ("%s", pwmd_strerror (ENOMEM));
829 goto fail;
831 break;
832 case PARAM_INT:
833 param->value.itype = strtol (value, &e, 10);
834 if (e && *e)
836 INVALID_VALUE (filename, lineno);
837 goto fail;
839 break;
840 case PARAM_LONG:
841 param->value.ltype = strtol (value, &e, 10);
842 if (e && *e)
844 INVALID_VALUE (filename, lineno);
845 goto fail;
847 break;
848 case PARAM_LONGLONG:
849 param->value.lltype = strtoll (value, &e, 10);
850 if (e && *e)
852 INVALID_VALUE (filename, lineno);
853 goto fail;
855 break;
856 case PARAM_ULONGLONG:
857 param->value.ulltype = strtoull (value, &e, 10);
858 if (e && *e)
860 INVALID_VALUE (filename, lineno);
861 goto fail;
863 break;
864 case PARAM_ULONG:
865 param->value.ultype = strtoul (value, &e, 10);
866 if (e && *e)
868 INVALID_VALUE (filename, lineno);
869 goto fail;
871 break;
874 if (dup)
875 return 0;
877 tmp = slist_append (section->params, param);
878 if (!tmp)
880 log_write ("%s", pwmd_strerror (ENOMEM));
881 goto fail;
884 section->params = tmp;
885 return 0;
887 fail:
888 xfree (param->name);
889 xfree (param);
890 return 1;
893 struct slist_s *
894 config_parse (const char *filename)
896 struct slist_s *tmpconfig = NULL, *tmp;
897 struct config_section_s *cur_section = NULL;
898 char buf[LINE_MAX];
899 char *s;
900 int lineno = 1;
901 int have_global = 0;
902 FILE *fp = fopen (filename, "r");
904 if (!fp)
906 log_write ("%s: %s", filename,
907 pwmd_strerror (gpg_error_from_errno (errno)));
909 if (errno != ENOENT)
910 return NULL;
912 log_write (_("Using defaults!"));
913 goto defaults;
916 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
918 char line[LINE_MAX] = { 0 };
919 size_t len = 0;
921 if (*s == '#')
922 continue;
924 s = str_chomp (s);
925 for (; s && *s; s++)
927 int match = 0;
929 /* New file section. */
930 if (*s == '[')
932 struct config_section_s *section;
933 char *p = strchr (++s, ']');
935 if (!p)
937 log_write (_("%s(%i): unbalanced braces"), filename,
938 lineno);
939 goto fail;
942 len = strlen (s) - strlen (p);
943 memcpy (line, s, len);
944 line[len] = 0;
946 section = config_find_section (tmpconfig, line);
947 if (section)
949 log_write (_("%s(%i): section '%s' already exists!"),
950 filename, lineno, line);
951 goto fail;
954 if (!strcmp (line, "global"))
955 have_global = 1;
957 section = xcalloc (1, sizeof (struct config_section_s));
958 section->name = str_dup (line);
960 if (cur_section)
962 tmp = slist_append (tmpconfig, cur_section);
963 if (!tmp)
965 log_write ("%s", pwmd_strerror (ENOMEM));
966 goto fail;
969 tmpconfig = tmp;
972 cur_section = section;
973 break;
976 if (!cur_section)
978 log_write (_("%s(%i): parameter outside of section!"), filename,
979 lineno);
980 goto fail;
983 /* Parameters for each section. */
984 for (int m = 0; config_params[m].name; m++)
986 size_t len = strlen (config_params[m].name);
988 if (!strncmp (s, config_params[m].name, len))
990 char *p = s + len;
992 while (*p && *p == ' ')
993 p++;
995 if (!*p || *p != '=')
996 continue;
998 p++;
999 while (*p && isspace (*p))
1000 p++;
1002 s[len] = 0;
1003 if (new_param (cur_section, filename, lineno, s, p,
1004 config_params[m].type))
1005 goto fail;
1007 match = 1;
1008 break;
1012 if (!match)
1014 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1015 goto fail;
1018 break;
1022 if (cur_section)
1024 tmp = slist_append (tmpconfig, cur_section);
1025 if (!tmp)
1027 log_write ("%s", pwmd_strerror (ENOMEM));
1028 goto fail;
1031 cur_section = NULL;
1032 tmpconfig = tmp;
1035 if (!have_global)
1036 log_write (_
1037 ("WARNING: %s: could not find a [global] configuration section!"),
1038 filename);
1040 defaults:
1041 if (set_defaults (&tmpconfig))
1042 goto fail;
1044 if (fp)
1045 fclose(fp);
1047 return tmpconfig;
1049 fail:
1050 if (fp)
1051 fclose (fp);
1053 config_free (tmpconfig);
1054 free_section (cur_section);
1055 return NULL;
1058 static void
1059 free_section (struct config_section_s *s)
1061 if (!s)
1062 return;
1064 for (;;)
1066 struct config_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 config_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);