s/GPG_ERR_INV_USER_ID/GPG_ERR_EACCES/.
[libpwmd.git] / src / rcfile.c
blobbc71249a7341e89ba2f0a64286ce16e7fb15a555
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
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>
31 #include <pwd.h>
33 #include "pwmd-error.h"
34 #include <gcrypt.h>
35 #include "mutex.h"
36 #include "rcfile.h"
37 #include "util-misc.h"
38 #include "common.h"
39 #include "util-slist.h"
40 #include "util-string.h"
41 #include "mem.h"
43 #define DEFAULT_PINENTRY_TIMEOUT "30"
44 #define DEFAULT_CACHE_TIMEOUT "600"
45 #define DEFAULT_KEEPALIVE_INTERVAL "60"
47 #define INVALID_VALUE(file, line) do { \
48 if (file) \
49 log_write(_("%s(%i): invalid value for parameter."), file, line); \
50 } while (0);
52 enum
54 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
55 PARAM_BOOL, PARAM_ULONG, PARAM_ULONGLONG
58 static struct config_params_s
60 char *name;
61 int type;
62 char *value;
63 } config_params[] = {
64 { "backup", PARAM_BOOL, "true"},
65 { "socket_path", PARAM_CHARP, NULL},
66 { "socket_perms", PARAM_CHARP, NULL},
67 { "passphrase", PARAM_CHARP, NULL},
68 { "passphrase_file", PARAM_CHARP, NULL},
69 { "agent_env_file", PARAM_CHARP, NULL},
70 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
71 { "enable_logging", PARAM_BOOL, "0"},
72 { "log_keepopen", PARAM_BOOL, "true"},
73 { "log_level", PARAM_INT, "0"},
74 { "disable_mlockall", PARAM_BOOL, "true"},
75 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
76 { "cache_push", PARAM_CHARPP, NULL},
77 { "disable_list_and_dump", PARAM_BOOL, "false"},
78 { "recursion_depth", PARAM_INT, "100"},
79 { "syslog", PARAM_BOOL, "false"},
80 { "xfer_progress", PARAM_INT, "8196"},
81 { "allowed", PARAM_CHARPP, NULL},
82 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
83 { "cipher", PARAM_CHARP, "aes256"},
84 { "kill_scd", PARAM_BOOL, "false"},
85 { "cipher_iterations", PARAM_ULONGLONG, "0"},
86 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
87 { "priority", PARAM_INT, INVALID_PRIORITY},
88 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
89 { "tcp_port", PARAM_INT, "6466"},
90 { "enable_tcp", PARAM_BOOL, "false"},
91 { "tcp_require_key", PARAM_BOOL, "false"},
92 { "tcp_wait", PARAM_INT, "0"},
93 { "tcp_bind", PARAM_CHARP, "any"},
94 { "tcp_interface", PARAM_CHARP, NULL},
95 { "tls_timeout", PARAM_INT, "300"},
96 { "tls_cipher_suite", PARAM_CHARP, "SECURE256"},
97 { "tls_access", PARAM_CHARPP, NULL},
98 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
99 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
100 { "use_agent", PARAM_BOOL, "false"},
101 { "require_save_key", PARAM_BOOL, "true"},
102 { "invoking_user", PARAM_CHARP, NULL},
103 { "invoking_tls", PARAM_CHARP, NULL},
104 { NULL, 0, NULL},
107 struct config_param_s
109 char *name;
110 int type;
111 union
113 int itype;
114 char *cptype;
115 char **cpptype;
116 long ltype;
117 long long lltype;
118 unsigned long ultype;
119 unsigned long long ulltype;
120 } value;
123 static struct config_section_s *config_find_section (struct slist_s *config,
124 const char *name);
125 static int new_param (struct config_section_s *section, const char *filename,
126 int lineno, const char *name, const char *value,
127 int type);
128 static void free_section (struct config_section_s *s);
129 static int set_defaults (struct slist_s **config);
131 static void
132 section_remove_param (struct config_section_s *section, const char *name)
134 unsigned i, t = slist_length (section->params);
136 for (i = 0; i < t; i++)
138 struct config_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 config_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 config_param_s *
182 config_has_param (struct config_section_s *s, const char *what)
184 unsigned i, t = slist_length (s->params);
186 for (i = 0; i < t; i++)
188 struct config_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 config_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 config_param_s *p;
210 struct config_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 config_section_s *
230 new_section (struct slist_s **config, const char *name)
232 struct slist_s *tmp;
233 struct config_section_s *s = xcalloc (1, sizeof (struct config_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 config_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 config_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 config_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 config_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 config_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 config_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 config_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 config_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 config_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 config_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 config_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 config_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 config_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 = NULL;
634 char **list;
635 int exists;
636 int i;
637 struct passwd *pwd;
639 for (i = 0; config_params[i].name; i++)
641 switch (config_params[i].type)
643 case PARAM_BOOL:
644 config_get_bool_param (*config, "global", config_params[i].name,
645 &exists);
646 if (!exists)
648 if (config_set_bool_param
649 (config, "global", config_params[i].name,
650 config_params[i].value))
651 goto fail;
653 break;
654 case PARAM_INT:
655 config_get_int_param (*config, "global", config_params[i].name,
656 &exists);
657 if (!exists)
659 if (config_set_int_param
660 (config, "global", config_params[i].name,
661 config_params[i].value))
662 goto fail;
664 break;
665 case PARAM_CHARP:
666 s = config_get_string_param (*config, "global",
667 config_params[i].name, &exists);
668 xfree (s);
669 if (!exists && config_params[i].value)
671 if (config_set_string_param (config, "global",
672 config_params[i].name,
673 config_params[i].value))
674 goto fail;
676 break;
677 case PARAM_CHARPP:
678 list = config_get_list_param (*config, "global",
679 config_params[i].name, &exists);
680 strv_free (list);
681 if (!exists && config_params[i].value)
683 if (config_set_list_param (config, "global",
684 config_params[i].name,
685 config_params[i].value))
686 goto fail;
688 break;
689 case PARAM_LONG:
690 config_get_long_param (*config, "global", config_params[i].name,
691 &exists);
692 if (!exists)
694 if (config_set_long_param
695 (config, "global", config_params[i].name,
696 config_params[i].value))
697 goto fail;
699 break;
700 case PARAM_LONGLONG:
701 config_get_longlong_param (*config, "global", config_params[i].name,
702 &exists);
703 if (!exists)
705 if (config_set_longlong_param (config, "global",
706 config_params[i].name,
707 config_params[i].value))
708 goto fail;
710 break;
714 list = config_get_list_param (*config, "global", "allowed", &exists);
715 strv_free (list);
716 if (!exists)
718 char *p = get_username (getuid());
720 if (config_set_list_param (config, "global", "allowed", p))
722 xfree (p);
723 goto fail;
726 xfree (p);
729 max_recursion_depth = config_get_int_param (*config, "global",
730 "recursion_depth", &exists);
731 disable_list_and_dump = config_get_bool_param (*config, "global",
732 "disable_list_and_dump",
733 &exists);
734 #ifdef HAVE_MLOCKALL
735 disable_mlock =
736 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
737 #endif
739 s = config_get_string_param(*config, "global", "invoking_user", &exists);
740 errno = 0;
741 if (!s || !*s)
742 pwd = getpwuid(getuid());
743 else
744 pwd = getpwnam(s);
746 if (!pwd)
748 log_write (_("could not set invoking user: user '%s' is invalid"), s);
749 goto fail;
752 xfree (s);
753 #ifdef WITH_GNUTLS
754 invoking_tls = config_get_string_param(*config, "global", "invoking_tls",
755 &exists);
756 #endif
757 invoking_uid = pwd->pw_uid;
758 invoking_gid = pwd->pw_gid;
759 return 0;
761 fail:
762 xfree (s);
763 return 1;
766 static struct config_section_s *
767 config_find_section (struct slist_s *config, const char *name)
769 unsigned i, t = slist_length (config);
771 for (i = 0; i < t; i++)
773 struct config_section_s *s = slist_nth_data (config, i);
775 if (!strcmp (s->name, name))
776 return s;
779 return NULL;
782 /* Append a new parameter to the list of parameters for a file
783 * section. When an existing parameter of the same name exists, its
784 * value is updated.
786 static int
787 new_param (struct config_section_s *section, const char *filename, int lineno,
788 const char *name, const char *value, int type)
790 struct config_param_s *param = NULL;
791 struct slist_s *tmp;
792 char *e;
793 unsigned i, t = slist_length (section->params);
794 int dup = 0;
796 for (i = 0; i < t; i++)
798 struct config_param_s *p = slist_nth_data (section->params, i);
799 if (!p)
800 break;
802 if (!strcmp (name, p->name))
804 param = p;
805 dup = 1;
806 break;
810 if (!param)
812 param = xcalloc (1, sizeof (struct config_param_s));
813 if (!param)
815 log_write ("%s", pwmd_strerror (ENOMEM));
816 return 1;
819 param->name = str_dup (name);
820 if (!param->name)
822 xfree (param);
823 log_write ("%s", pwmd_strerror (ENOMEM));
824 return 1;
828 param->type = type;
830 switch (type)
832 case PARAM_BOOL:
833 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
834 || !strcasecmp (value, "false"))
835 param->value.itype = 0;
836 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
837 || !strcasecmp (value, "true"))
838 param->value.itype = 1;
839 else
841 INVALID_VALUE (filename, lineno);
842 goto fail;
844 param->type = PARAM_INT;
845 break;
846 case PARAM_CHARP:
847 xfree (param->value.cptype);
848 param->value.cptype = NULL;
849 param->value.cptype = value && *value ? str_dup (value) : NULL;
850 if (value && *value && !param->value.cptype)
852 log_write ("%s", pwmd_strerror (ENOMEM));
853 goto fail;
855 break;
856 case PARAM_CHARPP:
857 strv_free (param->value.cpptype);
858 param->value.cpptype = NULL;
859 param->value.cpptype = value && *value ? str_split (value, ",", 0) : NULL;
860 if (value && *value && !param->value.cpptype)
862 log_write ("%s", pwmd_strerror (ENOMEM));
863 goto fail;
865 break;
866 case PARAM_INT:
867 param->value.itype = strtol (value, &e, 10);
868 if (e && *e)
870 INVALID_VALUE (filename, lineno);
871 goto fail;
873 break;
874 case PARAM_LONG:
875 param->value.ltype = strtol (value, &e, 10);
876 if (e && *e)
878 INVALID_VALUE (filename, lineno);
879 goto fail;
881 break;
882 case PARAM_LONGLONG:
883 param->value.lltype = strtoll (value, &e, 10);
884 if (e && *e)
886 INVALID_VALUE (filename, lineno);
887 goto fail;
889 break;
890 case PARAM_ULONGLONG:
891 param->value.ulltype = strtoull (value, &e, 10);
892 if (e && *e)
894 INVALID_VALUE (filename, lineno);
895 goto fail;
897 break;
898 case PARAM_ULONG:
899 param->value.ultype = strtoul (value, &e, 10);
900 if (e && *e)
902 INVALID_VALUE (filename, lineno);
903 goto fail;
905 break;
908 if (dup)
909 return 0;
911 tmp = slist_append (section->params, param);
912 if (!tmp)
914 log_write ("%s", pwmd_strerror (ENOMEM));
915 goto fail;
918 section->params = tmp;
919 return 0;
921 fail:
922 xfree (param->name);
923 xfree (param);
924 return 1;
927 struct slist_s *
928 config_parse (const char *filename)
930 struct slist_s *tmpconfig = NULL, *tmp;
931 struct config_section_s *cur_section = NULL;
932 char buf[LINE_MAX];
933 char *s;
934 int lineno = 1;
935 int have_global = 0;
936 FILE *fp = fopen (filename, "r");
938 if (!fp)
940 log_write ("%s: %s", filename,
941 pwmd_strerror (gpg_error_from_errno (errno)));
943 if (errno != ENOENT)
944 return NULL;
946 log_write (_("Using defaults!"));
947 goto defaults;
950 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
952 char line[LINE_MAX] = { 0 };
953 size_t len = 0;
955 if (*s == '#')
956 continue;
958 s = str_chomp (s);
959 for (; s && *s; s++)
961 int match = 0;
963 /* New file section. */
964 if (*s == '[')
966 struct config_section_s *section;
967 char *p = strchr (++s, ']');
969 if (!p)
971 log_write (_("%s(%i): unbalanced braces"), filename,
972 lineno);
973 goto fail;
976 len = strlen (s) - strlen (p);
977 memcpy (line, s, len);
978 line[len] = 0;
980 section = config_find_section (tmpconfig, line);
981 if (section)
983 log_write (_("%s(%i): section '%s' already exists!"),
984 filename, lineno, line);
985 goto fail;
988 if (!strcmp (line, "global"))
989 have_global = 1;
991 section = xcalloc (1, sizeof (struct config_section_s));
992 section->name = str_dup (line);
994 if (cur_section)
996 tmp = slist_append (tmpconfig, cur_section);
997 if (!tmp)
999 log_write ("%s", pwmd_strerror (ENOMEM));
1000 goto fail;
1003 tmpconfig = tmp;
1006 cur_section = section;
1007 break;
1010 if (!cur_section)
1012 log_write (_("%s(%i): parameter outside of section!"), filename,
1013 lineno);
1014 goto fail;
1017 /* Parameters for each section. */
1018 for (int m = 0; config_params[m].name; m++)
1020 size_t len = strlen (config_params[m].name);
1022 if (!strncmp (s, config_params[m].name, len))
1024 char *p = s + len;
1026 while (*p && *p == ' ')
1027 p++;
1029 if (!*p || *p != '=')
1030 continue;
1032 p++;
1033 while (*p && isspace (*p))
1034 p++;
1036 s[len] = 0;
1037 if (new_param (cur_section, filename, lineno, s, p,
1038 config_params[m].type))
1039 goto fail;
1041 match = 1;
1042 break;
1046 if (!match)
1048 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1049 goto fail;
1052 break;
1056 if (cur_section)
1058 tmp = slist_append (tmpconfig, cur_section);
1059 if (!tmp)
1061 log_write ("%s", pwmd_strerror (ENOMEM));
1062 goto fail;
1065 cur_section = NULL;
1066 tmpconfig = tmp;
1069 if (!have_global)
1070 log_write (_
1071 ("WARNING: %s: could not find a [global] configuration section!"),
1072 filename);
1074 defaults:
1075 if (set_defaults (&tmpconfig))
1076 goto fail;
1078 if (fp)
1079 fclose(fp);
1081 return tmpconfig;
1083 fail:
1084 if (fp)
1085 fclose (fp);
1087 config_free (tmpconfig);
1088 free_section (cur_section);
1089 return NULL;
1092 static void
1093 free_section (struct config_section_s *s)
1095 if (!s)
1096 return;
1098 for (;;)
1100 struct config_param_s *p = slist_nth_data (s->params, 0);
1102 if (!p)
1103 break;
1105 section_remove_param (s, p->name);
1108 s->params = NULL;
1109 xfree (s->name);
1110 s->name = NULL;
1113 void
1114 config_free (struct slist_s *config)
1116 for (;;)
1118 struct config_section_s *s = slist_nth_data (config, 0);
1119 if (!s)
1120 break;
1122 free_section (s);
1123 config = slist_remove (config, s);
1124 xfree (s);