2 * Copyright (c) 1997 - 2002 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("$Id: config_file.c,v 1.46 2002/09/10 19:04:55 joda Exp $");
39 static krb5_error_code parse_section(char *p, krb5_config_section **s,
40 krb5_config_section **res,
41 const char **error_message);
42 static krb5_error_code parse_binding(FILE *f, unsigned *lineno, char *p,
43 krb5_config_binding **b,
44 krb5_config_binding **parent,
45 const char **error_message);
46 static krb5_error_code parse_list(FILE *f, unsigned *lineno,
47 krb5_config_binding **parent,
48 const char **error_message);
50 static krb5_config_section *
51 get_entry(krb5_config_section **parent, const char *name, int type)
53 krb5_config_section **q;
55 for(q = parent; *q != NULL; q = &(*q)->next)
56 if(type == krb5_config_list &&
58 strcmp(name, (*q)->name) == 0)
60 *q = calloc(1, sizeof(**q));
63 (*q)->name = strdup(name);
65 if((*q)->name == NULL) {
83 * starting at the line in `p', storing the resulting structure in
84 * `s' and hooking it into `parent'.
85 * Store the error message in `error_message'.
88 static krb5_error_code
89 parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
90 const char **error_message)
93 krb5_config_section *tmp;
95 p1 = strchr (p + 1, ']');
97 *error_message = "missing ]";
98 return KRB5_CONFIG_BADFORMAT;
101 tmp = get_entry(parent, p + 1, krb5_config_list);
103 *error_message = "out of memory";
104 return KRB5_CONFIG_BADFORMAT;
111 * Parse a brace-enclosed list from `f', hooking in the structure at
113 * Store the error message in `error_message'.
117 parse_list(FILE *f, unsigned *lineno, krb5_config_binding **parent,
118 const char **error_message)
122 krb5_config_binding *b = NULL;
123 unsigned beg_lineno = *lineno;
125 while(fgets(buf, sizeof(buf), f) != NULL) {
129 if (buf[strlen(buf) - 1] == '\n')
130 buf[strlen(buf) - 1] = '\0';
132 while(isspace((unsigned char)*p))
134 if (*p == '#' || *p == ';' || *p == '\0')
136 while(isspace((unsigned char)*p))
142 ret = parse_binding (f, lineno, p, &b, parent, error_message);
146 *lineno = beg_lineno;
147 *error_message = "unclosed {";
148 return KRB5_CONFIG_BADFORMAT;
156 parse_binding(FILE *f, unsigned *lineno, char *p,
157 krb5_config_binding **b, krb5_config_binding **parent,
158 const char **error_message)
160 krb5_config_binding *tmp;
165 while (*p && *p != '=' && !isspace((unsigned char)*p))
168 *error_message = "missing =";
169 return KRB5_CONFIG_BADFORMAT;
172 while (isspace((unsigned char)*p))
175 *error_message = "missing =";
176 return KRB5_CONFIG_BADFORMAT;
179 while(isspace((unsigned char)*p))
183 tmp = get_entry(parent, p1, krb5_config_list);
185 *error_message = "out of memory";
186 return KRB5_CONFIG_BADFORMAT;
188 ret = parse_list (f, lineno, &tmp->u.list, error_message);
190 tmp = get_entry(parent, p1, krb5_config_string);
192 *error_message = "out of memory";
193 return KRB5_CONFIG_BADFORMAT;
197 while(p > p1 && isspace((unsigned char)*(p-1)))
200 tmp->u.string = strdup(p1);
207 * Parse the config file `fname', generating the structures into `res'
208 * returning error messages in `error_message'
211 static krb5_error_code
212 krb5_config_parse_file_debug (const char *fname,
213 krb5_config_section **res,
215 const char **error_message)
218 krb5_config_section *s;
219 krb5_config_binding *b;
221 krb5_error_code ret = 0;
226 f = fopen (fname, "r");
228 *error_message = "cannot open file";
231 while (fgets(buf, sizeof(buf), f) != NULL) {
235 if(buf[strlen(buf) - 1] == '\n')
236 buf[strlen(buf) - 1] = '\0';
238 while(isspace((unsigned char)*p))
240 if (*p == '#' || *p == ';')
243 ret = parse_section(p, &s, res, error_message);
248 } else if (*p == '}') {
249 *error_message = "unmatched }";
250 ret = EINVAL; /* XXX */
252 } else if(*p != '\0') {
253 ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message);
264 krb5_config_parse_file_multi (krb5_context context,
266 krb5_config_section **res)
272 ret = krb5_config_parse_file_debug (fname, res, &lineno, &str);
274 krb5_set_error_string (context, "%s:%u: %s", fname, lineno, str);
281 krb5_config_parse_file (krb5_context context,
283 krb5_config_section **res)
286 return krb5_config_parse_file_multi(context, fname, res);
289 #endif /* !HAVE_NETINFO */
292 free_binding (krb5_context context, krb5_config_binding *b)
294 krb5_config_binding *next_b;
298 if (b->type == krb5_config_string)
300 else if (b->type == krb5_config_list)
301 free_binding (context, b->u.list);
303 krb5_abortx(context, "unknown binding type (%d) in free_binding",
312 krb5_config_file_free (krb5_context context, krb5_config_section *s)
314 free_binding (context, s);
319 krb5_config_get_next (krb5_context context,
320 const krb5_config_section *c,
321 const krb5_config_binding **pointer,
328 va_start(args, type);
329 ret = krb5_config_vget_next (context, c, pointer, type, args);
335 vget_next(krb5_context context,
336 const krb5_config_binding *b,
337 const krb5_config_binding **pointer,
342 const char *p = va_arg(args, const char *);
344 if(strcmp(b->name, name) == 0) {
345 if(b->type == type && p == NULL) {
348 } else if(b->type == krb5_config_list && p != NULL) {
349 return vget_next(context, b->u.list, pointer, type, p, args);
358 krb5_config_vget_next (krb5_context context,
359 const krb5_config_section *c,
360 const krb5_config_binding **pointer,
364 const krb5_config_binding *b;
373 if (*pointer == NULL) {
374 /* first time here, walk down the tree looking for the right
376 p = va_arg(args, const char *);
379 return vget_next(context, c, pointer, type, p, args);
382 /* we were called again, so just look for more entries with the
383 same name and type */
384 for (b = (*pointer)->next; b != NULL; b = b->next) {
385 if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) {
394 krb5_config_get (krb5_context context,
395 const krb5_config_section *c,
402 va_start(args, type);
403 ret = krb5_config_vget (context, c, type, args);
409 krb5_config_vget (krb5_context context,
410 const krb5_config_section *c,
414 const krb5_config_binding *foo = NULL;
416 return krb5_config_vget_next (context, c, &foo, type, args);
419 const krb5_config_binding *
420 krb5_config_get_list (krb5_context context,
421 const krb5_config_section *c,
424 const krb5_config_binding *ret;
428 ret = krb5_config_vget_list (context, c, args);
433 const krb5_config_binding *
434 krb5_config_vget_list (krb5_context context,
435 const krb5_config_section *c,
438 return krb5_config_vget (context, c, krb5_config_list, args);
442 krb5_config_get_string (krb5_context context,
443 const krb5_config_section *c,
450 ret = krb5_config_vget_string (context, c, args);
456 krb5_config_vget_string (krb5_context context,
457 const krb5_config_section *c,
460 return krb5_config_vget (context, c, krb5_config_string, args);
464 krb5_config_vget_string_default (krb5_context context,
465 const krb5_config_section *c,
466 const char *def_value,
471 ret = krb5_config_vget_string (context, c, args);
478 krb5_config_get_string_default (krb5_context context,
479 const krb5_config_section *c,
480 const char *def_value,
486 va_start(args, def_value);
487 ret = krb5_config_vget_string_default (context, c, def_value, args);
493 krb5_config_vget_strings(krb5_context context,
494 const krb5_config_section *c,
497 char **strings = NULL;
499 const krb5_config_binding *b = NULL;
502 while((p = krb5_config_vget_next(context, c, &b,
503 krb5_config_string, args))) {
504 char *tmp = strdup(p);
509 s = strtok_r(tmp, " \t", &pos);
511 char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
515 strings[nstr] = strdup(s);
517 if(strings[nstr-1] == NULL)
519 s = strtok_r(NULL, " \t", &pos);
524 char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
528 strings[nstr] = NULL;
540 krb5_config_get_strings(krb5_context context,
541 const krb5_config_section *c,
547 ret = krb5_config_vget_strings(context, c, ap);
553 krb5_config_free_strings(char **strings)
564 krb5_config_vget_bool_default (krb5_context context,
565 const krb5_config_section *c,
566 krb5_boolean def_value,
570 str = krb5_config_vget_string (context, c, args);
573 if(strcasecmp(str, "yes") == 0 ||
574 strcasecmp(str, "true") == 0 ||
575 atoi(str)) return TRUE;
580 krb5_config_vget_bool (krb5_context context,
581 const krb5_config_section *c,
584 return krb5_config_vget_bool_default (context, c, FALSE, args);
588 krb5_config_get_bool_default (krb5_context context,
589 const krb5_config_section *c,
590 krb5_boolean def_value,
595 va_start(ap, def_value);
596 ret = krb5_config_vget_bool_default(context, c, def_value, ap);
602 krb5_config_get_bool (krb5_context context,
603 const krb5_config_section *c,
609 ret = krb5_config_vget_bool (context, c, ap);
615 krb5_config_vget_time_default (krb5_context context,
616 const krb5_config_section *c,
621 str = krb5_config_vget_string (context, c, args);
624 return parse_time (str, NULL);
628 krb5_config_vget_time (krb5_context context,
629 const krb5_config_section *c,
632 return krb5_config_vget_time_default (context, c, -1, args);
636 krb5_config_get_time_default (krb5_context context,
637 const krb5_config_section *c,
643 va_start(ap, def_value);
644 ret = krb5_config_vget_time_default(context, c, def_value, ap);
650 krb5_config_get_time (krb5_context context,
651 const krb5_config_section *c,
657 ret = krb5_config_vget_time (context, c, ap);
664 krb5_config_vget_int_default (krb5_context context,
665 const krb5_config_section *c,
670 str = krb5_config_vget_string (context, c, args);
676 l = strtol(str, &endptr, 0);
685 krb5_config_vget_int (krb5_context context,
686 const krb5_config_section *c,
689 return krb5_config_vget_int_default (context, c, -1, args);
693 krb5_config_get_int_default (krb5_context context,
694 const krb5_config_section *c,
700 va_start(ap, def_value);
701 ret = krb5_config_vget_int_default(context, c, def_value, ap);
707 krb5_config_get_int (krb5_context context,
708 const krb5_config_section *c,
714 ret = krb5_config_vget_int (context, c, ap);