Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : *
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer.
14 : *
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.
18 : *
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.
22 : *
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
33 : * SUCH DAMAGE.
34 : */
35 :
36 : #include "baselocl.h"
37 : #include <assert.h>
38 : #include <ctype.h>
39 : #include <parse_time.h>
40 :
41 : #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
42 : #include <CoreFoundation/CoreFoundation.h>
43 : #endif
44 :
45 : /* Gaah! I want a portable funopen */
46 : struct fileptr {
47 : heim_context context;
48 : const char *s;
49 : FILE *f;
50 : };
51 :
52 : static char *
53 76573417 : config_fgets(char *str, size_t len, struct fileptr *ptr)
54 : {
55 : /* XXX this is not correct, in that they don't do the same if the
56 : line is longer than len */
57 76573417 : if(ptr->f != NULL)
58 78413355 : return fgets(str, len, ptr->f);
59 : else {
60 : /* this is almost strsep_copy */
61 0 : const char *p;
62 0 : ssize_t l;
63 0 : if(*ptr->s == '\0')
64 0 : return NULL;
65 0 : p = ptr->s + strcspn(ptr->s, "\n");
66 0 : if(*p == '\n')
67 0 : p++;
68 0 : l = min(len, (size_t)(p - ptr->s));
69 0 : if(len > 0) {
70 0 : memcpy(str, ptr->s, l);
71 0 : str[l] = '\0';
72 : }
73 0 : ptr->s = p;
74 0 : return str;
75 : }
76 : }
77 :
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);
88 :
89 : heim_config_section *
90 49531496 : heim_config_get_entry(heim_config_section **parent, const char *name, int type)
91 : {
92 1173791 : heim_config_section **q;
93 :
94 146634587 : for (q = parent; *q != NULL; q = &(*q)->next)
95 97104479 : if (type == heim_config_list &&
96 18802582 : (unsigned)type == (*q)->type &&
97 18802582 : strcmp(name, (*q)->name) == 0)
98 1388 : return *q;
99 49530108 : *q = calloc(1, sizeof(**q));
100 49530108 : if (*q == NULL)
101 0 : return NULL;
102 49530108 : (*q)->name = strdup(name);
103 49530108 : (*q)->type = type;
104 49530108 : if ((*q)->name == NULL) {
105 0 : free(*q);
106 0 : *q = NULL;
107 0 : return NULL;
108 : }
109 48356317 : return *q;
110 : }
111 :
112 : /*
113 : * Parse a section:
114 : *
115 : * [section]
116 : * foo = bar
117 : * b = {
118 : * a
119 : * }
120 : * ...
121 : *
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'.
125 : */
126 :
127 : static heim_error_code
128 4915462 : parse_section(char *p, heim_config_section **s, heim_config_section **parent,
129 : const char **err_message)
130 : {
131 126848 : char *p1;
132 126848 : heim_config_section *tmp;
133 :
134 4915462 : p1 = strchr (p + 1, ']');
135 4915462 : if (p1 == NULL) {
136 0 : *err_message = "missing ]";
137 0 : return HEIM_ERR_CONFIG_BADFORMAT;
138 : }
139 4915462 : *p1 = '\0';
140 4915462 : tmp = heim_config_get_entry(parent, p + 1, heim_config_list);
141 4915462 : if(tmp == NULL) {
142 0 : *err_message = "out of memory";
143 0 : return HEIM_ERR_CONFIG_BADFORMAT;
144 : }
145 4915462 : *s = tmp;
146 4915462 : return 0;
147 : }
148 :
149 : /*
150 : * Parse a brace-enclosed list from `f', hooking in the structure at
151 : * `parent'.
152 : * Store the error message in `err_message'.
153 : */
154 :
155 : static heim_error_code
156 5680370 : parse_list(struct fileptr *f, unsigned *lineno, heim_config_binding **parent,
157 : const char **err_message)
158 : {
159 126932 : char buf[2048];
160 126932 : heim_error_code ret;
161 5680370 : heim_config_binding *b = NULL;
162 5680370 : unsigned beg_lineno = *lineno;
163 :
164 28393740 : while(config_fgets(buf, sizeof(buf), f) != NULL) {
165 634588 : char *p;
166 :
167 28393740 : ++*lineno;
168 28393740 : buf[strcspn(buf, "\r\n")] = '\0';
169 28393740 : p = buf;
170 79516810 : while(isspace((unsigned char)*p))
171 51123070 : ++p;
172 28393740 : if (*p == '#' || *p == ';' || *p == '\0')
173 0 : continue;
174 28393740 : while(isspace((unsigned char)*p))
175 0 : ++p;
176 28393740 : if (*p == '}')
177 5553438 : return 0;
178 22713370 : if (*p == '\0')
179 0 : continue;
180 22713370 : ret = parse_binding (f, lineno, p, &b, parent, err_message);
181 22713370 : if (ret)
182 0 : return ret;
183 : }
184 0 : *lineno = beg_lineno;
185 0 : *err_message = "unclosed {";
186 0 : return HEIM_ERR_CONFIG_BADFORMAT;
187 : }
188 :
189 : /*
190 : *
191 : */
192 :
193 : static heim_error_code
194 44616034 : parse_binding(struct fileptr *f, unsigned *lineno, char *p,
195 : heim_config_binding **b, heim_config_binding **parent,
196 : const char **err_message)
197 : {
198 1046943 : heim_config_binding *tmp;
199 1046943 : char *p1, *p2;
200 44616034 : heim_error_code ret = 0;
201 :
202 44616034 : p1 = p;
203 714460478 : while (*p && *p != '=' && !isspace((unsigned char)*p))
204 669844444 : ++p;
205 44616034 : if (*p == '\0') {
206 0 : *err_message = "missing =";
207 0 : return HEIM_ERR_CONFIG_BADFORMAT;
208 : }
209 43569091 : p2 = p;
210 89232068 : while (isspace((unsigned char)*p))
211 44616034 : ++p;
212 44616034 : if (*p != '=') {
213 0 : *err_message = "missing =";
214 0 : return HEIM_ERR_CONFIG_BADFORMAT;
215 : }
216 44616034 : ++p;
217 89232068 : while(isspace((unsigned char)*p))
218 44616034 : ++p;
219 44616034 : *p2 = '\0';
220 44616034 : if (*p == '{') {
221 5680370 : tmp = heim_config_get_entry(parent, p1, heim_config_list);
222 5680370 : if (tmp == NULL) {
223 0 : *err_message = "out of memory";
224 0 : return HEIM_ERR_CONFIG_BADFORMAT;
225 : }
226 5680370 : ret = parse_list (f, lineno, &tmp->u.list, err_message);
227 : } else {
228 38935664 : tmp = heim_config_get_entry(parent, p1, heim_config_string);
229 38935664 : if (tmp == NULL) {
230 0 : *err_message = "out of memory";
231 0 : return HEIM_ERR_CONFIG_BADFORMAT;
232 : }
233 38935664 : p1 = p;
234 38935664 : p = p1 + strlen(p1);
235 38935664 : while(p > p1 && isspace((unsigned char)*(p-1)))
236 0 : --p;
237 38935664 : *p = '\0';
238 38935664 : tmp->u.string = strdup(p1);
239 : }
240 44616034 : *b = tmp;
241 44616034 : return ret;
242 : }
243 :
244 : #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
245 :
246 : #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
247 : #define HAVE_CFPROPERTYLISTCREATEWITHSTREAM 1
248 : #endif
249 :
250 : static char *
251 : cfstring2cstring(CFStringRef string)
252 : {
253 : CFIndex len;
254 : char *str;
255 :
256 : str = (char *) CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
257 : if (str)
258 : return strdup(str);
259 :
260 : len = CFStringGetLength(string);
261 : len = 1 + CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8);
262 : str = malloc(len);
263 : if (str == NULL)
264 : return NULL;
265 :
266 : if (!CFStringGetCString (string, str, len, kCFStringEncodingUTF8)) {
267 : free (str);
268 : return NULL;
269 : }
270 : return str;
271 : }
272 :
273 : static void
274 : convert_content(const void *key, const void *value, void *context)
275 : {
276 : heim_config_section *tmp, **parent = context;
277 : char *k;
278 :
279 : if (CFGetTypeID(key) != CFStringGetTypeID())
280 : return;
281 :
282 : k = cfstring2cstring(key);
283 : if (k == NULL)
284 : return;
285 :
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);
292 : } else {
293 : /* log */
294 : }
295 : free(k);
296 : }
297 :
298 : static heim_error_code
299 : parse_plist_config(heim_context context, const char *path, heim_config_section **parent)
300 : {
301 : CFReadStreamRef s;
302 : CFDictionaryRef d;
303 : CFURLRef url;
304 :
305 : url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)path, strlen(path), 0);
306 : if (url == NULL) {
307 : heim_clear_error_message(context);
308 : return ENOMEM;
309 : }
310 :
311 : s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
312 : CFRelease(url);
313 : if (s == NULL) {
314 : heim_clear_error_message(context);
315 : return ENOMEM;
316 : }
317 :
318 : if (!CFReadStreamOpen(s)) {
319 : CFRelease(s);
320 : heim_clear_error_message(context);
321 : return ENOENT;
322 : }
323 :
324 : #ifdef HAVE_CFPROPERTYLISTCREATEWITHSTREAM
325 : d = (CFDictionaryRef)CFPropertyListCreateWithStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
326 : #else
327 : d = (CFDictionaryRef)CFPropertyListCreateFromStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
328 : #endif
329 : CFRelease(s);
330 : if (d == NULL) {
331 : heim_clear_error_message(context);
332 : return ENOENT;
333 : }
334 :
335 : CFDictionaryApplyFunction(d, convert_content, parent);
336 : CFRelease(d);
337 :
338 : return 0;
339 : }
340 :
341 : #endif
342 :
343 : static int
344 0 : is_absolute_path(const char *path)
345 : {
346 : /*
347 : * An absolute path is one that refers to an explicit object
348 : * without ambiguity.
349 : */
350 : #ifdef WIN32
351 : size_t len = strlen(path);
352 :
353 : /* UNC path is by definition absolute */
354 : if (len > 2
355 : && ISPATHSEP(path[0])
356 : && ISPATHSEP(path[1]))
357 : return 1;
358 :
359 : /* A drive letter path might be absolute */
360 : if (len > 3
361 : && isalpha((unsigned char)path[0])
362 : && path[1] == ':'
363 : && ISPATHSEP(path[2]))
364 : return 1;
365 :
366 : /*
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.
370 : */
371 : #else
372 : /* UNIX is easy, first char '/' is absolute */
373 0 : if (ISPATHSEP(path[0]))
374 0 : return 1;
375 : #endif
376 0 : return 0;
377 : }
378 :
379 : /*
380 : * Parse the config file `fname', generating the structures into `res'
381 : * returning error messages in `err_message'
382 : */
383 :
384 : static heim_error_code
385 1237011 : heim_config_parse_debug(struct fileptr *f,
386 : heim_config_section **res,
387 : unsigned *lineno,
388 : const char **err_message)
389 : {
390 1237011 : heim_config_section *s = NULL;
391 1237011 : heim_config_binding *b = NULL;
392 31715 : char buf[2048];
393 31715 : heim_error_code ret;
394 :
395 1237011 : *lineno = 0;
396 1237011 : *err_message = "";
397 :
398 48179677 : while (config_fgets(buf, sizeof(buf), f) != NULL) {
399 1173635 : char *p;
400 :
401 46942666 : ++*lineno;
402 46942666 : buf[strcspn(buf, "\r\n")] = '\0';
403 46942666 : p = buf;
404 72738162 : while(isspace((unsigned char)*p))
405 25795496 : ++p;
406 46942666 : if (*p == '#' || *p == ';')
407 3707430 : continue;
408 43235236 : if (*p == '[') {
409 4915462 : ret = parse_section(p, &s, res, err_message);
410 4915462 : if (ret)
411 0 : return ret;
412 4915462 : b = NULL;
413 38319774 : } else if (*p == '}') {
414 0 : *err_message = "unmatched }";
415 0 : return 2048;
416 38319774 : } else if (strncmp(p, "include", sizeof("include") - 1) == 0 &&
417 0 : isspace((unsigned char)p[sizeof("include") - 1])) {
418 0 : p += sizeof("include");
419 0 : while (isspace((unsigned char)*p))
420 0 : p++;
421 0 : if (!is_absolute_path(p)) {
422 0 : heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
423 : "Configuration include path must be "
424 : "absolute");
425 0 : return HEIM_ERR_CONFIG_BADFORMAT;
426 : }
427 0 : ret = heim_config_parse_file_multi(f->context, p, res);
428 0 : if (ret)
429 0 : return ret;
430 38319774 : } else if (strncmp(p, "includedir", sizeof("includedir") - 1) == 0 &&
431 0 : isspace((unsigned char)p[sizeof("includedir") - 1])) {
432 0 : p += sizeof("includedir");
433 0 : while (isspace((unsigned char)*p))
434 0 : p++;
435 0 : if (!is_absolute_path(p)) {
436 0 : heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
437 : "Configuration includedir path must be "
438 : "absolute");
439 0 : return HEIM_ERR_CONFIG_BADFORMAT;
440 : }
441 0 : ret = heim_config_parse_dir_multi(f->context, p, res);
442 0 : if (ret)
443 0 : return ret;
444 38319774 : } else if(*p != '\0') {
445 21902664 : if (s == NULL) {
446 0 : *err_message = "binding before section";
447 0 : return 2048;
448 : }
449 21902664 : ret = parse_binding(f, lineno, p, &b, &s->u.list, err_message);
450 21902664 : if (ret)
451 0 : return ret;
452 : }
453 : }
454 1205296 : return 0;
455 : }
456 :
457 : static int
458 3001170 : is_plist_file(const char *fname)
459 : {
460 3001170 : size_t len = strlen(fname);
461 3001170 : char suffix[] = ".plist";
462 3001170 : if (len < sizeof(suffix))
463 0 : return 0;
464 3001170 : if (strcasecmp(&fname[len - (sizeof(suffix) - 1)], suffix) != 0)
465 3001170 : return 0;
466 0 : return 1;
467 : }
468 :
469 : /**
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.
474 : *
475 : * This interface can be used to parse several configuration directories
476 : * into one resulting heim_config_section by calling it repeatably.
477 : *
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().
482 : *
483 : * @ingroup heim_support
484 : */
485 :
486 : heim_error_code
487 0 : heim_config_parse_dir_multi(heim_context context,
488 : const char *dname,
489 : heim_config_section **res)
490 : {
491 0 : struct dirent *entry;
492 0 : heim_error_code ret;
493 0 : DIR *d;
494 :
495 0 : if ((d = opendir(dname)) == NULL)
496 0 : return errno;
497 :
498 0 : while ((entry = readdir(d)) != NULL) {
499 0 : char *p = entry->d_name;
500 0 : char *path;
501 0 : int is_valid = 1;
502 :
503 0 : while (*p) {
504 : /*
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
509 : * be aware.
510 : */
511 0 : if (!isalnum((unsigned char)*p) && *p != '_' && *p != '-' &&
512 0 : strcmp(p, ".conf") != 0) {
513 0 : is_valid = 0;
514 0 : break;
515 : }
516 0 : p++;
517 : }
518 0 : if (!is_valid)
519 0 : continue;
520 :
521 0 : if (asprintf(&path, "%s/%s", dname, entry->d_name) == -1 ||
522 0 : path == NULL) {
523 0 : (void) closedir(d);
524 0 : return heim_enomem(context);
525 : }
526 0 : ret = heim_config_parse_file_multi(context, path, res);
527 0 : free(path);
528 0 : if (ret == ENOMEM) {
529 0 : (void) closedir(d);
530 0 : return ENOMEM;
531 : }
532 : /* Ignore malformed config files so we don't lock out admins, etc... */
533 : }
534 0 : (void) closedir(d);
535 0 : return 0;
536 : }
537 :
538 : static int
539 0 : is_devnull(struct stat *st)
540 : {
541 : #ifdef WIN32
542 : return 0;
543 : #else
544 0 : struct stat devnullst;
545 :
546 0 : if (stat("/dev/null", &devnullst) == -1)
547 0 : return 0;
548 0 : return st->st_dev == devnullst.st_dev && st->st_ino == devnullst.st_ino;
549 : #endif
550 : }
551 :
552 : HEIMDAL_THREAD_LOCAL int config_include_depth = 0;
553 :
554 : /**
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.
558 : *
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().
563 : *
564 : * @ingroup heim_support
565 : */
566 :
567 : heim_error_code
568 3001170 : heim_config_parse_file_multi(heim_context context,
569 : const char *fname,
570 : heim_config_section **res)
571 : {
572 73332 : const char *str;
573 3001170 : char *newfname = NULL;
574 3001170 : unsigned lineno = 0;
575 3001170 : heim_error_code ret = 0;
576 73332 : struct fileptr f;
577 73332 : struct stat st;
578 :
579 3001170 : if (config_include_depth > 5) {
580 0 : heim_warnx(context, "Maximum config file include depth reached; "
581 : "not including %s", fname);
582 0 : return 0;
583 : }
584 3001170 : config_include_depth++;
585 :
586 : /**
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().
590 : */
591 3001170 : if (ISTILDE(fname[0]) && ISPATHSEP(fname[1])) {
592 792122 : if (!heim_context_get_homedir_access(context)) {
593 0 : heim_set_error_message(context, EPERM,
594 : "Access to home directory not allowed");
595 0 : ret = EPERM;
596 0 : goto out;
597 : }
598 792122 : if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 ||
599 792122 : newfname == NULL) {
600 0 : ret = heim_enomem(context);
601 0 : goto out;
602 : }
603 772600 : fname = newfname;
604 : }
605 :
606 3001170 : if (is_plist_file(fname)) {
607 : #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
608 : ret = parse_plist_config(context, fname, res);
609 : if (ret) {
610 : heim_set_error_message(context, ret,
611 : "Failed to parse plist %s", fname);
612 : goto out;
613 : }
614 : #else
615 0 : heim_set_error_message(context, ENOENT,
616 : "no support for plist configuration files");
617 0 : ret = ENOENT;
618 0 : goto out;
619 : #endif
620 : } else {
621 3001170 : char *exp_fname = NULL;
622 :
623 : /*
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.
628 : */
629 3001170 : ret = heim_expand_path_tokens(context, fname, 1, &exp_fname, NULL);
630 3001170 : if (ret)
631 1764159 : goto out;
632 3001170 : free(newfname);
633 3001170 : fname = newfname = exp_fname;
634 :
635 3001170 : f.context = context;
636 3001170 : f.f = fopen(fname, "r");
637 3001170 : f.s = NULL;
638 3001170 : if (f.f == NULL || fstat(fileno(f.f), &st) == -1) {
639 1764159 : if (f.f != NULL)
640 0 : (void) fclose(f.f);
641 1764159 : ret = errno;
642 1764159 : heim_set_error_message(context, ret, "open or stat %s: %s",
643 : fname, strerror(ret));
644 1764159 : goto out;
645 : }
646 :
647 1237011 : if (!S_ISREG(st.st_mode) && !is_devnull(&st)) {
648 0 : (void) fclose(f.f);
649 0 : heim_set_error_message(context, EISDIR, "not a regular file %s: %s",
650 : fname, strerror(EISDIR));
651 0 : ret = EISDIR;
652 0 : goto out;
653 : }
654 :
655 1237011 : ret = heim_config_parse_debug(&f, res, &lineno, &str);
656 1237011 : fclose(f.f);
657 1237011 : if (ret) {
658 0 : if (ret != HEIM_ERR_CONFIG_BADFORMAT)
659 0 : ret = HEIM_ERR_CONFIG_BADFORMAT;
660 0 : heim_set_error_message(context, ret, "%s:%u: %s",
661 : fname, lineno, str);
662 0 : goto out;
663 : }
664 : }
665 :
666 3001170 : out:
667 3001170 : config_include_depth--;
668 3001170 : if (ret == HEIM_ERR_CONFIG_BADFORMAT || (ret && config_include_depth > 0)) {
669 0 : heim_warn(context, ret, "Ignoring");
670 0 : if (config_include_depth > 0)
671 0 : ret = 0;
672 : }
673 3001170 : free(newfname);
674 3001170 : return ret;
675 : }
676 :
677 : heim_error_code
678 0 : heim_config_parse_file(heim_context context,
679 : const char *fname,
680 : heim_config_section **res)
681 : {
682 0 : *res = NULL;
683 0 : return heim_config_parse_file_multi(context, fname, res);
684 : }
685 :
686 : static void
687 13178930 : free_binding(heim_context context, heim_config_binding *b)
688 : {
689 309512 : heim_config_binding *next_b;
690 :
691 61445419 : while (b) {
692 48266489 : free (b->name);
693 48266489 : assert(b->type == heim_config_string || b->type == heim_config_list);
694 48266489 : if (b->type == heim_config_string)
695 37939699 : free (b->u.string);
696 : else
697 10326790 : free_binding (context, b->u.list);
698 48266489 : next_b = b->next;
699 48266489 : free (b);
700 48266489 : b = next_b;
701 : }
702 13178930 : }
703 :
704 : /**
705 : * Free configuration file section, the result of
706 : * heim_config_parse_file() and heim_config_parse_file_multi().
707 : *
708 : * @param context A Kerberos 5 context
709 : * @param s the configuration section to free
710 : *
711 : * @return returns 0 on successes, otherwise an error code, see
712 : * heim_get_error_message()
713 : *
714 : * @ingroup heim_support
715 : */
716 :
717 : heim_error_code
718 2852140 : heim_config_file_free(heim_context context, heim_config_section *s)
719 : {
720 2852140 : free_binding (context, s);
721 2852140 : return 0;
722 : }
723 :
724 : #ifndef HEIMDAL_SMALLER
725 :
726 : heim_error_code
727 0 : heim_config_copy(heim_context context,
728 : heim_config_section *c,
729 : heim_config_section **head)
730 : {
731 0 : heim_config_binding *d, *previous = NULL;
732 :
733 0 : *head = NULL;
734 :
735 0 : while (c) {
736 0 : d = calloc(1, sizeof(*d));
737 :
738 0 : if (*head == NULL)
739 0 : *head = d;
740 :
741 0 : d->name = strdup(c->name);
742 0 : d->type = c->type;
743 0 : assert(d->type == heim_config_string || d->type == heim_config_list);
744 0 : if (d->type == heim_config_string)
745 0 : d->u.string = strdup(c->u.string);
746 : else
747 0 : heim_config_copy (context, c->u.list, &d->u.list);
748 0 : if (previous)
749 0 : previous->next = d;
750 :
751 0 : previous = d;
752 0 : c = c->next;
753 : }
754 0 : return 0;
755 : }
756 :
757 : #endif /* HEIMDAL_SMALLER */
758 :
759 : const void *
760 0 : heim_config_get_next(heim_context context,
761 : const heim_config_section *c,
762 : const heim_config_binding **pointer,
763 : int type,
764 : ...)
765 : {
766 0 : const char *ret;
767 0 : va_list args;
768 :
769 0 : va_start(args, type);
770 0 : ret = heim_config_vget_next(context, c, pointer, type, args);
771 0 : va_end(args);
772 0 : return ret;
773 : }
774 :
775 : static const void *
776 79548590 : vget_next(heim_context context,
777 : const heim_config_binding *b,
778 : const heim_config_binding **pointer,
779 : int type,
780 : const char *name,
781 : va_list args)
782 : {
783 80578381 : const char *p = va_arg(args, const char *);
784 :
785 394814951 : while (b != NULL) {
786 356612774 : if (strcmp(b->name, name) == 0) {
787 42411826 : if (b->type == (unsigned)type && p == NULL) {
788 2781029 : *pointer = b;
789 2781029 : return b->u.generic;
790 39630797 : } else if (b->type == heim_config_list && p != NULL) {
791 39595175 : return vget_next(context, b->u.list, pointer, type, p, args);
792 : }
793 : }
794 314236570 : b = b->next;
795 : }
796 37208485 : return NULL;
797 : }
798 :
799 : const void *
800 46314756 : heim_config_vget_next(heim_context context,
801 : const heim_config_section *c,
802 : const heim_config_binding **pointer,
803 : int type,
804 : va_list args)
805 : {
806 1139172 : const heim_config_binding *b;
807 1139172 : const char *p;
808 :
809 46314756 : if (c == NULL)
810 5027780 : return NULL;
811 :
812 41217213 : if (*pointer == NULL) {
813 : /* first time here, walk down the tree looking for the right
814 : section */
815 40983206 : p = va_arg(args, const char *);
816 40983206 : if (p == NULL)
817 0 : return NULL;
818 40983206 : return vget_next(context, c, pointer, type, p, args);
819 : }
820 :
821 : /* we were called again, so just look for more entries with the
822 : same name and type */
823 924017 : for (b = (*pointer)->next; b != NULL; b = b->next) {
824 690836 : if(strcmp(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) {
825 826 : *pointer = b;
826 826 : return b->u.generic;
827 : }
828 : }
829 228725 : return NULL;
830 : }
831 :
832 : const void *
833 0 : heim_config_get(heim_context context,
834 : const heim_config_section *c,
835 : int type,
836 : ...)
837 : {
838 0 : const void *ret;
839 0 : va_list args;
840 :
841 0 : va_start(args, type);
842 0 : ret = heim_config_vget(context, c, type, args);
843 0 : va_end(args);
844 0 : return ret;
845 : }
846 :
847 :
848 : const void *
849 34886296 : heim_config_vget(heim_context context,
850 : const heim_config_section *c,
851 : int type,
852 : va_list args)
853 : {
854 34886296 : const heim_config_binding *foo = NULL;
855 :
856 34886296 : return heim_config_vget_next(context, c, &foo, type, args);
857 : }
858 :
859 : /**
860 : * Get a list of configuration binding list for more processing
861 : *
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.
865 : *
866 : * @return NULL if configuration list is not found, a list otherwise
867 : *
868 : * @ingroup heim_support
869 : */
870 :
871 : const heim_config_binding *
872 0 : heim_config_get_list(heim_context context,
873 : const heim_config_section *c,
874 : ...)
875 : {
876 0 : const heim_config_binding *ret;
877 0 : va_list args;
878 :
879 0 : va_start(args, c);
880 0 : ret = heim_config_vget_list(context, c, args);
881 0 : va_end(args);
882 0 : return ret;
883 : }
884 :
885 : /**
886 : * Get a list of configuration binding list for more processing
887 : *
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
891 : *
892 : * @return NULL if configuration list is not found, a list otherwise
893 : *
894 : * @ingroup heim_support
895 : */
896 :
897 : const heim_config_binding *
898 0 : heim_config_vget_list(heim_context context,
899 : const heim_config_section *c,
900 : va_list args)
901 : {
902 0 : return heim_config_vget(context, c, heim_config_list, args);
903 : }
904 :
905 : /**
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
909 : * the string.
910 : *
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.
914 : *
915 : * @return NULL if configuration string not found, a string otherwise
916 : *
917 : * @ingroup heim_support
918 : */
919 :
920 : const char *
921 792002 : heim_config_get_string(heim_context context,
922 : const heim_config_section *c,
923 : ...)
924 : {
925 19510 : const char *ret;
926 19510 : va_list args;
927 :
928 792002 : va_start(args, c);
929 792002 : ret = heim_config_vget_string(context, c, args);
930 792002 : va_end(args);
931 792002 : return ret;
932 : }
933 :
934 : /**
935 : * Like heim_config_get_string(), but uses a va_list instead of ...
936 : *
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
940 : *
941 : * @return NULL if configuration string not found, a string otherwise
942 : *
943 : * @ingroup heim_support
944 : */
945 :
946 : const char *
947 34886296 : heim_config_vget_string(heim_context context,
948 : const heim_config_section *c,
949 : va_list args)
950 : {
951 34886296 : return heim_config_vget(context, c, heim_config_string, args);
952 : }
953 :
954 : /**
955 : * Like heim_config_vget_string(), but instead of returning NULL,
956 : * instead return a default value.
957 : *
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
963 : *
964 : * @return a configuration string
965 : *
966 : * @ingroup heim_support
967 : */
968 :
969 : const char *
970 6803506 : heim_config_vget_string_default(heim_context context,
971 : const heim_config_section *c,
972 : const char *def_value,
973 : va_list args)
974 : {
975 166848 : const char *ret;
976 :
977 6803506 : ret = heim_config_vget_string(context, c, args);
978 6803506 : if (ret == NULL)
979 6791339 : ret = def_value;
980 6803506 : return ret;
981 : }
982 :
983 : /**
984 : * Like heim_config_get_string(), but instead of returning NULL,
985 : * instead return a default value.
986 : *
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.
992 : *
993 : * @return a configuration string
994 : *
995 : * @ingroup heim_support
996 : */
997 :
998 : const char *
999 0 : heim_config_get_string_default(heim_context context,
1000 : const heim_config_section *c,
1001 : const char *def_value,
1002 : ...)
1003 : {
1004 0 : const char *ret;
1005 0 : va_list args;
1006 :
1007 0 : va_start(args, def_value);
1008 0 : ret = heim_config_vget_string_default (context, c, def_value, args);
1009 0 : va_end(args);
1010 0 : return ret;
1011 : }
1012 :
1013 : static char *
1014 745220 : next_component_string(char * begin, const char * delims, char **state)
1015 : {
1016 8912 : char * end;
1017 :
1018 745220 : if (begin == NULL)
1019 511213 : begin = *state;
1020 :
1021 745220 : if (*begin == '\0')
1022 229551 : return NULL;
1023 :
1024 506757 : end = begin;
1025 511213 : while (*end == '"') {
1026 0 : char * t = strchr(end + 1, '"');
1027 :
1028 0 : if (t)
1029 0 : end = ++t;
1030 : else
1031 0 : end += strlen(end);
1032 : }
1033 :
1034 511213 : if (*end != '\0') {
1035 4456 : size_t pos;
1036 :
1037 511213 : pos = strcspn(end, delims);
1038 511213 : end = end + pos;
1039 : }
1040 :
1041 511213 : if (*end != '\0') {
1042 277206 : *end = '\0';
1043 277206 : *state = end + 1;
1044 277206 : if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
1045 0 : begin++; *(end - 1) = '\0';
1046 : }
1047 277206 : return begin;
1048 : }
1049 :
1050 234007 : *state = end;
1051 234007 : if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
1052 0 : begin++; *(end - 1) = '\0';
1053 : }
1054 229551 : return begin;
1055 : }
1056 :
1057 : /**
1058 : * Get a list of configuration strings, free the result with
1059 : * heim_config_free_strings().
1060 : *
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
1064 : *
1065 : * @return TRUE or FALSE
1066 : *
1067 : * @ingroup heim_support
1068 : */
1069 :
1070 : char **
1071 11194453 : heim_config_vget_strings(heim_context context,
1072 : const heim_config_section *c,
1073 : va_list args)
1074 : {
1075 11194453 : char **strings = NULL;
1076 11194453 : size_t nstr = 0;
1077 11194453 : const heim_config_binding *b = NULL;
1078 275273 : const char *p;
1079 :
1080 11428460 : while((p = heim_config_vget_next(context, c, &b,
1081 : heim_config_string, args))) {
1082 234007 : char *tmp = strdup(p);
1083 234007 : char *pos = NULL;
1084 4456 : char *s;
1085 234007 : if(tmp == NULL)
1086 0 : goto cleanup;
1087 234007 : s = next_component_string(tmp, " \t", &pos);
1088 745220 : while(s){
1089 511213 : char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
1090 511213 : if(tmp2 == NULL) {
1091 0 : free(tmp);
1092 0 : goto cleanup;
1093 : }
1094 511213 : strings = tmp2;
1095 511213 : strings[nstr] = strdup(s);
1096 511213 : nstr++;
1097 511213 : if(strings[nstr-1] == NULL) {
1098 0 : free(tmp);
1099 0 : goto cleanup;
1100 : }
1101 511213 : s = next_component_string(NULL, " \t", &pos);
1102 : }
1103 234007 : free(tmp);
1104 : }
1105 11194453 : if(nstr){
1106 233181 : char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
1107 233181 : if(tmp == NULL)
1108 0 : goto cleanup;
1109 233181 : strings = tmp;
1110 233181 : strings[nstr] = NULL;
1111 : }
1112 10919180 : return strings;
1113 0 : cleanup:
1114 0 : while(nstr--)
1115 0 : free(strings[nstr]);
1116 0 : free(strings);
1117 0 : return NULL;
1118 :
1119 : }
1120 :
1121 : /**
1122 : * Get a list of configuration strings, free the result with
1123 : * heim_config_free_strings().
1124 : *
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.
1128 : *
1129 : * @return TRUE or FALSE
1130 : *
1131 : * @ingroup heim_support
1132 : */
1133 :
1134 : char **
1135 0 : heim_config_get_strings(heim_context context,
1136 : const heim_config_section *c,
1137 : ...)
1138 : {
1139 0 : va_list ap;
1140 0 : char **ret;
1141 0 : va_start(ap, c);
1142 0 : ret = heim_config_vget_strings(context, c, ap);
1143 0 : va_end(ap);
1144 0 : return ret;
1145 : }
1146 :
1147 : /**
1148 : * Free the resulting strings from heim_config-get_strings() and
1149 : * heim_config_vget_strings().
1150 : *
1151 : * @param strings strings to free
1152 : *
1153 : * @ingroup heim_support
1154 : */
1155 :
1156 : void
1157 2905210 : heim_config_free_strings(char **strings)
1158 : {
1159 2905210 : char **s = strings;
1160 :
1161 3396130 : while (s && *s) {
1162 490920 : free(*s);
1163 490920 : s++;
1164 : }
1165 2905210 : free(strings);
1166 2905210 : }
1167 :
1168 : /**
1169 : * Like heim_config_get_bool_default() but with a va_list list of
1170 : * configuration selection.
1171 : *
1172 : * Configuration value to a boolean value, where yes/true and any
1173 : * non-zero number means TRUE and other value is FALSE.
1174 : *
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
1180 : *
1181 : * @return TRUE or FALSE
1182 : *
1183 : * @ingroup heim_support
1184 : */
1185 :
1186 : int
1187 14354325 : heim_config_vget_bool_default(heim_context context,
1188 : const heim_config_section *c,
1189 : int def_value,
1190 : va_list args)
1191 : {
1192 358291 : const char *str;
1193 14354325 : str = heim_config_vget_string(context, c, args);
1194 14354325 : if (str == NULL)
1195 11526743 : return def_value;
1196 4981864 : return !!(strcasecmp(str, "yes") == 0 ||
1197 2511403 : strcasecmp(str, "true") == 0 ||
1198 1274652 : atoi(str));
1199 : }
1200 :
1201 : /**
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.
1205 : *
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
1209 : *
1210 : * @return TRUE or FALSE
1211 : *
1212 : * @ingroup heim_support
1213 : */
1214 :
1215 : int
1216 0 : heim_config_vget_bool(heim_context context,
1217 : const heim_config_section *c,
1218 : va_list args)
1219 : {
1220 0 : return heim_config_vget_bool_default(context, c, 0, args);
1221 : }
1222 :
1223 : /**
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.
1227 : *
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.
1233 : *
1234 : * @return TRUE or FALSE
1235 : *
1236 : * @ingroup heim_support
1237 : */
1238 :
1239 : int
1240 0 : heim_config_get_bool_default(heim_context context,
1241 : const heim_config_section *c,
1242 : int def_value,
1243 : ...)
1244 : {
1245 0 : va_list ap;
1246 0 : int ret;
1247 :
1248 0 : va_start(ap, def_value);
1249 0 : ret = heim_config_vget_bool_default(context, c, def_value, ap);
1250 0 : va_end(ap);
1251 0 : return ret;
1252 : }
1253 :
1254 : /**
1255 : * Like heim_config_get_bool() but with a va_list list of
1256 : * configuration selection.
1257 : *
1258 : * Configuration value to a boolean value, where yes/true and any
1259 : * non-zero number means TRUE and other value is FALSE.
1260 : *
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.
1264 : *
1265 : * @return TRUE or FALSE
1266 : *
1267 : * @ingroup heim_support
1268 : */
1269 :
1270 : int
1271 0 : heim_config_get_bool(heim_context context,
1272 : const heim_config_section *c,
1273 : ...)
1274 : {
1275 0 : va_list ap;
1276 0 : int ret;
1277 0 : va_start(ap, c);
1278 0 : ret = heim_config_vget_bool (context, c, ap);
1279 0 : va_end(ap);
1280 0 : return ret;
1281 : }
1282 :
1283 : /**
1284 : * Get the time from the configuration file using a relative time.
1285 : *
1286 : * Like heim_config_get_time_default() but with a va_list list of
1287 : * configuration selection.
1288 : *
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
1294 : *
1295 : * @return parsed the time (or def_value on parse error)
1296 : *
1297 : * @ingroup heim_support
1298 : */
1299 :
1300 : time_t
1301 4857487 : heim_config_vget_time_default(heim_context context,
1302 : const heim_config_section *c,
1303 : int def_value,
1304 : va_list args)
1305 : {
1306 118718 : const char *str;
1307 4857487 : time_t t = -1;
1308 :
1309 4857487 : if ((str = heim_config_vget_string(context, c, args)))
1310 0 : t = parse_time(str, "s");
1311 4857487 : return t != -1 ? t : def_value;
1312 : }
1313 :
1314 : /**
1315 : * Get the time from the configuration file using a relative time, for example: 1h30s
1316 : *
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
1320 : *
1321 : * @return parsed the time or -1 on error
1322 : *
1323 : * @ingroup heim_support
1324 : */
1325 :
1326 : time_t
1327 27558 : heim_config_vget_time(heim_context context,
1328 : const heim_config_section *c,
1329 : va_list args)
1330 : {
1331 27558 : return heim_config_vget_time_default(context, c, -1, args);
1332 : }
1333 :
1334 : /**
1335 : * Get the time from the configuration file using a relative time, for example: 1h30s
1336 : *
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.
1342 : *
1343 : * @return parsed the time (or def_value on parse error)
1344 : *
1345 : * @ingroup heim_support
1346 : */
1347 :
1348 : time_t
1349 792002 : heim_config_get_time_default(heim_context context,
1350 : const heim_config_section *c,
1351 : int def_value,
1352 : ...)
1353 : {
1354 19510 : va_list ap;
1355 19510 : time_t ret;
1356 :
1357 792002 : va_start(ap, def_value);
1358 792002 : ret = heim_config_vget_time_default(context, c, def_value, ap);
1359 792002 : va_end(ap);
1360 792002 : return ret;
1361 : }
1362 :
1363 : /**
1364 : * Get the time from the configuration file using a relative time, for example: 1h30s
1365 : *
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.
1369 : *
1370 : * @return parsed the time or -1 on error
1371 : *
1372 : * @ingroup heim_support
1373 : */
1374 :
1375 : time_t
1376 0 : heim_config_get_time(heim_context context,
1377 : const heim_config_section *c,
1378 : ...)
1379 : {
1380 0 : va_list ap;
1381 0 : int ret;
1382 0 : va_start(ap, c);
1383 0 : ret = heim_config_vget_time(context, c, ap);
1384 0 : va_end(ap);
1385 0 : return ret;
1386 : }
1387 :
1388 :
1389 : int
1390 5383731 : heim_config_vget_int_default(heim_context context,
1391 : const heim_config_section *c,
1392 : int def_value,
1393 : va_list args)
1394 : {
1395 130688 : const char *str;
1396 5383731 : str = heim_config_vget_string (context, c, args);
1397 5383731 : if(str == NULL)
1398 5253043 : return def_value;
1399 : else {
1400 0 : char *endptr;
1401 0 : long l;
1402 0 : l = strtol(str, &endptr, 0);
1403 0 : if (endptr == str)
1404 0 : return def_value;
1405 : else
1406 0 : return l;
1407 : }
1408 : }
1409 :
1410 : int
1411 0 : heim_config_vget_int(heim_context context,
1412 : const heim_config_section *c,
1413 : va_list args)
1414 : {
1415 0 : return heim_config_vget_int_default(context, c, -1, args);
1416 : }
1417 :
1418 : int
1419 0 : heim_config_get_int_default(heim_context context,
1420 : const heim_config_section *c,
1421 : int def_value,
1422 : ...)
1423 : {
1424 0 : va_list ap;
1425 0 : int ret;
1426 :
1427 0 : va_start(ap, def_value);
1428 0 : ret = heim_config_vget_int_default(context, c, def_value, ap);
1429 0 : va_end(ap);
1430 0 : return ret;
1431 : }
1432 :
1433 : int
1434 0 : heim_config_get_int(heim_context context,
1435 : const heim_config_section *c,
1436 : ...)
1437 : {
1438 0 : va_list ap;
1439 0 : int ret;
1440 0 : va_start(ap, c);
1441 0 : ret = heim_config_vget_int (context, c, ap);
1442 0 : va_end(ap);
1443 0 : return ret;
1444 : }
1445 :
1446 : #ifndef HEIMDAL_SMALLER
1447 : heim_error_code
1448 0 : heim_config_parse_string_multi(heim_context context,
1449 : const char *string,
1450 : heim_config_section **res)
1451 : {
1452 0 : const char *str;
1453 0 : unsigned lineno = 0;
1454 0 : heim_error_code ret;
1455 0 : struct fileptr f;
1456 :
1457 0 : f.context = context;
1458 0 : f.f = NULL;
1459 0 : f.s = string;
1460 :
1461 0 : ret = heim_config_parse_debug(&f, res, &lineno, &str);
1462 0 : if (ret) {
1463 0 : if (ret != HEIM_ERR_CONFIG_BADFORMAT) {
1464 0 : ret = HEIM_ERR_CONFIG_BADFORMAT;
1465 0 : heim_set_error_message(context, ret, "%s:%u: %s",
1466 : "<constant>", lineno, str);
1467 : }
1468 0 : return ret;
1469 : }
1470 0 : return 0;
1471 : }
1472 : #endif
|