2 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <parse_time.h>
41 #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
42 #include <CoreFoundation/CoreFoundation.h>
45 /* Gaah! I want a portable funopen */
53 config_fgets(char *str, size_t len, struct fileptr *ptr)
55 /* XXX this is not correct, in that they don't do the same if the
56 line is longer than len */
58 return fgets(str, len, ptr->f);
60 /* this is almost strsep_copy */
65 p = ptr->s + strcspn(ptr->s, "\n");
68 l = min(len, (size_t)(p - ptr->s));
70 memcpy(str, ptr->s, l);
78 static heim_error_code parse_section(char *p, heim_config_section **s,
79 heim_config_section **res,
80 const char **err_message);
81 static heim_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
82 heim_config_binding **b,
83 heim_config_binding **parent,
84 const char **err_message);
85 static heim_error_code parse_list(struct fileptr *f, unsigned *lineno,
86 heim_config_binding **parent,
87 const char **err_message);
90 heim_config_get_entry(heim_config_section **parent, const char *name, int type)
92 heim_config_section **q;
94 for (q = parent; *q != NULL; q = &(*q)->next)
95 if (type == heim_config_list &&
96 (unsigned)type == (*q)->type &&
97 strcmp(name, (*q)->name) == 0)
99 *q = calloc(1, sizeof(**q));
102 (*q)->name = strdup(name);
104 if ((*q)->name == NULL) {
122 * starting at the line in `p', storing the resulting structure in
123 * `s' and hooking it into `parent'.
124 * Store the error message in `err_message'.
127 static heim_error_code
128 parse_section(char *p, heim_config_section **s, heim_config_section **parent,
129 const char **err_message)
132 heim_config_section *tmp;
134 p1 = strchr (p + 1, ']');
136 *err_message = "missing ]";
137 return HEIM_ERR_CONFIG_BADFORMAT;
140 tmp = heim_config_get_entry(parent, p + 1, heim_config_list);
142 *err_message = "out of memory";
143 return HEIM_ERR_CONFIG_BADFORMAT;
150 * Parse a brace-enclosed list from `f', hooking in the structure at
152 * Store the error message in `err_message'.
155 static heim_error_code
156 parse_list(struct fileptr *f, unsigned *lineno, heim_config_binding **parent,
157 const char **err_message)
161 heim_config_binding *b = NULL;
162 unsigned beg_lineno = *lineno;
164 while(config_fgets(buf, sizeof(buf), f) != NULL) {
168 buf[strcspn(buf, "\r\n")] = '\0';
170 while(isspace((unsigned char)*p))
172 if (*p == '#' || *p == ';' || *p == '\0')
174 while(isspace((unsigned char)*p))
180 ret = parse_binding (f, lineno, p, &b, parent, err_message);
184 *lineno = beg_lineno;
185 *err_message = "unclosed {";
186 return HEIM_ERR_CONFIG_BADFORMAT;
193 static heim_error_code
194 parse_binding(struct fileptr *f, unsigned *lineno, char *p,
195 heim_config_binding **b, heim_config_binding **parent,
196 const char **err_message)
198 heim_config_binding *tmp;
200 heim_error_code ret = 0;
203 while (*p && *p != '=' && !isspace((unsigned char)*p))
206 *err_message = "missing =";
207 return HEIM_ERR_CONFIG_BADFORMAT;
210 while (isspace((unsigned char)*p))
213 *err_message = "missing =";
214 return HEIM_ERR_CONFIG_BADFORMAT;
217 while(isspace((unsigned char)*p))
221 tmp = heim_config_get_entry(parent, p1, heim_config_list);
223 *err_message = "out of memory";
224 return HEIM_ERR_CONFIG_BADFORMAT;
226 ret = parse_list (f, lineno, &tmp->u.list, err_message);
228 tmp = heim_config_get_entry(parent, p1, heim_config_string);
230 *err_message = "out of memory";
231 return HEIM_ERR_CONFIG_BADFORMAT;
235 while(p > p1 && isspace((unsigned char)*(p-1)))
238 tmp->u.string = strdup(p1);
244 #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
246 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
247 #define HAVE_CFPROPERTYLISTCREATEWITHSTREAM 1
251 cfstring2cstring(CFStringRef string)
256 str = (char *) CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
260 len = CFStringGetLength(string);
261 len = 1 + CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8);
266 if (!CFStringGetCString (string, str, len, kCFStringEncodingUTF8)) {
274 convert_content(const void *key, const void *value, void *context)
276 heim_config_section *tmp, **parent = context;
279 if (CFGetTypeID(key) != CFStringGetTypeID())
282 k = cfstring2cstring(key);
286 if (CFGetTypeID(value) == CFStringGetTypeID()) {
287 tmp = heim_config_get_entry(parent, k, heim_config_string);
288 tmp->u.string = cfstring2cstring(value);
289 } else if (CFGetTypeID(value) == CFDictionaryGetTypeID()) {
290 tmp = heim_config_get_entry(parent, k, heim_config_list);
291 CFDictionaryApplyFunction(value, convert_content, &tmp->u.list);
298 static heim_error_code
299 parse_plist_config(heim_context context, const char *path, heim_config_section **parent)
305 url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)path, strlen(path), 0);
307 heim_clear_error_message(context);
311 s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
314 heim_clear_error_message(context);
318 if (!CFReadStreamOpen(s)) {
320 heim_clear_error_message(context);
324 #ifdef HAVE_CFPROPERTYLISTCREATEWITHSTREAM
325 d = (CFDictionaryRef)CFPropertyListCreateWithStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
327 d = (CFDictionaryRef)CFPropertyListCreateFromStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
331 heim_clear_error_message(context);
335 CFDictionaryApplyFunction(d, convert_content, parent);
344 is_absolute_path(const char *path)
347 * An absolute path is one that refers to an explicit object
351 size_t len = strlen(path);
353 /* UNC path is by definition absolute */
355 && ISPATHSEP(path[0])
356 && ISPATHSEP(path[1]))
359 /* A drive letter path might be absolute */
363 && ISPATHSEP(path[2]))
367 * if no drive letter but first char is a path
368 * separator then the drive letter must be obtained
369 * from the including file.
372 /* UNIX is easy, first char '/' is absolute */
373 if (ISPATHSEP(path[0]))
380 * Parse the config file `fname', generating the structures into `res'
381 * returning error messages in `err_message'
384 static heim_error_code
385 heim_config_parse_debug(struct fileptr *f,
386 heim_config_section **res,
388 const char **err_message)
390 heim_config_section *s = NULL;
391 heim_config_binding *b = NULL;
398 while (config_fgets(buf, sizeof(buf), f) != NULL) {
402 buf[strcspn(buf, "\r\n")] = '\0';
404 while(isspace((unsigned char)*p))
406 if (*p == '#' || *p == ';')
409 ret = parse_section(p, &s, res, err_message);
413 } else if (*p == '}') {
414 *err_message = "unmatched }";
416 } else if (strncmp(p, "include", sizeof("include") - 1) == 0 &&
417 isspace(p[sizeof("include") - 1])) {
418 p += sizeof("include");
421 if (!is_absolute_path(p)) {
422 heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
423 "Configuration include path must be "
425 return HEIM_ERR_CONFIG_BADFORMAT;
427 ret = heim_config_parse_file_multi(f->context, p, res);
430 } else if (strncmp(p, "includedir", sizeof("includedir") - 1) == 0 &&
431 isspace(p[sizeof("includedir") - 1])) {
432 p += sizeof("includedir");
435 if (!is_absolute_path(p)) {
436 heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
437 "Configuration includedir path must be "
439 return HEIM_ERR_CONFIG_BADFORMAT;
441 ret = heim_config_parse_dir_multi(f->context, p, res);
444 } else if(*p != '\0') {
446 *err_message = "binding before section";
449 ret = parse_binding(f, lineno, p, &b, &s->u.list, err_message);
458 is_plist_file(const char *fname)
460 size_t len = strlen(fname);
461 char suffix[] = ".plist";
462 if (len < sizeof(suffix))
464 if (strcasecmp(&fname[len - (sizeof(suffix) - 1)], suffix) != 0)
470 * Parse configuration files in the given directory and add the result
471 * into res. Only files whose names consist only of alphanumeric
472 * characters, hyphen, and underscore, will be parsed, though files
473 * ending in ".conf" will also be parsed.
475 * This interface can be used to parse several configuration directories
476 * into one resulting heim_config_section by calling it repeatably.
478 * @param context a Kerberos 5 context.
479 * @param dname a directory name to a Kerberos configuration file
480 * @param res the returned result, must be free with heim_free_config_files().
481 * @return Return an error code or 0, see heim_get_error_message().
483 * @ingroup heim_support
487 heim_config_parse_dir_multi(heim_context context,
489 heim_config_section **res)
491 struct dirent *entry;
495 if ((d = opendir(dname)) == NULL)
498 while ((entry = readdir(d)) != NULL) {
499 char *p = entry->d_name;
505 * Here be dragons. The call to heim_config_parse_file_multi()
506 * below expands path tokens. Because of the limitations here
507 * on file naming, we can't have path tokens in the file name,
508 * so we're safe. Anyone changing this if condition here should
511 if (!isalnum(*p) && *p != '_' && *p != '-' &&
512 strcmp(p, ".conf") != 0) {
521 if (asprintf(&path, "%s/%s", dname, entry->d_name) == -1 ||
524 return heim_enomem(context);
526 ret = heim_config_parse_file_multi(context, path, res);
532 /* Ignore malformed config files so we don't lock out admins, etc... */
539 * Parse a configuration file and add the result into res. This
540 * interface can be used to parse several configuration files into one
541 * resulting heim_config_section by calling it repeatably.
543 * @param context a Kerberos 5 context.
544 * @param fname a file name to a Kerberos configuration file
545 * @param res the returned result, must be free with heim_free_config_files().
546 * @return Return an error code or 0, see heim_get_error_message().
548 * @ingroup heim_support
551 HEIMDAL_THREAD_LOCAL int config_include_depth = 0;
554 heim_config_parse_file_multi(heim_context context,
556 heim_config_section **res)
559 char *newfname = NULL;
561 heim_error_code ret = 0;
565 if (config_include_depth > 5) {
566 heim_warnx(context, "Maximum config file include depth reached; "
567 "not including %s", fname);
570 config_include_depth++;
573 * If the fname starts with "~/" parse configuration file in the
574 * current users home directory. The behavior can be disabled and
575 * enabled by calling heim_set_home_dir_access().
577 if (ISTILDE(fname[0]) && ISPATHSEP(fname[1])) {
578 if (!heim_context_get_homedir_access(context)) {
579 heim_set_error_message(context, EPERM,
580 "Access to home directory not allowed");
584 if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 ||
586 ret = heim_enomem(context);
592 if (is_plist_file(fname)) {
593 #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
594 ret = parse_plist_config(context, fname, res);
596 heim_set_error_message(context, ret,
597 "Failed to parse plist %s", fname);
601 heim_set_error_message(context, ENOENT,
602 "no support for plist configuration files");
607 char *exp_fname = NULL;
610 * Note that heim_config_parse_dir_multi() doesn't want tokens
611 * expanded here, but it happens to limit the names of files to
612 * include such that there can be no tokens to expand. Don't
613 * add token expansion for tokens using _, say.
615 ret = heim_expand_path_tokens(context, fname, 1, &exp_fname, NULL);
619 fname = newfname = exp_fname;
622 f.f = fopen(fname, "r");
624 if (f.f == NULL || fstat(fileno(f.f), &st) == -1) {
628 heim_set_error_message(context, ret, "open or stat %s: %s",
629 fname, strerror(ret));
633 if (!S_ISREG(st.st_mode)) {
635 heim_set_error_message(context, EISDIR, "not a regular file %s: %s",
636 fname, strerror(EISDIR));
641 ret = heim_config_parse_debug(&f, res, &lineno, &str);
644 if (ret != HEIM_ERR_CONFIG_BADFORMAT)
645 ret = HEIM_ERR_CONFIG_BADFORMAT;
646 heim_set_error_message(context, ret, "%s:%u: %s",
653 config_include_depth--;
654 if (ret == HEIM_ERR_CONFIG_BADFORMAT || (ret && config_include_depth > 0)) {
655 heim_warn(context, ret, "Ignoring");
656 if (config_include_depth > 0)
664 heim_config_parse_file(heim_context context,
666 heim_config_section **res)
669 return heim_config_parse_file_multi(context, fname, res);
673 free_binding(heim_context context, heim_config_binding *b)
675 heim_config_binding *next_b;
679 assert(b->type == heim_config_string || b->type == heim_config_list);
680 if (b->type == heim_config_string)
683 free_binding (context, b->u.list);
691 * Free configuration file section, the result of
692 * heim_config_parse_file() and heim_config_parse_file_multi().
694 * @param context A Kerberos 5 context
695 * @param s the configuration section to free
697 * @return returns 0 on successes, otherwise an error code, see
698 * heim_get_error_message()
700 * @ingroup heim_support
704 heim_config_file_free(heim_context context, heim_config_section *s)
706 free_binding (context, s);
710 #ifndef HEIMDAL_SMALLER
713 heim_config_copy(heim_context context,
714 heim_config_section *c,
715 heim_config_section **head)
717 heim_config_binding *d, *previous = NULL;
722 d = calloc(1, sizeof(*d));
727 d->name = strdup(c->name);
729 assert(d->type == heim_config_string || d->type == heim_config_list);
730 if (d->type == heim_config_string)
731 d->u.string = strdup(c->u.string);
733 heim_config_copy (context, c->u.list, &d->u.list);
743 #endif /* HEIMDAL_SMALLER */
746 heim_config_get_next(heim_context context,
747 const heim_config_section *c,
748 const heim_config_binding **pointer,
755 va_start(args, type);
756 ret = heim_config_vget_next(context, c, pointer, type, args);
762 vget_next(heim_context context,
763 const heim_config_binding *b,
764 const heim_config_binding **pointer,
769 const char *p = va_arg(args, const char *);
772 if (strcmp(b->name, name) == 0) {
773 if (b->type == (unsigned)type && p == NULL) {
776 } else if (b->type == heim_config_list && p != NULL) {
777 return vget_next(context, b->u.list, pointer, type, p, args);
786 heim_config_vget_next(heim_context context,
787 const heim_config_section *c,
788 const heim_config_binding **pointer,
792 const heim_config_binding *b;
798 if (*pointer == NULL) {
799 /* first time here, walk down the tree looking for the right
801 p = va_arg(args, const char *);
804 return vget_next(context, c, pointer, type, p, args);
807 /* we were called again, so just look for more entries with the
808 same name and type */
809 for (b = (*pointer)->next; b != NULL; b = b->next) {
810 if(strcmp(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) {
819 heim_config_get(heim_context context,
820 const heim_config_section *c,
827 va_start(args, type);
828 ret = heim_config_vget(context, c, type, args);
835 heim_config_vget(heim_context context,
836 const heim_config_section *c,
840 const heim_config_binding *foo = NULL;
842 return heim_config_vget_next(context, c, &foo, type, args);
846 * Get a list of configuration binding list for more processing
848 * @param context A Kerberos 5 context.
849 * @param c a configuration section, or NULL to use the section from context
850 * @param ... a list of names, terminated with NULL.
852 * @return NULL if configuration list is not found, a list otherwise
854 * @ingroup heim_support
857 const heim_config_binding *
858 heim_config_get_list(heim_context context,
859 const heim_config_section *c,
862 const heim_config_binding *ret;
866 ret = heim_config_vget_list(context, c, args);
872 * Get a list of configuration binding list for more processing
874 * @param context A Kerberos 5 context.
875 * @param c a configuration section, or NULL to use the section from context
876 * @param args a va_list of arguments
878 * @return NULL if configuration list is not found, a list otherwise
880 * @ingroup heim_support
883 const heim_config_binding *
884 heim_config_vget_list(heim_context context,
885 const heim_config_section *c,
888 return heim_config_vget(context, c, heim_config_list, args);
892 * Returns a "const char *" to a string in the configuration database.
893 * The string may not be valid after a reload of the configuration
894 * database so a caller should make a local copy if it needs to keep
897 * @param context A Kerberos 5 context.
898 * @param c a configuration section, or NULL to use the section from context
899 * @param ... a list of names, terminated with NULL.
901 * @return NULL if configuration string not found, a string otherwise
903 * @ingroup heim_support
907 heim_config_get_string(heim_context context,
908 const heim_config_section *c,
915 ret = heim_config_vget_string(context, c, args);
921 * Like heim_config_get_string(), but uses a va_list instead of ...
923 * @param context A Kerberos 5 context.
924 * @param c a configuration section, or NULL to use the section from context
925 * @param args a va_list of arguments
927 * @return NULL if configuration string not found, a string otherwise
929 * @ingroup heim_support
933 heim_config_vget_string(heim_context context,
934 const heim_config_section *c,
937 return heim_config_vget(context, c, heim_config_string, args);
941 * Like heim_config_vget_string(), but instead of returning NULL,
942 * instead return a default value.
944 * @param context A Kerberos 5 context.
945 * @param c a configuration section, or NULL to use the section from context
946 * @param def_value the default value to return if no configuration
947 * found in the database.
948 * @param args a va_list of arguments
950 * @return a configuration string
952 * @ingroup heim_support
956 heim_config_vget_string_default(heim_context context,
957 const heim_config_section *c,
958 const char *def_value,
963 ret = heim_config_vget_string(context, c, args);
970 * Like heim_config_get_string(), but instead of returning NULL,
971 * instead return a default value.
973 * @param context A Kerberos 5 context.
974 * @param c a configuration section, or NULL to use the section from context
975 * @param def_value the default value to return if no configuration
976 * found in the database.
977 * @param ... a list of names, terminated with NULL.
979 * @return a configuration string
981 * @ingroup heim_support
985 heim_config_get_string_default(heim_context context,
986 const heim_config_section *c,
987 const char *def_value,
993 va_start(args, def_value);
994 ret = heim_config_vget_string_default (context, c, def_value, args);
1000 next_component_string(char * begin, const char * delims, char **state)
1011 while (*end == '"') {
1012 char * t = strchr(end + 1, '"');
1023 pos = strcspn(end, delims);
1030 if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
1031 begin++; *(end - 1) = '\0';
1037 if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
1038 begin++; *(end - 1) = '\0';
1044 * Get a list of configuration strings, free the result with
1045 * heim_config_free_strings().
1047 * @param context A Kerberos 5 context.
1048 * @param c a configuration section, or NULL to use the section from context
1049 * @param args a va_list of arguments
1051 * @return TRUE or FALSE
1053 * @ingroup heim_support
1057 heim_config_vget_strings(heim_context context,
1058 const heim_config_section *c,
1061 char **strings = NULL;
1063 const heim_config_binding *b = NULL;
1066 while((p = heim_config_vget_next(context, c, &b,
1067 heim_config_string, args))) {
1068 char *tmp = strdup(p);
1073 s = next_component_string(tmp, " \t", &pos);
1075 char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
1081 strings[nstr] = strdup(s);
1083 if(strings[nstr-1] == NULL) {
1087 s = next_component_string(NULL, " \t", &pos);
1092 char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
1096 strings[nstr] = NULL;
1101 free(strings[nstr]);
1108 * Get a list of configuration strings, free the result with
1109 * heim_config_free_strings().
1111 * @param context A Kerberos 5 context.
1112 * @param c a configuration section, or NULL to use the section from context
1113 * @param ... a list of names, terminated with NULL.
1115 * @return TRUE or FALSE
1117 * @ingroup heim_support
1121 heim_config_get_strings(heim_context context,
1122 const heim_config_section *c,
1128 ret = heim_config_vget_strings(context, c, ap);
1134 * Free the resulting strings from heim_config-get_strings() and
1135 * heim_config_vget_strings().
1137 * @param strings strings to free
1139 * @ingroup heim_support
1143 heim_config_free_strings(char **strings)
1155 * Like heim_config_get_bool_default() but with a va_list list of
1156 * configuration selection.
1158 * Configuration value to a boolean value, where yes/true and any
1159 * non-zero number means TRUE and other value is FALSE.
1161 * @param context A Kerberos 5 context.
1162 * @param c a configuration section, or NULL to use the section from context
1163 * @param def_value the default value to return if no configuration
1164 * found in the database.
1165 * @param args a va_list of arguments
1167 * @return TRUE or FALSE
1169 * @ingroup heim_support
1173 heim_config_vget_bool_default(heim_context context,
1174 const heim_config_section *c,
1179 str = heim_config_vget_string(context, c, args);
1182 return !!(strcasecmp(str, "yes") == 0 ||
1183 strcasecmp(str, "true") == 0 ||
1188 * heim_config_get_bool() will convert the configuration
1189 * option value to a boolean value, where yes/true and any non-zero
1190 * number means TRUE and other value is FALSE.
1192 * @param context A Kerberos 5 context.
1193 * @param c a configuration section, or NULL to use the section from context
1194 * @param args a va_list of arguments
1196 * @return TRUE or FALSE
1198 * @ingroup heim_support
1202 heim_config_vget_bool(heim_context context,
1203 const heim_config_section *c,
1206 return heim_config_vget_bool_default(context, c, 0, args);
1210 * heim_config_get_bool_default() will convert the configuration
1211 * option value to a boolean value, where yes/true and any non-zero
1212 * number means TRUE and other value is FALSE.
1214 * @param context A Kerberos 5 context.
1215 * @param c a configuration section, or NULL to use the section from context
1216 * @param def_value the default value to return if no configuration
1217 * found in the database.
1218 * @param ... a list of names, terminated with NULL.
1220 * @return TRUE or FALSE
1222 * @ingroup heim_support
1226 heim_config_get_bool_default(heim_context context,
1227 const heim_config_section *c,
1234 va_start(ap, def_value);
1235 ret = heim_config_vget_bool_default(context, c, def_value, ap);
1241 * Like heim_config_get_bool() but with a va_list list of
1242 * configuration selection.
1244 * Configuration value to a boolean value, where yes/true and any
1245 * non-zero number means TRUE and other value is FALSE.
1247 * @param context A Kerberos 5 context.
1248 * @param c a configuration section, or NULL to use the section from context
1249 * @param ... a list of names, terminated with NULL.
1251 * @return TRUE or FALSE
1253 * @ingroup heim_support
1257 heim_config_get_bool(heim_context context,
1258 const heim_config_section *c,
1264 ret = heim_config_vget_bool (context, c, ap);
1270 * Get the time from the configuration file using a relative time.
1272 * Like heim_config_get_time_default() but with a va_list list of
1273 * configuration selection.
1275 * @param context A Kerberos 5 context.
1276 * @param c a configuration section, or NULL to use the section from context
1277 * @param def_value the default value to return if no configuration
1278 * found in the database.
1279 * @param args a va_list of arguments
1281 * @return parsed the time (or def_value on parse error)
1283 * @ingroup heim_support
1287 heim_config_vget_time_default(heim_context context,
1288 const heim_config_section *c,
1295 if ((str = heim_config_vget_string(context, c, args)))
1296 t = parse_time(str, "s");
1297 return t != -1 ? t : def_value;
1301 * Get the time from the configuration file using a relative time, for example: 1h30s
1303 * @param context A Kerberos 5 context.
1304 * @param c a configuration section, or NULL to use the section from context
1305 * @param args a va_list of arguments
1307 * @return parsed the time or -1 on error
1309 * @ingroup heim_support
1313 heim_config_vget_time(heim_context context,
1314 const heim_config_section *c,
1317 return heim_config_vget_time_default(context, c, -1, args);
1321 * Get the time from the configuration file using a relative time, for example: 1h30s
1323 * @param context A Kerberos 5 context.
1324 * @param c a configuration section, or NULL to use the section from context
1325 * @param def_value the default value to return if no configuration
1326 * found in the database.
1327 * @param ... a list of names, terminated with NULL.
1329 * @return parsed the time (or def_value on parse error)
1331 * @ingroup heim_support
1335 heim_config_get_time_default(heim_context context,
1336 const heim_config_section *c,
1343 va_start(ap, def_value);
1344 ret = heim_config_vget_time_default(context, c, def_value, ap);
1350 * Get the time from the configuration file using a relative time, for example: 1h30s
1352 * @param context A Kerberos 5 context.
1353 * @param c a configuration section, or NULL to use the section from context
1354 * @param ... a list of names, terminated with NULL.
1356 * @return parsed the time or -1 on error
1358 * @ingroup heim_support
1362 heim_config_get_time(heim_context context,
1363 const heim_config_section *c,
1369 ret = heim_config_vget_time(context, c, ap);
1376 heim_config_vget_int_default(heim_context context,
1377 const heim_config_section *c,
1382 str = heim_config_vget_string (context, c, args);
1388 l = strtol(str, &endptr, 0);
1397 heim_config_vget_int(heim_context context,
1398 const heim_config_section *c,
1401 return heim_config_vget_int_default(context, c, -1, args);
1405 heim_config_get_int_default(heim_context context,
1406 const heim_config_section *c,
1413 va_start(ap, def_value);
1414 ret = heim_config_vget_int_default(context, c, def_value, ap);
1420 heim_config_get_int(heim_context context,
1421 const heim_config_section *c,
1427 ret = heim_config_vget_int (context, c, ap);
1432 #ifndef HEIMDAL_SMALLER
1434 heim_config_parse_string_multi(heim_context context,
1436 heim_config_section **res)
1439 unsigned lineno = 0;
1440 heim_error_code ret;
1443 f.context = context;
1447 ret = heim_config_parse_debug(&f, res, &lineno, &str);
1449 if (ret != HEIM_ERR_CONFIG_BADFORMAT) {
1450 ret = HEIM_ERR_CONFIG_BADFORMAT;
1451 heim_set_error_message(context, ret, "%s:%u: %s",
1452 "<constant>", lineno, str);