2 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
35 __RCSID("$Heimdal: config_file.c 19213 2006-12-04 23:36:36Z lha $"
40 /* Gaah! I want a portable funopen */
47 config_fgets(char *str
, size_t len
, struct fileptr
*ptr
)
49 /* XXX this is not correct, in that they don't do the same if the
50 line is longer than len */
52 return fgets(str
, len
, ptr
->f
);
54 /* this is almost strsep_copy */
59 p
= ptr
->s
+ strcspn(ptr
->s
, "\n");
62 l
= min(len
, p
- ptr
->s
);
64 memcpy(str
, ptr
->s
, l
);
72 static krb5_error_code
parse_section(char *p
, krb5_config_section
**s
,
73 krb5_config_section
**res
,
74 const char **error_message
);
75 static krb5_error_code
parse_binding(struct fileptr
*f
, unsigned *lineno
, char *p
,
76 krb5_config_binding
**b
,
77 krb5_config_binding
**parent
,
78 const char **error_message
);
79 static krb5_error_code
parse_list(struct fileptr
*f
, unsigned *lineno
,
80 krb5_config_binding
**parent
,
81 const char **error_message
);
83 static krb5_config_section
*
84 get_entry(krb5_config_section
**parent
, const char *name
, int type
)
86 krb5_config_section
**q
;
88 for(q
= parent
; *q
!= NULL
; q
= &(*q
)->next
)
89 if(type
== krb5_config_list
&&
91 strcmp(name
, (*q
)->name
) == 0)
93 *q
= calloc(1, sizeof(**q
));
96 (*q
)->name
= strdup(name
);
98 if((*q
)->name
== NULL
) {
116 * starting at the line in `p', storing the resulting structure in
117 * `s' and hooking it into `parent'.
118 * Store the error message in `error_message'.
121 static krb5_error_code
122 parse_section(char *p
, krb5_config_section
**s
, krb5_config_section
**parent
,
123 const char **error_message
)
126 krb5_config_section
*tmp
;
128 p1
= strchr (p
+ 1, ']');
130 *error_message
= "missing ]";
131 return KRB5_CONFIG_BADFORMAT
;
134 tmp
= get_entry(parent
, p
+ 1, krb5_config_list
);
136 *error_message
= "out of memory";
137 return KRB5_CONFIG_BADFORMAT
;
144 * Parse a brace-enclosed list from `f', hooking in the structure at
146 * Store the error message in `error_message'.
149 static krb5_error_code
150 parse_list(struct fileptr
*f
, unsigned *lineno
, krb5_config_binding
**parent
,
151 const char **error_message
)
155 krb5_config_binding
*b
= NULL
;
156 unsigned beg_lineno
= *lineno
;
158 while(config_fgets(buf
, sizeof(buf
), f
) != NULL
) {
162 buf
[strcspn(buf
, "\r\n")] = '\0';
164 while(isspace((unsigned char)*p
))
166 if (*p
== '#' || *p
== ';' || *p
== '\0')
168 while(isspace((unsigned char)*p
))
174 ret
= parse_binding (f
, lineno
, p
, &b
, parent
, error_message
);
178 *lineno
= beg_lineno
;
179 *error_message
= "unclosed {";
180 return KRB5_CONFIG_BADFORMAT
;
187 static krb5_error_code
188 parse_binding(struct fileptr
*f
, unsigned *lineno
, char *p
,
189 krb5_config_binding
**b
, krb5_config_binding
**parent
,
190 const char **error_message
)
192 krb5_config_binding
*tmp
;
194 krb5_error_code ret
= 0;
197 while (*p
&& *p
!= '=' && !isspace((unsigned char)*p
))
200 *error_message
= "missing =";
201 return KRB5_CONFIG_BADFORMAT
;
204 while (isspace((unsigned char)*p
))
207 *error_message
= "missing =";
208 return KRB5_CONFIG_BADFORMAT
;
211 while(isspace((unsigned char)*p
))
215 tmp
= get_entry(parent
, p1
, krb5_config_list
);
217 *error_message
= "out of memory";
218 return KRB5_CONFIG_BADFORMAT
;
220 ret
= parse_list (f
, lineno
, &tmp
->u
.list
, error_message
);
222 tmp
= get_entry(parent
, p1
, krb5_config_string
);
224 *error_message
= "out of memory";
225 return KRB5_CONFIG_BADFORMAT
;
229 while(p
> p1
&& isspace((unsigned char)*(p
-1)))
232 tmp
->u
.string
= strdup(p1
);
239 * Parse the config file `fname', generating the structures into `res'
240 * returning error messages in `error_message'
243 static krb5_error_code
244 krb5_config_parse_debug (struct fileptr
*f
,
245 krb5_config_section
**res
,
247 const char **error_message
)
249 krb5_config_section
*s
= NULL
;
250 krb5_config_binding
*b
= NULL
;
254 while (config_fgets(buf
, sizeof(buf
), f
) != NULL
) {
258 buf
[strcspn(buf
, "\r\n")] = '\0';
260 while(isspace((unsigned char)*p
))
262 if (*p
== '#' || *p
== ';')
265 ret
= parse_section(p
, &s
, res
, error_message
);
269 } else if (*p
== '}') {
270 *error_message
= "unmatched }";
271 return EINVAL
; /* XXX */
272 } else if(*p
!= '\0') {
274 *error_message
= "binding before section";
277 ret
= parse_binding(f
, lineno
, p
, &b
, &s
->u
.list
, error_message
);
285 krb5_error_code KRB5_LIB_FUNCTION
286 krb5_config_parse_string_multi(krb5_context context
,
288 krb5_config_section
**res
)
297 ret
= krb5_config_parse_debug (&f
, res
, &lineno
, &str
);
299 krb5_set_error_string (context
, "%s:%u: %s", "<constant>", lineno
, str
);
305 krb5_error_code KRB5_LIB_FUNCTION
306 krb5_config_parse_file_multi (krb5_context context
,
308 krb5_config_section
**res
)
314 f
.f
= fopen(fname
, "r");
318 krb5_set_error_string (context
, "open %s: %s", fname
, strerror(ret
));
322 ret
= krb5_config_parse_debug (&f
, res
, &lineno
, &str
);
325 krb5_set_error_string (context
, "%s:%u: %s", fname
, lineno
, str
);
331 krb5_error_code KRB5_LIB_FUNCTION
332 krb5_config_parse_file (krb5_context context
,
334 krb5_config_section
**res
)
337 return krb5_config_parse_file_multi(context
, fname
, res
);
340 #endif /* !HAVE_NETINFO */
343 free_binding (krb5_context context
, krb5_config_binding
*b
)
345 krb5_config_binding
*next_b
;
349 if (b
->type
== krb5_config_string
)
351 else if (b
->type
== krb5_config_list
)
352 free_binding (context
, b
->u
.list
);
354 krb5_abortx(context
, "unknown binding type (%d) in free_binding",
362 krb5_error_code KRB5_LIB_FUNCTION
363 krb5_config_file_free (krb5_context context
, krb5_config_section
*s
)
365 free_binding (context
, s
);
370 krb5_config_get_next (krb5_context context
,
371 const krb5_config_section
*c
,
372 const krb5_config_binding
**pointer
,
379 va_start(args
, type
);
380 ret
= krb5_config_vget_next (context
, c
, pointer
, type
, args
);
386 vget_next(krb5_context context
,
387 const krb5_config_binding
*b
,
388 const krb5_config_binding
**pointer
,
393 const char *p
= va_arg(args
, const char *);
395 if(strcmp(b
->name
, name
) == 0) {
396 if(b
->type
== type
&& p
== NULL
) {
399 } else if(b
->type
== krb5_config_list
&& p
!= NULL
) {
400 return vget_next(context
, b
->u
.list
, pointer
, type
, p
, args
);
409 krb5_config_vget_next (krb5_context context
,
410 const krb5_config_section
*c
,
411 const krb5_config_binding
**pointer
,
415 const krb5_config_binding
*b
;
424 if (*pointer
== NULL
) {
425 /* first time here, walk down the tree looking for the right
427 p
= va_arg(args
, const char *);
430 return vget_next(context
, c
, pointer
, type
, p
, args
);
433 /* we were called again, so just look for more entries with the
434 same name and type */
435 for (b
= (*pointer
)->next
; b
!= NULL
; b
= b
->next
) {
436 if(strcmp(b
->name
, (*pointer
)->name
) == 0 && b
->type
== type
) {
445 krb5_config_get (krb5_context context
,
446 const krb5_config_section
*c
,
453 va_start(args
, type
);
454 ret
= krb5_config_vget (context
, c
, type
, args
);
460 krb5_config_vget (krb5_context context
,
461 const krb5_config_section
*c
,
465 const krb5_config_binding
*foo
= NULL
;
467 return krb5_config_vget_next (context
, c
, &foo
, type
, args
);
470 const krb5_config_binding
*
471 krb5_config_get_list (krb5_context context
,
472 const krb5_config_section
*c
,
475 const krb5_config_binding
*ret
;
479 ret
= krb5_config_vget_list (context
, c
, args
);
484 const krb5_config_binding
*
485 krb5_config_vget_list (krb5_context context
,
486 const krb5_config_section
*c
,
489 return krb5_config_vget (context
, c
, krb5_config_list
, args
);
492 const char* KRB5_LIB_FUNCTION
493 krb5_config_get_string (krb5_context context
,
494 const krb5_config_section
*c
,
501 ret
= krb5_config_vget_string (context
, c
, args
);
506 const char* KRB5_LIB_FUNCTION
507 krb5_config_vget_string (krb5_context context
,
508 const krb5_config_section
*c
,
511 return krb5_config_vget (context
, c
, krb5_config_string
, args
);
514 const char* KRB5_LIB_FUNCTION
515 krb5_config_vget_string_default (krb5_context context
,
516 const krb5_config_section
*c
,
517 const char *def_value
,
522 ret
= krb5_config_vget_string (context
, c
, args
);
528 const char* KRB5_LIB_FUNCTION
529 krb5_config_get_string_default (krb5_context context
,
530 const krb5_config_section
*c
,
531 const char *def_value
,
537 va_start(args
, def_value
);
538 ret
= krb5_config_vget_string_default (context
, c
, def_value
, args
);
543 char ** KRB5_LIB_FUNCTION
544 krb5_config_vget_strings(krb5_context context
,
545 const krb5_config_section
*c
,
548 char **strings
= NULL
;
550 const krb5_config_binding
*b
= NULL
;
553 while((p
= krb5_config_vget_next(context
, c
, &b
,
554 krb5_config_string
, args
))) {
555 char *tmp
= strdup(p
);
560 s
= strtok_r(tmp
, " \t", &pos
);
562 char **tmp2
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
566 strings
[nstr
] = strdup(s
);
568 if(strings
[nstr
-1] == NULL
)
570 s
= strtok_r(NULL
, " \t", &pos
);
575 char **tmp
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
579 strings
[nstr
] = NULL
;
591 krb5_config_get_strings(krb5_context context
,
592 const krb5_config_section
*c
,
598 ret
= krb5_config_vget_strings(context
, c
, ap
);
603 void KRB5_LIB_FUNCTION
604 krb5_config_free_strings(char **strings
)
614 krb5_boolean KRB5_LIB_FUNCTION
615 krb5_config_vget_bool_default (krb5_context context
,
616 const krb5_config_section
*c
,
617 krb5_boolean def_value
,
621 str
= krb5_config_vget_string (context
, c
, args
);
624 if(strcasecmp(str
, "yes") == 0 ||
625 strcasecmp(str
, "true") == 0 ||
626 atoi(str
)) return TRUE
;
630 krb5_boolean KRB5_LIB_FUNCTION
631 krb5_config_vget_bool (krb5_context context
,
632 const krb5_config_section
*c
,
635 return krb5_config_vget_bool_default (context
, c
, FALSE
, args
);
638 krb5_boolean KRB5_LIB_FUNCTION
639 krb5_config_get_bool_default (krb5_context context
,
640 const krb5_config_section
*c
,
641 krb5_boolean def_value
,
646 va_start(ap
, def_value
);
647 ret
= krb5_config_vget_bool_default(context
, c
, def_value
, ap
);
652 krb5_boolean KRB5_LIB_FUNCTION
653 krb5_config_get_bool (krb5_context context
,
654 const krb5_config_section
*c
,
660 ret
= krb5_config_vget_bool (context
, c
, ap
);
665 int KRB5_LIB_FUNCTION
666 krb5_config_vget_time_default (krb5_context context
,
667 const krb5_config_section
*c
,
674 str
= krb5_config_vget_string (context
, c
, args
);
677 if (krb5_string_to_deltat(str
, &t
))
682 int KRB5_LIB_FUNCTION
683 krb5_config_vget_time (krb5_context context
,
684 const krb5_config_section
*c
,
687 return krb5_config_vget_time_default (context
, c
, -1, args
);
690 int KRB5_LIB_FUNCTION
691 krb5_config_get_time_default (krb5_context context
,
692 const krb5_config_section
*c
,
698 va_start(ap
, def_value
);
699 ret
= krb5_config_vget_time_default(context
, c
, def_value
, ap
);
704 int KRB5_LIB_FUNCTION
705 krb5_config_get_time (krb5_context context
,
706 const krb5_config_section
*c
,
712 ret
= krb5_config_vget_time (context
, c
, ap
);
718 int KRB5_LIB_FUNCTION
719 krb5_config_vget_int_default (krb5_context context
,
720 const krb5_config_section
*c
,
725 str
= krb5_config_vget_string (context
, c
, args
);
731 l
= strtol(str
, &endptr
, 0);
739 int KRB5_LIB_FUNCTION
740 krb5_config_vget_int (krb5_context context
,
741 const krb5_config_section
*c
,
744 return krb5_config_vget_int_default (context
, c
, -1, args
);
747 int KRB5_LIB_FUNCTION
748 krb5_config_get_int_default (krb5_context context
,
749 const krb5_config_section
*c
,
755 va_start(ap
, def_value
);
756 ret
= krb5_config_vget_int_default(context
, c
, def_value
, ap
);
761 int KRB5_LIB_FUNCTION
762 krb5_config_get_int (krb5_context context
,
763 const krb5_config_section
*c
,
769 ret
= krb5_config_vget_int (context
, c
, ap
);