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 */
361 && isalpha((unsigned char)path
[0])
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((unsigned char)p
[sizeof("include") - 1])) {
418 p
+= sizeof("include");
419 while (isspace((unsigned char)*p
))
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((unsigned char)p
[sizeof("includedir") - 1])) {
432 p
+= sizeof("includedir");
433 while (isspace((unsigned char)*p
))
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((unsigned char)*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 is_devnull(struct stat
*st
)
544 struct stat devnullst
;
546 if (stat("/dev/null", &devnullst
) == -1)
548 return st
->st_dev
== devnullst
.st_dev
&& st
->st_ino
== devnullst
.st_ino
;
552 HEIMDAL_THREAD_LOCAL
int config_include_depth
= 0;
555 * Parse a configuration file and add the result into res. This
556 * interface can be used to parse several configuration files into one
557 * resulting heim_config_section by calling it repeatably.
559 * @param context a Kerberos 5 context.
560 * @param fname a file name to a Kerberos configuration file
561 * @param res the returned result, must be free with heim_free_config_files().
562 * @return Return an error code or 0, see heim_get_error_message().
564 * @ingroup heim_support
568 heim_config_parse_file_multi(heim_context context
,
570 heim_config_section
**res
)
573 char *newfname
= NULL
;
575 heim_error_code ret
= 0;
579 if (config_include_depth
> 5) {
580 heim_warnx(context
, "Maximum config file include depth reached; "
581 "not including %s", fname
);
584 config_include_depth
++;
587 * If the fname starts with "~/" parse configuration file in the
588 * current users home directory. The behavior can be disabled and
589 * enabled by calling heim_set_home_dir_access().
591 if (ISTILDE(fname
[0]) && ISPATHSEP(fname
[1])) {
592 if (!heim_context_get_homedir_access(context
)) {
593 heim_set_error_message(context
, EPERM
,
594 "Access to home directory not allowed");
598 if (asprintf(&newfname
, "%%{USERCONFIG}%s", &fname
[1]) < 0 ||
600 ret
= heim_enomem(context
);
606 if (is_plist_file(fname
)) {
607 #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
608 ret
= parse_plist_config(context
, fname
, res
);
610 heim_set_error_message(context
, ret
,
611 "Failed to parse plist %s", fname
);
615 heim_set_error_message(context
, ENOENT
,
616 "no support for plist configuration files");
621 char *exp_fname
= NULL
;
624 * Note that heim_config_parse_dir_multi() doesn't want tokens
625 * expanded here, but it happens to limit the names of files to
626 * include such that there can be no tokens to expand. Don't
627 * add token expansion for tokens using _, say.
629 ret
= heim_expand_path_tokens(context
, fname
, 1, &exp_fname
, NULL
);
633 fname
= newfname
= exp_fname
;
636 f
.f
= fopen(fname
, "r");
638 if (f
.f
== NULL
|| fstat(fileno(f
.f
), &st
) == -1) {
642 heim_set_error_message(context
, ret
, "open or stat %s: %s",
643 fname
, strerror(ret
));
647 if (!S_ISREG(st
.st_mode
) && !is_devnull(&st
)) {
649 heim_set_error_message(context
, EISDIR
, "not a regular file %s: %s",
650 fname
, strerror(EISDIR
));
655 ret
= heim_config_parse_debug(&f
, res
, &lineno
, &str
);
658 if (ret
!= HEIM_ERR_CONFIG_BADFORMAT
)
659 ret
= HEIM_ERR_CONFIG_BADFORMAT
;
660 heim_set_error_message(context
, ret
, "%s:%u: %s",
667 config_include_depth
--;
668 if (ret
== HEIM_ERR_CONFIG_BADFORMAT
|| (ret
&& config_include_depth
> 0)) {
669 heim_warn(context
, ret
, "Ignoring");
670 if (config_include_depth
> 0)
678 heim_config_parse_file(heim_context context
,
680 heim_config_section
**res
)
683 return heim_config_parse_file_multi(context
, fname
, res
);
687 free_binding(heim_context context
, heim_config_binding
*b
)
689 heim_config_binding
*next_b
;
693 assert(b
->type
== heim_config_string
|| b
->type
== heim_config_list
);
694 if (b
->type
== heim_config_string
)
697 free_binding (context
, b
->u
.list
);
705 * Free configuration file section, the result of
706 * heim_config_parse_file() and heim_config_parse_file_multi().
708 * @param context A Kerberos 5 context
709 * @param s the configuration section to free
711 * @return returns 0 on successes, otherwise an error code, see
712 * heim_get_error_message()
714 * @ingroup heim_support
718 heim_config_file_free(heim_context context
, heim_config_section
*s
)
720 free_binding (context
, s
);
724 #ifndef HEIMDAL_SMALLER
727 heim_config_copy(heim_context context
,
728 heim_config_section
*c
,
729 heim_config_section
**head
)
731 heim_config_binding
*d
, *previous
= NULL
;
736 d
= calloc(1, sizeof(*d
));
741 d
->name
= strdup(c
->name
);
743 assert(d
->type
== heim_config_string
|| d
->type
== heim_config_list
);
744 if (d
->type
== heim_config_string
)
745 d
->u
.string
= strdup(c
->u
.string
);
747 heim_config_copy (context
, c
->u
.list
, &d
->u
.list
);
757 #endif /* HEIMDAL_SMALLER */
760 heim_config_get_next(heim_context context
,
761 const heim_config_section
*c
,
762 const heim_config_binding
**pointer
,
769 va_start(args
, type
);
770 ret
= heim_config_vget_next(context
, c
, pointer
, type
, args
);
776 vget_next(heim_context context
,
777 const heim_config_binding
*b
,
778 const heim_config_binding
**pointer
,
783 const char *p
= va_arg(args
, const char *);
786 if (strcmp(b
->name
, name
) == 0) {
787 if (b
->type
== (unsigned)type
&& p
== NULL
) {
790 } else if (b
->type
== heim_config_list
&& p
!= NULL
) {
791 return vget_next(context
, b
->u
.list
, pointer
, type
, p
, args
);
800 heim_config_vget_next(heim_context context
,
801 const heim_config_section
*c
,
802 const heim_config_binding
**pointer
,
806 const heim_config_binding
*b
;
812 if (*pointer
== NULL
) {
813 /* first time here, walk down the tree looking for the right
815 p
= va_arg(args
, const char *);
818 return vget_next(context
, c
, pointer
, type
, p
, args
);
821 /* we were called again, so just look for more entries with the
822 same name and type */
823 for (b
= (*pointer
)->next
; b
!= NULL
; b
= b
->next
) {
824 if(strcmp(b
->name
, (*pointer
)->name
) == 0 && b
->type
== (unsigned)type
) {
833 heim_config_get(heim_context context
,
834 const heim_config_section
*c
,
841 va_start(args
, type
);
842 ret
= heim_config_vget(context
, c
, type
, args
);
849 heim_config_vget(heim_context context
,
850 const heim_config_section
*c
,
854 const heim_config_binding
*foo
= NULL
;
856 return heim_config_vget_next(context
, c
, &foo
, type
, args
);
860 * Get a list of configuration binding list for more processing
862 * @param context A Kerberos 5 context.
863 * @param c a configuration section, or NULL to use the section from context
864 * @param ... a list of names, terminated with NULL.
866 * @return NULL if configuration list is not found, a list otherwise
868 * @ingroup heim_support
871 const heim_config_binding
*
872 heim_config_get_list(heim_context context
,
873 const heim_config_section
*c
,
876 const heim_config_binding
*ret
;
880 ret
= heim_config_vget_list(context
, c
, args
);
886 * Get a list of configuration binding list for more processing
888 * @param context A Kerberos 5 context.
889 * @param c a configuration section, or NULL to use the section from context
890 * @param args a va_list of arguments
892 * @return NULL if configuration list is not found, a list otherwise
894 * @ingroup heim_support
897 const heim_config_binding
*
898 heim_config_vget_list(heim_context context
,
899 const heim_config_section
*c
,
902 return heim_config_vget(context
, c
, heim_config_list
, args
);
906 * Returns a "const char *" to a string in the configuration database.
907 * The string may not be valid after a reload of the configuration
908 * database so a caller should make a local copy if it needs to keep
911 * @param context A Kerberos 5 context.
912 * @param c a configuration section, or NULL to use the section from context
913 * @param ... a list of names, terminated with NULL.
915 * @return NULL if configuration string not found, a string otherwise
917 * @ingroup heim_support
921 heim_config_get_string(heim_context context
,
922 const heim_config_section
*c
,
929 ret
= heim_config_vget_string(context
, c
, args
);
935 * Like heim_config_get_string(), but uses a va_list instead of ...
937 * @param context A Kerberos 5 context.
938 * @param c a configuration section, or NULL to use the section from context
939 * @param args a va_list of arguments
941 * @return NULL if configuration string not found, a string otherwise
943 * @ingroup heim_support
947 heim_config_vget_string(heim_context context
,
948 const heim_config_section
*c
,
951 return heim_config_vget(context
, c
, heim_config_string
, args
);
955 * Like heim_config_vget_string(), but instead of returning NULL,
956 * instead return a default value.
958 * @param context A Kerberos 5 context.
959 * @param c a configuration section, or NULL to use the section from context
960 * @param def_value the default value to return if no configuration
961 * found in the database.
962 * @param args a va_list of arguments
964 * @return a configuration string
966 * @ingroup heim_support
970 heim_config_vget_string_default(heim_context context
,
971 const heim_config_section
*c
,
972 const char *def_value
,
977 ret
= heim_config_vget_string(context
, c
, args
);
984 * Like heim_config_get_string(), but instead of returning NULL,
985 * instead return a default value.
987 * @param context A Kerberos 5 context.
988 * @param c a configuration section, or NULL to use the section from context
989 * @param def_value the default value to return if no configuration
990 * found in the database.
991 * @param ... a list of names, terminated with NULL.
993 * @return a configuration string
995 * @ingroup heim_support
999 heim_config_get_string_default(heim_context context
,
1000 const heim_config_section
*c
,
1001 const char *def_value
,
1007 va_start(args
, def_value
);
1008 ret
= heim_config_vget_string_default (context
, c
, def_value
, args
);
1014 next_component_string(char * begin
, const char * delims
, char **state
)
1025 while (*end
== '"') {
1026 char * t
= strchr(end
+ 1, '"');
1037 pos
= strcspn(end
, delims
);
1044 if (*begin
== '"' && *(end
- 1) == '"' && begin
+ 1 < end
) {
1045 begin
++; *(end
- 1) = '\0';
1051 if (*begin
== '"' && *(end
- 1) == '"' && begin
+ 1 < end
) {
1052 begin
++; *(end
- 1) = '\0';
1058 * Get a list of configuration strings, free the result with
1059 * heim_config_free_strings().
1061 * @param context A Kerberos 5 context.
1062 * @param c a configuration section, or NULL to use the section from context
1063 * @param args a va_list of arguments
1065 * @return TRUE or FALSE
1067 * @ingroup heim_support
1071 heim_config_vget_strings(heim_context context
,
1072 const heim_config_section
*c
,
1075 char **strings
= NULL
;
1077 const heim_config_binding
*b
= NULL
;
1080 while((p
= heim_config_vget_next(context
, c
, &b
,
1081 heim_config_string
, args
))) {
1082 char *tmp
= strdup(p
);
1087 s
= next_component_string(tmp
, " \t", &pos
);
1089 char **tmp2
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
1095 strings
[nstr
] = strdup(s
);
1097 if(strings
[nstr
-1] == NULL
) {
1101 s
= next_component_string(NULL
, " \t", &pos
);
1106 char **tmp
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
1110 strings
[nstr
] = NULL
;
1115 free(strings
[nstr
]);
1122 * Get a list of configuration strings, free the result with
1123 * heim_config_free_strings().
1125 * @param context A Kerberos 5 context.
1126 * @param c a configuration section, or NULL to use the section from context
1127 * @param ... a list of names, terminated with NULL.
1129 * @return TRUE or FALSE
1131 * @ingroup heim_support
1135 heim_config_get_strings(heim_context context
,
1136 const heim_config_section
*c
,
1142 ret
= heim_config_vget_strings(context
, c
, ap
);
1148 * Free the resulting strings from heim_config-get_strings() and
1149 * heim_config_vget_strings().
1151 * @param strings strings to free
1153 * @ingroup heim_support
1157 heim_config_free_strings(char **strings
)
1169 * Like heim_config_get_bool_default() but with a va_list list of
1170 * configuration selection.
1172 * Configuration value to a boolean value, where yes/true and any
1173 * non-zero number means TRUE and other value is FALSE.
1175 * @param context A Kerberos 5 context.
1176 * @param c a configuration section, or NULL to use the section from context
1177 * @param def_value the default value to return if no configuration
1178 * found in the database.
1179 * @param args a va_list of arguments
1181 * @return TRUE or FALSE
1183 * @ingroup heim_support
1187 heim_config_vget_bool_default(heim_context context
,
1188 const heim_config_section
*c
,
1193 str
= heim_config_vget_string(context
, c
, args
);
1196 return !!(strcasecmp(str
, "yes") == 0 ||
1197 strcasecmp(str
, "true") == 0 ||
1202 * heim_config_get_bool() will convert the configuration
1203 * option value to a boolean value, where yes/true and any non-zero
1204 * number means TRUE and other value is FALSE.
1206 * @param context A Kerberos 5 context.
1207 * @param c a configuration section, or NULL to use the section from context
1208 * @param args a va_list of arguments
1210 * @return TRUE or FALSE
1212 * @ingroup heim_support
1216 heim_config_vget_bool(heim_context context
,
1217 const heim_config_section
*c
,
1220 return heim_config_vget_bool_default(context
, c
, 0, args
);
1224 * heim_config_get_bool_default() will convert the configuration
1225 * option value to a boolean value, where yes/true and any non-zero
1226 * number means TRUE and other value is FALSE.
1228 * @param context A Kerberos 5 context.
1229 * @param c a configuration section, or NULL to use the section from context
1230 * @param def_value the default value to return if no configuration
1231 * found in the database.
1232 * @param ... a list of names, terminated with NULL.
1234 * @return TRUE or FALSE
1236 * @ingroup heim_support
1240 heim_config_get_bool_default(heim_context context
,
1241 const heim_config_section
*c
,
1248 va_start(ap
, def_value
);
1249 ret
= heim_config_vget_bool_default(context
, c
, def_value
, ap
);
1255 * Like heim_config_get_bool() but with a va_list list of
1256 * configuration selection.
1258 * Configuration value to a boolean value, where yes/true and any
1259 * non-zero number means TRUE and other value is FALSE.
1261 * @param context A Kerberos 5 context.
1262 * @param c a configuration section, or NULL to use the section from context
1263 * @param ... a list of names, terminated with NULL.
1265 * @return TRUE or FALSE
1267 * @ingroup heim_support
1271 heim_config_get_bool(heim_context context
,
1272 const heim_config_section
*c
,
1278 ret
= heim_config_vget_bool (context
, c
, ap
);
1284 * Get the time from the configuration file using a relative time.
1286 * Like heim_config_get_time_default() but with a va_list list of
1287 * configuration selection.
1289 * @param context A Kerberos 5 context.
1290 * @param c a configuration section, or NULL to use the section from context
1291 * @param def_value the default value to return if no configuration
1292 * found in the database.
1293 * @param args a va_list of arguments
1295 * @return parsed the time (or def_value on parse error)
1297 * @ingroup heim_support
1301 heim_config_vget_time_default(heim_context context
,
1302 const heim_config_section
*c
,
1309 if ((str
= heim_config_vget_string(context
, c
, args
)))
1310 t
= parse_time(str
, "s");
1311 return t
!= -1 ? t
: def_value
;
1315 * Get the time from the configuration file using a relative time, for example: 1h30s
1317 * @param context A Kerberos 5 context.
1318 * @param c a configuration section, or NULL to use the section from context
1319 * @param args a va_list of arguments
1321 * @return parsed the time or -1 on error
1323 * @ingroup heim_support
1327 heim_config_vget_time(heim_context context
,
1328 const heim_config_section
*c
,
1331 return heim_config_vget_time_default(context
, c
, -1, args
);
1335 * Get the time from the configuration file using a relative time, for example: 1h30s
1337 * @param context A Kerberos 5 context.
1338 * @param c a configuration section, or NULL to use the section from context
1339 * @param def_value the default value to return if no configuration
1340 * found in the database.
1341 * @param ... a list of names, terminated with NULL.
1343 * @return parsed the time (or def_value on parse error)
1345 * @ingroup heim_support
1349 heim_config_get_time_default(heim_context context
,
1350 const heim_config_section
*c
,
1357 va_start(ap
, def_value
);
1358 ret
= heim_config_vget_time_default(context
, c
, def_value
, ap
);
1364 * Get the time from the configuration file using a relative time, for example: 1h30s
1366 * @param context A Kerberos 5 context.
1367 * @param c a configuration section, or NULL to use the section from context
1368 * @param ... a list of names, terminated with NULL.
1370 * @return parsed the time or -1 on error
1372 * @ingroup heim_support
1376 heim_config_get_time(heim_context context
,
1377 const heim_config_section
*c
,
1383 ret
= heim_config_vget_time(context
, c
, ap
);
1390 heim_config_vget_int_default(heim_context context
,
1391 const heim_config_section
*c
,
1396 str
= heim_config_vget_string (context
, c
, args
);
1402 l
= strtol(str
, &endptr
, 0);
1411 heim_config_vget_int(heim_context context
,
1412 const heim_config_section
*c
,
1415 return heim_config_vget_int_default(context
, c
, -1, args
);
1419 heim_config_get_int_default(heim_context context
,
1420 const heim_config_section
*c
,
1427 va_start(ap
, def_value
);
1428 ret
= heim_config_vget_int_default(context
, c
, def_value
, ap
);
1434 heim_config_get_int(heim_context context
,
1435 const heim_config_section
*c
,
1441 ret
= heim_config_vget_int (context
, c
, ap
);
1446 #ifndef HEIMDAL_SMALLER
1448 heim_config_parse_string_multi(heim_context context
,
1450 heim_config_section
**res
)
1453 unsigned lineno
= 0;
1454 heim_error_code ret
;
1457 f
.context
= context
;
1461 ret
= heim_config_parse_debug(&f
, res
, &lineno
, &str
);
1463 if (ret
!= HEIM_ERR_CONFIG_BADFORMAT
) {
1464 ret
= HEIM_ERR_CONFIG_BADFORMAT
;
1465 heim_set_error_message(context
, ret
, "%s:%u: %s",
1466 "<constant>", lineno
, str
);