Always explicitly set 'invoking_user'.
[pwmd.git] / src / rcfile.c
blob74c56520d678a1a42b51ff04c972b18a91220941
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 { "allowed_file", PARAM_CHARP, NULL},
83 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
84 { "cipher", PARAM_CHARP, "aes256"},
85 { "kill_scd", PARAM_BOOL, "false"},
86 { "cipher_iterations", PARAM_ULONGLONG, "0"},
87 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
88 { "priority", PARAM_INT, INVALID_PRIORITY},
89 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
90 { "tcp_port", PARAM_INT, "6466"},
91 { "enable_tcp", PARAM_BOOL, "false"},
92 { "tcp_require_key", PARAM_BOOL, "false"},
93 { "tcp_wait", PARAM_INT, "0"},
94 { "tcp_bind", PARAM_CHARP, "any"},
95 { "tcp_interface", PARAM_CHARP, NULL},
96 { "tls_timeout", PARAM_INT, "300"},
97 { "tls_cipher_suite", PARAM_CHARP, "SECURE256"},
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 void
631 parse_allowed_file (struct slist_s *config, const char *section)
633 FILE *fp;
634 char buf[LINE_MAX];
635 int exists;
636 char **list = NULL;
637 char *tmp;
638 char *p = config_get_string_param (config, section, "allowed_file", &exists);
640 if (!p || !*p)
642 xfree (p);
643 return;
646 tmp = expand_homedir (p);
647 xfree (p);
648 p = tmp;
649 fp = fopen (p, "r");
650 if (!fp)
652 log_write ("%s: %s", p, strerror (errno));
653 xfree (p);
654 return;
657 xfree (p);
658 list = config_get_list_param (config, section, "allowed", &exists);
659 if (!list && exists)
661 fclose (fp);
662 log_write ("%s", strerror (ENOMEM));
663 return;
666 while ((p = fgets (buf, sizeof (buf), fp)))
668 char **pp;
670 if (p[strlen(p)-1] == '\n')
671 p[strlen(p)-1] = 0;
673 while (*p && isspace (*p))
674 p++;
676 if (!*p)
677 continue;
679 tmp = str_dup (p);
680 if (tmp)
681 pp = strv_cat (list, str_dup (p));
683 if (!pp || !tmp)
685 xfree (tmp);
686 strv_free (list);
687 fclose (fp);
688 log_write ("%s", strerror (ENOMEM));
689 return;
692 xfree (tmp);
693 list = pp;
696 fclose(fp);
697 if (!list)
698 return;
700 p = strv_join (",", list);
701 strv_free (list);
703 if (!p)
705 log_write ("%s", strerror (ENOMEM));
706 return;
709 config_set_list_param (&config, section, "allowed", p);
710 xfree (p);
713 static int
714 fixup_allowed_once (struct slist_s **config, const char *section)
716 char **list, **pp, *p;
717 int exists;
719 parse_allowed_file (*config, section);
720 list = config_get_list_param (*config, section, "allowed", &exists);
721 for (pp = list; pp && *pp; pp++)
723 if (*(*pp) == '#')
725 for (p = *pp; p && *p; p++)
726 *p = toupper(*p);
730 strv_free (list);
731 if (!exists)
733 if (!strcmp (section, "global"))
735 p = get_username (getuid());
737 if (config_set_list_param (config, section, "allowed", p))
739 xfree (p);
740 return 1;
743 xfree (p);
745 else
747 list = config_get_list_param (*config, "global", "allowed", &exists);
748 if (list)
750 p = strv_join (",", list);
751 strv_free (list);
752 if (config_set_list_param (config, section, "allowed", p))
754 xfree (p);
755 return 1;
758 xfree (p);
763 return 0;
766 static int
767 fixup_allowed (struct slist_s **config)
769 int n, t = slist_length (*config);
771 for (n = 0; n < t; n++)
773 struct config_section_s *section;
775 section = slist_nth_data (*config, n);
776 if (fixup_allowed_once (config, section->name))
777 return 1;
780 return 0;
783 static int
784 set_defaults (struct slist_s **config)
786 char *s = NULL, *p;
787 char **list;
788 int exists;
789 int i;
790 struct passwd *pwd;
792 for (i = 0; config_params[i].name; i++)
794 switch (config_params[i].type)
796 case PARAM_BOOL:
797 config_get_bool_param (*config, "global", config_params[i].name,
798 &exists);
799 if (!exists)
801 if (config_set_bool_param
802 (config, "global", config_params[i].name,
803 config_params[i].value))
804 goto fail;
806 break;
807 case PARAM_INT:
808 config_get_int_param (*config, "global", config_params[i].name,
809 &exists);
810 if (!exists)
812 if (config_set_int_param
813 (config, "global", config_params[i].name,
814 config_params[i].value))
815 goto fail;
817 break;
818 case PARAM_CHARP:
819 s = config_get_string_param (*config, "global",
820 config_params[i].name, &exists);
821 xfree (s);
822 if (!exists && config_params[i].value)
824 if (config_set_string_param (config, "global",
825 config_params[i].name,
826 config_params[i].value))
827 goto fail;
829 break;
830 case PARAM_CHARPP:
831 list = config_get_list_param (*config, "global",
832 config_params[i].name, &exists);
833 strv_free (list);
834 if (!exists && config_params[i].value)
836 if (config_set_list_param (config, "global",
837 config_params[i].name,
838 config_params[i].value))
839 goto fail;
841 break;
842 case PARAM_LONG:
843 config_get_long_param (*config, "global", config_params[i].name,
844 &exists);
845 if (!exists)
847 if (config_set_long_param
848 (config, "global", config_params[i].name,
849 config_params[i].value))
850 goto fail;
852 break;
853 case PARAM_LONGLONG:
854 config_get_longlong_param (*config, "global", config_params[i].name,
855 &exists);
856 if (!exists)
858 if (config_set_longlong_param (config, "global",
859 config_params[i].name,
860 config_params[i].value))
861 goto fail;
863 break;
867 s = NULL;
868 if (fixup_allowed (config))
869 goto fail;
871 max_recursion_depth = config_get_int_param (*config, "global",
872 "recursion_depth", &exists);
873 disable_list_and_dump = config_get_bool_param (*config, "global",
874 "disable_list_and_dump",
875 &exists);
876 #ifdef HAVE_MLOCKALL
877 disable_mlock =
878 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
879 #endif
881 s = config_get_string_param(*config, "global", "invoking_user", &exists);
882 errno = 0;
883 if (!s || !*s)
884 pwd = getpwuid(getuid());
885 else
886 pwd = getpwnam(s);
888 if (!pwd)
890 log_write (_("could not set invoking user: user '%s' is invalid"), s);
891 goto fail;
894 xfree (s);
895 config_set_string_param(config, "global", "invoking_user", pwd->pw_name);
896 #ifdef WITH_GNUTLS
897 invoking_tls = config_get_string_param(*config, "global", "invoking_tls",
898 &exists);
899 for (p = invoking_tls; p && *p; p++)
900 *p = toupper(*p);
902 #endif
903 invoking_uid = pwd->pw_uid;
904 invoking_gid = pwd->pw_gid;
905 return 0;
907 fail:
908 xfree (s);
909 return 1;
912 static struct config_section_s *
913 config_find_section (struct slist_s *config, const char *name)
915 unsigned i, t = slist_length (config);
917 for (i = 0; i < t; i++)
919 struct config_section_s *s = slist_nth_data (config, i);
921 if (!strcmp (s->name, name))
922 return s;
925 return NULL;
928 /* Append a new parameter to the list of parameters for a file
929 * section. When an existing parameter of the same name exists, its
930 * value is updated.
932 static int
933 new_param (struct config_section_s *section, const char *filename, int lineno,
934 const char *name, const char *value, int type)
936 struct config_param_s *param = NULL;
937 struct slist_s *tmp;
938 char *e;
939 unsigned i, t = slist_length (section->params);
940 int dup = 0;
942 for (i = 0; i < t; i++)
944 struct config_param_s *p = slist_nth_data (section->params, i);
945 if (!p)
946 break;
948 if (!strcmp (name, p->name))
950 param = p;
951 dup = 1;
952 break;
956 if (!param)
958 param = xcalloc (1, sizeof (struct config_param_s));
959 if (!param)
961 log_write ("%s", pwmd_strerror (ENOMEM));
962 return 1;
965 param->name = str_dup (name);
966 if (!param->name)
968 xfree (param);
969 log_write ("%s", pwmd_strerror (ENOMEM));
970 return 1;
974 param->type = type;
976 switch (type)
978 case PARAM_BOOL:
979 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
980 || !strcasecmp (value, "false"))
981 param->value.itype = 0;
982 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
983 || !strcasecmp (value, "true"))
984 param->value.itype = 1;
985 else
987 INVALID_VALUE (filename, lineno);
988 goto fail;
990 param->type = PARAM_INT;
991 break;
992 case PARAM_CHARP:
993 xfree (param->value.cptype);
994 param->value.cptype = NULL;
995 param->value.cptype = value && *value ? str_dup (value) : NULL;
996 if (value && *value && !param->value.cptype)
998 log_write ("%s", pwmd_strerror (ENOMEM));
999 goto fail;
1001 break;
1002 case PARAM_CHARPP:
1003 strv_free (param->value.cpptype);
1004 param->value.cpptype = NULL;
1005 param->value.cpptype = value && *value ? str_split (value, ",", 0) : NULL;
1006 if (value && *value && !param->value.cpptype)
1008 log_write ("%s", pwmd_strerror (ENOMEM));
1009 goto fail;
1011 break;
1012 case PARAM_INT:
1013 param->value.itype = strtol (value, &e, 10);
1014 if (e && *e)
1016 INVALID_VALUE (filename, lineno);
1017 goto fail;
1019 break;
1020 case PARAM_LONG:
1021 param->value.ltype = strtol (value, &e, 10);
1022 if (e && *e)
1024 INVALID_VALUE (filename, lineno);
1025 goto fail;
1027 break;
1028 case PARAM_LONGLONG:
1029 param->value.lltype = strtoll (value, &e, 10);
1030 if (e && *e)
1032 INVALID_VALUE (filename, lineno);
1033 goto fail;
1035 break;
1036 case PARAM_ULONGLONG:
1037 param->value.ulltype = strtoull (value, &e, 10);
1038 if (e && *e)
1040 INVALID_VALUE (filename, lineno);
1041 goto fail;
1043 break;
1044 case PARAM_ULONG:
1045 param->value.ultype = strtoul (value, &e, 10);
1046 if (e && *e)
1048 INVALID_VALUE (filename, lineno);
1049 goto fail;
1051 break;
1054 if (dup)
1055 return 0;
1057 tmp = slist_append (section->params, param);
1058 if (!tmp)
1060 log_write ("%s", pwmd_strerror (ENOMEM));
1061 goto fail;
1064 section->params = tmp;
1065 return 0;
1067 fail:
1068 xfree (param->name);
1069 xfree (param);
1070 return 1;
1073 struct slist_s *
1074 config_parse (const char *filename)
1076 struct slist_s *tmpconfig = NULL, *tmp;
1077 struct config_section_s *cur_section = NULL;
1078 char buf[LINE_MAX];
1079 char *s;
1080 int lineno = 1;
1081 int have_global = 0;
1082 FILE *fp = fopen (filename, "r");
1084 if (!fp)
1086 log_write ("%s: %s", filename,
1087 pwmd_strerror (gpg_error_from_errno (errno)));
1089 if (errno != ENOENT)
1090 return NULL;
1092 log_write (_("Using defaults!"));
1093 goto defaults;
1096 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1098 char line[LINE_MAX] = { 0 };
1099 size_t len = 0;
1101 if (*s == '#')
1102 continue;
1104 s = str_chomp (s);
1105 for (; s && *s; s++)
1107 int match = 0;
1109 /* New file section. */
1110 if (*s == '[')
1112 struct config_section_s *section;
1113 char *p = strchr (++s, ']');
1115 if (!p)
1117 log_write (_("%s(%i): unbalanced braces"), filename,
1118 lineno);
1119 goto fail;
1122 len = strlen (s) - strlen (p);
1123 memcpy (line, s, len);
1124 line[len] = 0;
1126 section = config_find_section (tmpconfig, line);
1127 if (section)
1129 log_write (_("%s(%i): section '%s' already exists!"),
1130 filename, lineno, line);
1131 goto fail;
1134 if (!strcmp (line, "global"))
1135 have_global = 1;
1137 section = xcalloc (1, sizeof (struct config_section_s));
1138 section->name = str_dup (line);
1140 if (cur_section)
1142 tmp = slist_append (tmpconfig, cur_section);
1143 if (!tmp)
1145 log_write ("%s", pwmd_strerror (ENOMEM));
1146 goto fail;
1149 tmpconfig = tmp;
1152 cur_section = section;
1153 break;
1156 if (!cur_section)
1158 log_write (_("%s(%i): parameter outside of section!"), filename,
1159 lineno);
1160 goto fail;
1163 /* Parameters for each section. */
1164 for (int m = 0; config_params[m].name; m++)
1166 size_t len = strlen (config_params[m].name);
1168 if (!strncmp (s, config_params[m].name, len))
1170 char *p = s + len;
1172 while (*p && *p == ' ')
1173 p++;
1175 if (!*p || *p != '=')
1176 continue;
1178 p++;
1179 while (*p && isspace (*p))
1180 p++;
1182 s[len] = 0;
1183 if (new_param (cur_section, filename, lineno, s, p,
1184 config_params[m].type))
1185 goto fail;
1187 match = 1;
1188 break;
1192 if (!match)
1194 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1195 goto fail;
1198 break;
1202 if (cur_section)
1204 tmp = slist_append (tmpconfig, cur_section);
1205 if (!tmp)
1207 log_write ("%s", pwmd_strerror (ENOMEM));
1208 goto fail;
1211 cur_section = NULL;
1212 tmpconfig = tmp;
1215 if (!have_global)
1216 log_write (_
1217 ("WARNING: %s: could not find a [global] configuration section!"),
1218 filename);
1220 defaults:
1221 if (set_defaults (&tmpconfig))
1222 goto fail;
1224 if (fp)
1225 fclose(fp);
1227 return tmpconfig;
1229 fail:
1230 if (fp)
1231 fclose (fp);
1233 config_free (tmpconfig);
1234 free_section (cur_section);
1235 return NULL;
1238 static void
1239 free_section (struct config_section_s *s)
1241 if (!s)
1242 return;
1244 for (;;)
1246 struct config_param_s *p = slist_nth_data (s->params, 0);
1248 if (!p)
1249 break;
1251 section_remove_param (s, p->name);
1254 s->params = NULL;
1255 xfree (s->name);
1256 s->name = NULL;
1259 void
1260 config_free (struct slist_s *config)
1262 for (;;)
1264 struct config_section_s *s = slist_nth_data (config, 0);
1265 if (!s)
1266 break;
1268 free_section (s);
1269 config = slist_remove (config, s);
1270 xfree (s);